<?php

/*
** Fishlib - a collection of utilities for db-driven applications in PHP
** Copyright (C) 2002  LTWD, LLC DBA The Madfish Group
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

require_once('fishbase.class.php');
class 
FishRequest extends FishBase
{
    var 
$agents = array(
        
'netscape' => 'Mozilla/4.7 [en] (Win98; U)'
        
'netscape4.0' => 'Mozilla/4.05 [en] (Win95; I)'
        
'ie' => 'Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)'
    
);

    function 
old_make_content($what)
    {
        if (!empty(
$what) && is_array($what))
        {
            
$pairs = array();
            foreach (
$what as $k => $v)
            {
                if (!
is_scalar($v) && $v !== NULL)
                {
                    
user_error(
                    
'Whoosp, k='.$k.' v is not a string: '.var_export($vTRUE)
                        ,  
E_USER_WARNING
                    
);
                    continue;
                }
                
$pairs[] = $k.'='.rawurlencode($v);
            }
            
$content implode('&'$pairs);
        }
        else
        {
            
$content $what;
        }
        return 
$content;
    }

    function 
make_content($value,$key=null)
    {
        
$outvalue null;
        
$type gettype($value);
        switch (
$type)
        {
            case 
'object':
                
$value get_object_vars($value);
            case 
'array':
                
$temp = array();
                foreach (
$value as $k => $v)
                {
                    if (
$key)
                        
$k $key rawurlencode("[{$k}]");
                    
$temp[] = FishRequest::make_content($v$k);
                }
                
$outvalue implode('&'$temp);
                break;
            case 
'boolean':
                
$value = (int)$value;
            case 
'string':
            case 
'integer':
            case 
'float':
            case 
'double':
            case 
'NULL':
                
$outvalue rawurlencode($value);
                if (
$key)
                    
$outvalue "{$key}={$outvalue}";
                break;
            default:
                
user_error(
                    
sprintf(
                        
"Illegal value for POST: value=[%s] key='%s'"
                        
var_export($valuetrue)
                        , 
$key
                    
)
                    , 
E_USER_ERROR
                
);
        }
        return 
$outvalue;
    }

    function 
get($where$what=NULL)
    {
        
$what FishRequest::make_content($what);
        
$url $where;
        if (
$what)
        {
            
$url $url .'?'.$what;
        }
        
ini_set('user_agent'$this->agents['netscape']);
        
$results['content'] = file_get_contents($url);
        
$results['header'] = FishUtil::array_key_value($GLOBALS'http_response_header');
        return 
$results;
    }

    function 
post($where$what=NULL$how='application/x-www-form-urlencoded')
    {
        
// $where should be a valid complete absolute URL,
        // but it pays to assume nothing...

        
preg_match('|^(.*)://|'$where$matches);
        
$scheme strtolower(FishUtil::array_key_value($matches,1,'http'));

        
$port NULL;
        
preg_match('|://([^/]+)|'$where$matches);
        
$host FishUtil::array_key_value($matches1FishUtil::array_key_value($_SERVER'HTTP_HOST'FishUtil::array_key_value($_SERVER'HOST'NULL)));
        if (
preg_match('/^(.*):(.*)$/'$host$matches))
        {
            
$host $matches[1];
            
$port $matches[2];
        }
        if (
$port === NULL)
        {
            if (
$scheme == 'ssl' || $scheme == 'https')
            {
                
$port 443;
            }
            else
            {
                
$port 80;
            }
        }

        
preg_match('|://[^/]+(.*)$|'$where$matches);
        
$url FishUtil::array_key_value($matches1$_SERVER['PHP_SELF']);

        if (
$port == 443 || $scheme == 'https' || $scheme == 'ssl')
        {
            
$socket 'ssl://'.$host;
        }
        else
        {
            
$socket $host;
        }
        
$errno NULL;
        
$errstr NULL;
        
$fp fsockopen($socket$port$errno$errstr);
        if (!
$fp)
        {
            
user_error(
                
"could not contact $socket $port: errno=$errno errstr=$errstr"
                
E_USER_ERROR
            
);
            return 
FALSE;
        }
        
$lines = array();
        
$lines[] = 'POST '.$url.' HTTP/1.1';
        
$lines[] = 'User-Agent: '.$this->agents['netscape'];
        
$lines[] = 'Host: '.$host;

        
$lines[] = 'Content-type: '.$how;

        
$content FishRequest::make_content($what);
        
$lines[] = 'Content-length: '.strlen($content);
        
$lines[] = '';
        
$lines[] = $content;

        
$request implode("\r\n"$lines);
        
fputs($fp$requeststrlen($request));

        
// now to get the results - this is just a tad wanky
        
$i 0;
        
$results '';

        
$headers = array();
        do
        {
            
$continue FALSE;
            do
            {
                
$new fgets($fp);
                
$new "$new";
                
$new trim($new);
                
$eof feof($fp);
                
$meta stream_get_meta_data($fp);
                if (!empty(
$new))
                {
                    if (
strstr($new':') !== FALSE)
                    {
                        
preg_match('/^([^:]*):[\s]*(.*)$/'$new$matches);
                        
$k = isset($matches[1]) ? $matches[1] : $new;
                        
$v = isset($matches[2]) ? $matches[2] : '';
                        
$headers[$k] = $v;
                    }
                    else
                    {
                        
$headers[$new] = '';
                        if (
preg_match('/^HTTP.*Continue/'$new))
                        {
                            
$continue TRUE;
                        }
                    }
                }
            }
            while (
$eof === FALSE && !empty($new) && $i 500);
        }
        while (
$continue === TRUE);
        
$content NULL;
        if (isset(
$headers['Content-Length']))
        {
            
$new fread($fp$headers['Content-Length']);
            
$new "$new";
            
$eof feof($fp);
            
$meta stream_get_meta_data($fp);
            
$content $new;
        }
        else
        {
            
// avoid this if we can, it gives a protocol error for SSL
            // - clearly there's a better way to handle it...
            // set_handler(E_WARNING, H_ALL, FALSE);
            
while ( $new fread($fp1024) )
            {
                
$new "$new";
                
$eof feof($fp);
                
$meta stream_get_meta_data($fp);
                
$content "{$content}{$new}";
            }
            
// pop_handler();
        
}
        
fclose($fp);

        
$results['headers'] = $headers;
        
$results['content'] = $content;

        return 
$results;
    }

    function 
force_download($filename$content=NULL)
    {

        if (
$content === NULL)
            
$content file_get_contents($filename);

        
// stupid browsers
        
if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== FALSE)
            
$mime_type 'application/notarealtype';
        elseif (
strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') !== FALSE)
            
$mime_type 'application/notarealtype';
        else
            
$mime_type 'application/octet-stream';

        
// headers
        
header("Content-Type: $mime_type");
        
header("Content-Disposition: attachment; filename=\"$filename\"");
        
header('Content-Transfer-Encoding: binary');
        
header('Expires: 0');

        
// not 100% sure of these, but don't seem to hurt and may keep various
        // browsers from cacheing the content
        
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        
header('Pragma: public');
        
header('Pragma: no-cache');

        
// content

        
print $content;

        
// because there's no point in returning from here
        
exit;
    }

}
?>