|
<?php |
|
/* |
|
* http.php |
|
* |
|
* @(#) $Header: /home/mlemos/cvsroot/http/http.php,v 1.79 2009/09/03 00:09:37 mlemos Exp $ |
|
* |
|
*/ |
|
|
|
class http_class |
|
{ |
|
var $host_name=""; |
|
var $host_port=0; |
|
var $proxy_host_name=""; |
|
var $proxy_host_port=80; |
|
var $socks_host_name = ''; |
|
var $socks_host_port = 1080; |
|
var $socks_version = '5'; |
|
|
|
var $protocol="http"; |
|
var $request_method="GET"; |
|
var $user_agent='httpclient (http://www.phpclasses.org/httpclient $Revision: 1.79 $)'; |
|
var $authentication_mechanism=""; |
|
var $user; |
|
var $password; |
|
var $realm; |
|
var $workstation; |
|
var $proxy_authentication_mechanism=""; |
|
var $proxy_user; |
|
var $proxy_password; |
|
var $proxy_realm; |
|
var $proxy_workstation; |
|
var $request_uri=""; |
|
var $request=""; |
|
var $request_headers=array(); |
|
var $request_user; |
|
var $request_password; |
|
var $request_realm; |
|
var $request_workstation; |
|
var $proxy_request_user; |
|
var $proxy_request_password; |
|
var $proxy_request_realm; |
|
var $proxy_request_workstation; |
|
var $request_body=""; |
|
var $request_arguments=array(); |
|
var $protocol_version="1.1"; |
|
var $timeout=0; |
|
var $data_timeout=0; |
|
var $debug=0; |
|
var $debug_response_body=1; |
|
var $html_debug=0; |
|
var $support_cookies=1; |
|
var $cookies=array(); |
|
var $error=""; |
|
var $exclude_address=""; |
|
var $follow_redirect=0; |
|
var $redirection_limit=5; |
|
var $response_status=""; |
|
var $response_message=""; |
|
var $file_buffer_length=8000; |
|
var $force_multipart_form_post=0; |
|
var $prefer_curl = 0; |
|
|
|
/* private variables - DO NOT ACCESS */ |
|
|
|
var $state="Disconnected"; |
|
var $use_curl=0; |
|
var $connection=0; |
|
var $content_length=0; |
|
var $response=""; |
|
var $read_response=0; |
|
var $read_length=0; |
|
var $request_host=""; |
|
var $next_token=""; |
|
var $redirection_level=0; |
|
var $chunked=0; |
|
var $remaining_chunk=0; |
|
var $last_chunk_read=0; |
|
var $months=array( |
|
"Jan"=>"01", |
|
"Feb"=>"02", |
|
"Mar"=>"03", |
|
"Apr"=>"04", |
|
"May"=>"05", |
|
"Jun"=>"06", |
|
"Jul"=>"07", |
|
"Aug"=>"08", |
|
"Sep"=>"09", |
|
"Oct"=>"10", |
|
"Nov"=>"11", |
|
"Dec"=>"12"); |
|
var $session=''; |
|
var $connection_close=0; |
|
|
|
/* Private methods - DO NOT CALL */ |
|
|
|
Function Tokenize($string,$separator="") |
|
{ |
|
if(!strcmp($separator,"")) |
|
{ |
|
$separator=$string; |
|
$string=$this->next_token; |
|
} |
|
for($character=0;$character<strlen($separator);$character++) |
|
{ |
|
if(GetType($position=strpos($string,$separator[$character]))=="integer") |
|
$found=(IsSet($found) ? min($found,$position) : $position); |
|
} |
|
if(IsSet($found)) |
|
{ |
|
$this->next_token=substr($string,$found+1); |
|
return(substr($string,0,$found)); |
|
} |
|
else |
|
{ |
|
$this->next_token=""; |
|
return($string); |
|
} |
|
} |
|
|
|
Function CookieEncode($value, $name) |
|
{ |
|
return($name ? str_replace("=", "%25", $value) : str_replace(";", "%3B", $value)); |
|
} |
|
|
|
Function SetError($error) |
|
{ |
|
return($this->error=$error); |
|
} |
|
|
|
Function SetPHPError($error, &$php_error_message) |
|
{ |
|
if(IsSet($php_error_message) |
|
&& strlen($php_error_message)) |
|
$error.=": ".$php_error_message; |
|
return($this->SetError($error)); |
|
} |
|
|
|
Function SetDataAccessError($error,$check_connection=0) |
|
{ |
|
$this->error=$error; |
|
if(!$this->use_curl |
|
&& function_exists("socket_get_status")) |
|
{ |
|
$status=socket_get_status($this->connection); |
|
if($status["timed_out"]) |
|
$this->error.=": data access time out"; |
|
elseif($status["eof"]) |
|
{ |
|
if($check_connection) |
|
$this->error=""; |
|
else |
|
$this->error.=": the server disconnected"; |
|
} |
|
} |
|
} |
|
|
|
Function OutputDebug($message) |
|
{ |
|
$message.="\n"; |
|
if($this->html_debug) |
|
$message=str_replace("\n","<br />\n",HtmlEntities($message)); |
|
echo $message; |
|
flush(); |
|
} |
|
|
|
Function GetLine() |
|
{ |
|
for($line="";;) |
|
{ |
|
if($this->use_curl) |
|
{ |
|
$eol=strpos($this->response,"\n",$this->read_response); |
|
$data=($eol ? substr($this->response,$this->read_response,$eol+1-$this->read_response) : ""); |
|
$this->read_response+=strlen($data); |
|
} |
|
else |
|
{ |
|
if(feof($this->connection)) |
|
{ |
|
$this->SetDataAccessError("reached the end of data while reading from the HTTP server connection"); |
|
return(0); |
|
} |
|
$data=fgets($this->connection,100); |
|
} |
|
if(GetType($data)!="string" |
|
|| strlen($data)==0) |
|
{ |
|
$this->SetDataAccessError("it was not possible to read line from the HTTP server"); |
|
return(0); |
|
} |
|
$line.=$data; |
|
$length=strlen($line); |
|
if($length |
|
&& !strcmp(substr($line,$length-1,1),"\n")) |
|
{ |
|
$length-=(($length>=2 && !strcmp(substr($line,$length-2,1),"\r")) ? 2 : 1); |
|
$line=substr($line,0,$length); |
|
if($this->debug) |
|
$this->OutputDebug("S $line"); |
|
return($line); |
|
} |
|
} |
|
} |
|
|
|
Function PutLine($line) |
|
{ |
|
if($this->debug) |
|
$this->OutputDebug("C $line"); |
|
if(!fputs($this->connection,$line."\r\n")) |
|
{ |
|
$this->SetDataAccessError("it was not possible to send a line to the HTTP server"); |
|
return(0); |
|
} |
|
return(1); |
|
} |
|
|
|
Function PutData($data) |
|
{ |
|
if(strlen($data)) |
|
{ |
|
if($this->debug) |
|
$this->OutputDebug('C '.$data); |
|
if(!fputs($this->connection,$data)) |
|
{ |
|
$this->SetDataAccessError("it was not possible to send data to the HTTP server"); |
|
return(0); |
|
} |
|
} |
|
return(1); |
|
} |
|
|
|
Function FlushData() |
|
{ |
|
if(!fflush($this->connection)) |
|
{ |
|
$this->SetDataAccessError("it was not possible to send data to the HTTP server"); |
|
return(0); |
|
} |
|
return(1); |
|
} |
|
|
|
Function ReadChunkSize() |
|
{ |
|
if($this->remaining_chunk==0) |
|
{ |
|
$debug=$this->debug; |
|
if(!$this->debug_response_body) |
|
$this->debug=0; |
|
$line=$this->GetLine(); |
|
$this->debug=$debug; |
|
if(GetType($line)!="string") |
|
return($this->SetError("4 could not read chunk start: ".$this->error)); |
|
$this->remaining_chunk=hexdec($line); |
|
} |
|
return(""); |
|
} |
|
|
|
Function ReadBytes($length) |
|
{ |
|
if($this->use_curl) |
|
{ |
|
$bytes=substr($this->response,$this->read_response,min($length,strlen($this->response)-$this->read_response)); |
|
$this->read_response+=strlen($bytes); |
|
if($this->debug |
|
&& $this->debug_response_body |
|
&& strlen($bytes)) |
|
$this->OutputDebug("S ".$bytes); |
|
} |
|
else |
|
{ |
|
if($this->chunked) |
|
{ |
|
for($bytes="",$remaining=$length;$remaining;) |
|
{ |
|
if(strlen($this->ReadChunkSize())) |
|
return(""); |
|
if($this->remaining_chunk==0) |
|
{ |
|
$this->last_chunk_read=1; |
|
break; |
|
} |
|
$ask=min($this->remaining_chunk,$remaining); |
|
$chunk=@fread($this->connection,$ask); |
|
$read=strlen($chunk); |
|
if($read==0) |
|
{ |
|
$this->SetDataAccessError("it was not possible to read data chunk from the HTTP server"); |
|
return(""); |
|
} |
|
if($this->debug |
|
&& $this->debug_response_body) |
|
$this->OutputDebug("S ".$chunk); |
|
$bytes.=$chunk; |
|
$this->remaining_chunk-=$read; |
|
$remaining-=$read; |
|
if($this->remaining_chunk==0) |
|
{ |
|
if(feof($this->connection)) |
|
return($this->SetError("reached the end of data while reading the end of data chunk mark from the HTTP server")); |
|
$data=@fread($this->connection,2); |
|
if(strcmp($data,"\r\n")) |
|
{ |
|
$this->SetDataAccessError("it was not possible to read end of data chunk from the HTTP server"); |
|
return(""); |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
$bytes=@fread($this->connection,$length); |
|
if(strlen($bytes)) |
|
{ |
|
if($this->debug |
|
&& $this->debug_response_body) |
|
$this->OutputDebug("S ".$bytes); |
|
} |
|
else |
|
$this->SetDataAccessError("it was not possible to read data from the HTTP server", $this->connection_close); |
|
} |
|
} |
|
return($bytes); |
|
} |
|
|
|
Function EndOfInput() |
|
{ |
|
if($this->use_curl) |
|
return($this->read_response>=strlen($this->response)); |
|
if($this->chunked) |
|
return($this->last_chunk_read); |
|
return(feof($this->connection)); |
|
} |
|
|
|
Function Resolve($domain, &$ip, $server_type) |
|
{ |
|
if(preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/',$domain)) |
|
$ip=$domain; |
|
else |
|
{ |
|
if($this->debug) |
|
$this->OutputDebug('Resolving '.$server_type.' server domain "'.$domain.'"...'); |
|
if(!strcmp($ip=@gethostbyname($domain),$domain)) |
|
$ip=""; |
|
} |
|
if(strlen($ip)==0 |
|
|| (strlen($this->exclude_address) |
|
&& !strcmp(@gethostbyname($this->exclude_address),$ip))) |
|
return($this->SetError("could not resolve the host domain \"".$domain."\"")); |
|
return(''); |
|
} |
|
|
|
Function Connect($host_name, $host_port, $ssl, $server_type = 'HTTP') |
|
{ |
|
$domain=$host_name; |
|
$port = $host_port; |
|
if(strlen($error = $this->Resolve($domain, $ip, $server_type))) |
|
return($error); |
|
if(strlen($this->socks_host_name)) |
|
{ |
|
switch($this->socks_version) |
|
{ |
|
case '4': |
|
$version = 4; |
|
break; |
|
case '5': |
|
$version = 5; |
|
break; |
|
default: |
|
return('it was not specified a supported SOCKS protocol version'); |
|
break; |
|
} |
|
$host_ip = $ip; |
|
$port = $this->socks_host_port; |
|
$host_server_type = $server_type; |
|
$server_type = 'SOCKS'; |
|
if(strlen($error = $this->Resolve($this->socks_host_name, $ip, $server_type))) |
|
return($error); |
|
} |
|
if($this->debug) |
|
$this->OutputDebug('Connecting to '.$server_type.' server IP '.$ip.' port '.$port.'...'); |
|
if($ssl) |
|
$ip="ssl://".$ip; |
|
if(($this->connection=($this->timeout ? @fsockopen($ip, $port, $errno, $error, $this->timeout) : @fsockopen($ip, $port, $errno)))==0) |
|
{ |
|
switch($errno) |
|
{ |
|
case -3: |
|
return($this->SetError("-3 socket could not be created")); |
|
case -4: |
|
return($this->SetError("-4 dns lookup on hostname \"".$host_name."\" failed")); |
|
case -5: |
|
return($this->SetError("-5 connection refused or timed ou |