1<?php 2/* 3 * http.php 4 * 5 * @(#) $Header: /opt2/ena/metal/http/http.php,v 1.90 2013/02/20 11:45:28 mlemos Exp $ 6 * 7 */ 8 9define('HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR', -1); 10define('HTTP_CLIENT_ERROR_NO_ERROR', 0); 11define('HTTP_CLIENT_ERROR_INVALID_SERVER_ADDRESS', 1); 12define('HTTP_CLIENT_ERROR_CANNOT_CONNECT', 2); 13define('HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE', 3); 14define('HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE', 4); 15define('HTTP_CLIENT_ERROR_PROTOCOL_FAILURE', 5); 16define('HTTP_CLIENT_ERROR_INVALID_PARAMETERS', 6); 17 18class http_class 19{ 20 var $host_name=""; 21 var $host_port=0; 22 var $proxy_host_name=""; 23 var $proxy_host_port=80; 24 var $socks_host_name = ''; 25 var $socks_host_port = 1080; 26 var $socks_version = '5'; 27 28 var $protocol="http"; 29 var $request_method="GET"; 30 var $user_agent='httpclient (http://www.phpclasses.org/httpclient $Revision: 1.90 $)'; 31 var $accept=''; 32 var $authentication_mechanism=""; 33 var $user; 34 var $password; 35 var $realm; 36 var $workstation; 37 var $proxy_authentication_mechanism=""; 38 var $proxy_user; 39 var $proxy_password; 40 var $proxy_realm; 41 var $proxy_workstation; 42 var $request_uri=""; 43 var $request=""; 44 var $request_headers=array(); 45 var $request_user; 46 var $request_password; 47 var $request_realm; 48 var $request_workstation; 49 var $proxy_request_user; 50 var $proxy_request_password; 51 var $proxy_request_realm; 52 var $proxy_request_workstation; 53 var $request_body=""; 54 var $request_arguments=array(); 55 var $protocol_version="1.1"; 56 var $timeout=0; 57 var $data_timeout=0; 58 var $debug=0; 59 var $log_debug=0; 60 var $debug_response_body=1; 61 var $html_debug=0; 62 var $support_cookies=1; 63 var $cookies=array(); 64 var $error=""; 65 var $error_code = HTTP_CLIENT_ERROR_NO_ERROR; 66 var $exclude_address=""; 67 var $follow_redirect=0; 68 var $redirection_limit=5; 69 var $response_status=""; 70 var $response_message=""; 71 var $file_buffer_length=8000; 72 var $force_multipart_form_post=0; 73 var $prefer_curl = 0; 74 var $keep_alive = 1; 75 var $sasl_authenticate = 1; 76 77 /* private variables - DO NOT ACCESS */ 78 79 var $state="Disconnected"; 80 var $use_curl=0; 81 var $connection=0; 82 var $content_length=0; 83 var $response=""; 84 var $read_response=0; 85 var $read_length=0; 86 var $request_host=""; 87 var $next_token=""; 88 var $redirection_level=0; 89 var $chunked=0; 90 var $remaining_chunk=0; 91 var $last_chunk_read=0; 92 var $months=array( 93 "Jan"=>"01", 94 "Feb"=>"02", 95 "Mar"=>"03", 96 "Apr"=>"04", 97 "May"=>"05", 98 "Jun"=>"06", 99 "Jul"=>"07", 100 "Aug"=>"08", 101 "Sep"=>"09", 102 "Oct"=>"10", 103 "Nov"=>"11", 104 "Dec"=>"12"); 105 var $session=''; 106 var $connection_close=0; 107 var $force_close = 0; 108 var $connected_host = ''; 109 var $connected_port = -1; 110 var $connected_ssl = 0; 111 112 /* Private methods - DO NOT CALL */ 113 114 Function Tokenize($string,$separator="") 115 { 116 if(!strcmp($separator,"")) 117 { 118 $separator=$string; 119 $string=$this->next_token; 120 } 121 for($character=0;$character<strlen($separator);$character++) 122 { 123 if(GetType($position=strpos($string,$separator[$character]))=="integer") 124 $found=(IsSet($found) ? min($found,$position) : $position); 125 } 126 if(IsSet($found)) 127 { 128 $this->next_token=substr($string,$found+1); 129 return(substr($string,0,$found)); 130 } 131 else 132 { 133 $this->next_token=""; 134 return($string); 135 } 136 } 137 138 Function CookieEncode($value, $name) 139 { 140 return($name ? str_replace("=", "%25", $value) : str_replace(";", "%3B", $value)); 141 } 142 143 Function SetError($error, $error_code = HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR) 144 { 145 $this->error_code = $error_code; 146 return($this->error=$error); 147 } 148 149 Function SetPHPError($error, &$php_error_message, $error_code = HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR) 150 { 151 if(IsSet($php_error_message) 152 && strlen($php_error_message)) 153 $error.=": ".$php_error_message; 154 return($this->SetError($error, $error_code)); 155 } 156 157 Function SetDataAccessError($error,$check_connection=0) 158 { 159 $this->error=$error; 160 $this->error_code = HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE; 161 if(!$this->use_curl 162 && function_exists("socket_get_status")) 163 { 164 $status=socket_get_status($this->connection); 165 if($status["timed_out"]) 166 $this->error.=": data access time out"; 167 elseif($status["eof"]) 168 { 169 if($check_connection) 170 $this->error=""; 171 else 172 $this->error.=": the server disconnected"; 173 } 174 } 175 } 176 177 Function OutputDebug($message) 178 { 179 if($this->log_debug) 180 error_log($message); 181 else 182 { 183 $message.="\n"; 184 if($this->html_debug) 185 $message=str_replace("\n","<br />\n",HtmlEntities($message)); 186 echo $message; 187 flush(); 188 } 189 } 190 191 Function GetLine() 192 { 193 for($line="";;) 194 { 195 if($this->use_curl) 196 { 197 $eol=strpos($this->response,"\n",$this->read_response); 198 $data=($eol ? substr($this->response,$this->read_response,$eol+1-$this->read_response) : ""); 199 $this->read_response+=strlen($data); 200 } 201 else 202 { 203 if(feof($this->connection)) 204 { 205 $this->SetDataAccessError("reached the end of data while reading from the HTTP server connection"); 206 return(0); 207 } 208 $data=fgets($this->connection,100); 209 } 210 if(GetType($data)!="string" 211 || strlen($data)==0) 212 { 213 $this->SetDataAccessError("it was not possible to read line from the HTTP server"); 214 return(0); 215 } 216 $line.=$data; 217 $length=strlen($line); 218 if($length 219 && !strcmp(substr($line,$length-1,1),"\n")) 220 { 221 $length-=(($length>=2 && !strcmp(substr($line,$length-2,1),"\r")) ? 2 : 1); 222 $line=substr($line,0,$length); 223 if($this->debug) 224 $this->OutputDebug("S $line"); 225 return($line); 226 } 227 } 228 } 229 230 Function PutLine($line) 231 { 232 if($this->debug) 233 $this->OutputDebug("C $line"); 234 if(!fputs($this->connection,$line."\r\n")) 235 { 236 $this->SetDataAccessError("it was not possible to send a line to the HTTP server"); 237 return(0); 238 } 239 return(1); 240 } 241 242 Function PutData($data) 243 { 244 if(strlen($data)) 245 { 246 if($this->debug) 247 $this->OutputDebug('C '.$data); 248 if(!fputs($this->connection,$data)) 249 { 250 $this->SetDataAccessError("it was not possible to send data to the HTTP server"); 251 return(0); 252 } 253 } 254 return(1); 255 } 256 257 Function FlushData() 258 { 259 if(!fflush($this->connection)) 260 { 261 $this->SetDataAccessError("it was not possible to send data to the HTTP server"); 262 return(0); 263 } 264 return(1); 265 } 266 267 Function ReadChunkSize() 268 { 269 if($this->remaining_chunk==0) 270 { 271 $debug=$this->debug; 272 if(!$this->debug_response_body) 273 $this->debug=0; 274 $line=$this->GetLine(); 275 $this->debug=$debug; 276 if(GetType($line)!="string") 277 return($this->SetError("could not read chunk start: ".$this->error, $this->error_code)); 278 $this->remaining_chunk=hexdec($line); 279 if($this->remaining_chunk == 0) 280 { 281 if(!$this->debug_response_body) 282 $this->debug=0; 283 $line=$this->GetLine(); 284 $this->debug=$debug; 285 if(GetType($line)!="string") 286 return($this->SetError("could not read chunk end: ".$this->error, $this->error_code)); 287 } 288 } 289 return(""); 290 } 291 292 Function ReadBytes($length) 293 { 294 if($this->use_curl) 295 { 296 $bytes=substr($this->response,$this->read_response,min($length,strlen($this->response)-$this->read_response)); 297 $this->read_response+=strlen($bytes); 298 if($this->debug 299 && $this->debug_response_body 300 && strlen($bytes)) 301 $this->OutputDebug("S ".$bytes); 302 } 303 else 304 { 305 if($this->chunked) 306 { 307 for($bytes="",$remaining=$length;$remaining;) 308 { 309 if(strlen($this->ReadChunkSize())) 310 return(""); 311 if($this->remaining_chunk==0) 312 { 313 $this->last_chunk_read=1; 314 break; 315 } 316 $ask=min($this->remaining_chunk,$remaining); 317 $chunk=@fread($this->connection,$ask); 318 $read=strlen($chunk); 319 if($read==0) 320 { 321 $this->SetDataAccessError("it was not possible to read data chunk from the HTTP server"); 322 return(""); 323 } 324 if($this->debug 325 && $this->debug_response_body) 326 $this->OutputDebug("S ".$chunk); 327 $bytes.=$chunk; 328 $this->remaining_chunk-=$read; 329 $remaining-=$read; 330 if($this->remaining_chunk==0) 331 { 332 if(feof($this->connection)) 333 return($this->SetError("reached the end of data while reading the end of data chunk mark from the HTTP server", HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); 334 $data=@fread($this->connection,2); 335 if(strcmp($data,"\r\n")) 336 { 337 $this->SetDataAccessError("it was not possible to read end of data chunk from the HTTP server"); 338 return(""); 339 } 340 } 341 } 342 } 343 else 344 { 345 $bytes=@fread($this->connection,$length); 346 if(strlen($bytes)) 347 { 348 if($this->debug 349 && $this->debug_response_body) 350 $this->OutputDebug("S ".$bytes); 351 } 352 else 353 $this->SetDataAccessError("it was not possible to read data from the HTTP server", $this->connection_close); 354 } 355 } 356 return($bytes); 357 } 358 359 Function EndOfInput() 360 { 361 if($this->use_curl) 362 return($this->read_response>=strlen($this->response)); 363 if($this->chunked) 364 return($this->last_chunk_read); 365 if($this->content_length_set) 366 return($this->content_length <= $this->read_length); 367 return(feof($this->connection)); 368 } 369 370 Function Resolve($domain, &$ip, $server_type) 371 { 372 if(preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/',$domain)) 373 $ip=$domain; 374 else 375 { 376 if($this->debug) 377 $this->OutputDebug('Resolving '.$server_type.' server domain "'.$domain.'"...'); 378 if(!strcmp($ip=@gethostbyname($domain),$domain)) 379 $ip=""; 380 } 381 if(strlen($ip)==0 382 || (strlen($this->exclude_address) 383 && !strcmp(@gethostbyname($this->exclude_address),$ip))) 384 return($this->SetError("could not resolve the host domain \"".$domain."\"", HTTP_CLIENT_ERROR_INVALID_SERVER_ADDRESS)); 385 return(''); 386 } 387 388 Function Connect($host_name, $host_port, $ssl, $server_type = 'HTTP') 389 { 390 $domain=$host_name; 391 $port = $host_port; 392 if(strlen($error = $this->Resolve($domain, $ip, $server_type))) 393 return($error); 394 if(strlen($this->socks_host_name)) 395 { 396 switch($this->socks_version) 397 { 398 case '4': 399 $version = 4; 400 break; 401 case '5': 402 $version = 5; 403 break; 404 default: 405 return('it was not specified a supported SOCKS protocol version'); 406 break; 407 } 408 $host_ip = $ip; 409 $port = $this->socks_host_port; 410 $host_server_type = $server_type; 411 $server_type = 'SOCKS'; 412 if(strlen($error = $this->Resolve($this->socks_host_name, $ip, $server_type))) 413 return($error); 414 } 415 if($this->debug) 416 $this->OutputDebug('Connecting to '.$server_type.' server IP '.$ip.' port '.$port.'...'); 417 if($ssl) 418 $ip="ssl://".$host_name; 419 if(($this->connection=($this->timeout ? @fsockopen($ip, $port, $errno, $error, $this->timeout) : @fsockopen($ip, $port, $errno)))==0) 420 { 421 $error_code = HTTP_CLIENT_ERROR_CANNOT_CONNECT; 422 switch($errno) 423 { 424 case -3: 425 return($this->SetError("socket could not be created", $error_code)); 426 case -4: 427 return($this->SetError("dns lookup on hostname \"".$host_name."\" failed", $error_code)); 428 case -5: 429 return($this->SetError("connection refused or timed out", $error_code)); 430 case -6: 431 return($this->SetError("fdopen() call failed", $error_code)); 432 case -7: 433 return($this->SetError("setvbuf() call failed", $error_code)); 434 default: 435 return($this->SetPHPError($errno." could not connect to the host \"".$host_name."\"",$php_errormsg, $error_code)); 436 } 437 } 438 else 439 { 440 if($this->data_timeout 441 && function_exists("socket_set_timeout")) 442 socket_set_timeout($this->connection,$this->data_timeout,0); 443 if(strlen($this->socks_host_name)) 444 { 445 if($this->debug) 446 $this->OutputDebug('Connected to the SOCKS server '.$this->socks_host_name); 447 $send_error = 'it was not possible to send data to the SOCKS server'; 448 $receive_error = 'it was not possible to receive data from the SOCKS server'; 449 switch($version) 450 { 451 case 4: 452 $command = 1; 453 $user = ''; 454 if(!fputs($this->connection, chr($version).chr($command).pack('nN', $host_port, ip2long($host_ip)).$user.Chr(0))) 455 $error = $this->SetDataAccessError($send_error); 456 else 457 { 458 $response = fgets($this->connection, 9); 459 if(strlen($response) != 8) 460 $error = $this->SetDataAccessError($receive_error); 461 else 462 { 463 $socks_errors = array( 464 "\x5a"=>'', 465 "\x5b"=>'request rejected', 466 "\x5c"=>'request failed because client is not running identd (or not reachable from the server)', 467 "\x5d"=>'request failed because client\'s identd could not confirm the user ID string in the request', 468 ); 469 $error_code = $response[1]; 470 $error = (IsSet($socks_errors[$error_code]) ? $socks_errors[$error_code] : 'unknown'); 471 if(strlen($error)) 472 $error = 'SOCKS error: '.$error; 473 } 474 } 475 break; 476 case 5: 477 if($this->debug) 478 $this->OutputDebug('Negotiating the authentication method ...'); 479 $methods = 1; 480 $method = 0; 481 if(!fputs($this->connection, chr($version).chr($methods).chr($method))) 482 $error = $this->SetDataAccessError($send_error); 483 else 484 { 485 $response = fgets($this->connection, 3); 486 if(strlen($response) != 2) 487 $error = $this->SetDataAccessError($receive_error); 488 elseif(Ord($response[1]) != $method) 489 $error = 'the SOCKS server requires an authentication method that is not yet supported'; 490 else 491 { 492 if($this->debug) 493 $this->OutputDebug('Connecting to '.$host_server_type.' server IP '.$host_ip.' port '.$host_port.'...'); 494 $command = 1; 495 $address_type = 1; 496 if(!fputs($this->connection, chr($version).chr($command)."\x00".chr($address_type).pack('Nn', ip2long($host_ip), $host_port))) 497 $error = $this->SetDataAccessError($send_error); 498 else 499 { 500 $response = fgets($this->connection, 11); 501 if(strlen($response) != 10) 502 $error = $this->SetDataAccessError($receive_error); 503 else 504 { 505 $socks_errors = array( 506 "\x00"=>'', 507 "\x01"=>'general SOCKS server failure', 508 "\x02"=>'connection not allowed by ruleset', 509 "\x03"=>'Network unreachable', 510 "\x04"=>'Host unreachable', 511 "\x05"=>'Connection refused', 512 "\x06"=>'TTL expired', 513 "\x07"=>'Command not supported', 514 "\x08"=>'Address type not supported' 515 ); 516 $error_code = $response[1]; 517 $error = (IsSet($socks_errors[$error_code]) ? $socks_errors[$error_code] : 'unknown'); 518 if(strlen($error)) 519 $error = 'SOCKS error: '.$error; 520 } 521 } 522 } 523 } 524 break; 525 default: 526 $error = 'support for SOCKS protocol version '.$this->socks_version.' is not yet implemented'; 527 break; 528 } 529 if(strlen($error)) 530 { 531 fclose($this->connection); 532 return($error); 533 } 534 } 535 if($this->debug) 536 $this->OutputDebug("Connected to $host_name"); 537 if(strlen($this->proxy_host_name) 538 && !strcmp(strtolower($this->protocol), 'https')) 539 { 540 if(function_exists('stream_socket_enable_crypto') 541 && in_array('ssl', stream_get_transports())) 542 $this->state = "ConnectedToProxy"; 543 else 544 { 545 $this->OutputDebug("It is not possible to start SSL after connecting to the proxy server. If the proxy refuses to forward the SSL request, you may need to upgrade to PHP 5.1 or later with OpenSSL support enabled."); 546 $this->state="Connected"; 547 } 548 } 549 else 550 $this->state="Connected"; 551 return(""); 552 } 553 } 554 555 Function Disconnect() 556 { 557 if($this->debug) 558 $this->OutputDebug("Disconnected from ".$this->connected_host); 559 if($this->use_curl) 560 { 561 curl_close($this->connection); 562 $this->response=""; 563 } 564 else 565 fclose($this->connection); 566 $this->state="Disconnected"; 567 return(""); 568 } 569 570 /* Public methods */ 571 572 Function GetRequestArguments($url, &$arguments) 573 { 574 $this->error = ''; 575 $this->error_code = HTTP_CLIENT_ERROR_NO_ERROR; 576 $arguments=array(); 577 $url = str_replace(' ', '%20', $url); 578 $parameters=@parse_url($url); 579 if(!$parameters) 580 return($this->SetError("it was not specified a valid URL", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 581 if(!IsSet($parameters["scheme"])) 582 return($this->SetError("it was not specified the protocol type argument", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 583 switch(strtolower($parameters["scheme"])) 584 { 585 case "http": 586 case "https": 587 $arguments["Protocol"]=$parameters["scheme"]; 588 break; 589 default: 590 return($parameters["scheme"]." connection scheme is not yet supported"); 591 } 592 if(!IsSet($parameters["host"])) 593 return($this->SetError("it was not specified the connection host argument", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 594 $arguments["HostName"]=$parameters["host"]; 595 $arguments["Headers"]=array("Host"=>$parameters["host"].(IsSet($parameters["port"]) ? ":".$parameters["port"] : "")); 596 if(IsSet($parameters["user"])) 597 { 598 $arguments["AuthUser"]=UrlDecode($parameters["user"]); 599 if(!IsSet($parameters["pass"])) 600 $arguments["AuthPassword"]=""; 601 } 602 if(IsSet($parameters["pass"])) 603 { 604 if(!IsSet($parameters["user"])) 605 $arguments["AuthUser"]=""; 606 $arguments["AuthPassword"]=UrlDecode($parameters["pass"]); 607 } 608 if(IsSet($parameters["port"])) 609 { 610 if(strcmp($parameters["port"],strval(intval($parameters["port"])))) 611 return($this->SetError("it was not specified a valid connection host argument", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 612 $arguments["HostPort"]=intval($parameters["port"]); 613 } 614 else 615 $arguments["HostPort"]=0; 616 $arguments["RequestURI"]=(IsSet($parameters["path"]) ? $parameters["path"] : "/").(IsSet($parameters["query"]) ? "?".$parameters["query"] : ""); 617 if(strlen($this->user_agent)) 618 $arguments["Headers"]["User-Agent"]=$this->user_agent; 619 if(strlen($this->accept)) 620 $arguments["Headers"]["Accept"]=$this->accept; 621 return(""); 622 } 623 624 Function Open($arguments) 625 { 626 if(strlen($this->error)) 627 return($this->error); 628 $error_code = HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR; 629 if(IsSet($arguments["HostName"])) 630 $this->host_name=$arguments["HostName"]; 631 if(IsSet($arguments["HostPort"])) 632 $this->host_port=$arguments["HostPort"]; 633 if(IsSet($arguments["ProxyHostName"])) 634 $this->proxy_host_name=$arguments["ProxyHostName"]; 635 if(IsSet($arguments["ProxyHostPort"])) 636 $this->proxy_host_port=$arguments["ProxyHostPort"]; 637 if(IsSet($arguments["SOCKSHostName"])) 638 $this->socks_host_name=$arguments["SOCKSHostName"]; 639 if(IsSet($arguments["SOCKSHostPort"])) 640 $this->socks_host_port=$arguments["SOCKSHostPort"]; 641 if(IsSet($arguments["SOCKSVersion"])) 642 $this->socks_version=$arguments["SOCKSVersion"]; 643 if(IsSet($arguments["Protocol"])) 644 $this->protocol=$arguments["Protocol"]; 645 switch(strtolower($this->protocol)) 646 { 647 case "http": 648 $default_port=80; 649 break; 650 case "https": 651 $default_port=443; 652 break; 653 default: 654 return($this->SetError("it was not specified a valid connection protocol", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 655 } 656 if(strlen($this->proxy_host_name)==0) 657 { 658 if(strlen($this->host_name)==0) 659 return($this->SetError("it was not specified a valid hostname", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 660 $host_name=$this->host_name; 661 $host_port=($this->host_port ? $this->host_port : $default_port); 662 $server_type = 'HTTP'; 663 } 664 else 665 { 666 $host_name=$this->proxy_host_name; 667 $host_port=$this->proxy_host_port; 668 $server_type = 'HTTP proxy'; 669 } 670 $ssl=(strtolower($this->protocol)=="https" && strlen($this->proxy_host_name)==0); 671 if($ssl 672 && strlen($this->socks_host_name)) 673 return($this->SetError('establishing SSL connections via a SOCKS server is not yet supported', HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 674 $this->use_curl=($ssl && $this->prefer_curl && function_exists("curl_init")); 675 switch($this->state) 676 { 677 case 'Connected': 678 if(!strcmp($host_name, $this->connected_host) 679 && intval($host_port) == $this->connected_port 680 && intval($ssl) == $this->connected_ssl) 681 { 682 if($this->debug) 683 $this->OutputDebug("Reusing connection to ".$this->connected_host); 684 return(''); 685 } 686 if(strlen($error = $this->Disconnect())) 687 return($error); 688 case "Disconnected": 689 break; 690 default: 691 return("1 already connected"); 692 } 693 if($this->debug) 694 $this->OutputDebug("Connecting to ".$this->host_name); 695 if($this->use_curl) 696 { 697 $error=(($this->connection=curl_init($this->protocol."://".$this->host_name.($host_port==$default_port ? "" : ":".strval($host_port))."/")) ? "" : "Could not initialize a CURL session"); 698 if(strlen($error)==0) 699 { 700 if(IsSet($arguments["SSLCertificateFile"])) 701 curl_setopt($this->connection,CURLOPT_SSLCERT,$arguments["SSLCertificateFile"]); 702 if(IsSet($arguments["SSLCertificatePassword"])) 703 curl_setopt($this->connection,CURLOPT_SSLCERTPASSWD,$arguments["SSLCertificatePassword"]); 704 if(IsSet($arguments["SSLKeyFile"])) 705 curl_setopt($this->connection,CURLOPT_SSLKEY,$arguments["SSLKeyFile"]); 706 if(IsSet($arguments["SSLKeyPassword"])) 707 curl_setopt($this->connection,CURLOPT_SSLKEYPASSWD,$arguments["SSLKeyPassword"]); 708 } 709 $this->state="Connected"; 710 } 711 else 712 { 713 $error=""; 714 if(strlen($this->proxy_host_name) 715 && (IsSet($arguments["SSLCertificateFile"]) 716 || IsSet($arguments["SSLCertificateFile"]))) 717 $error="establishing SSL connections using certificates or private keys via non-SSL proxies is not supported"; 718 else 719 { 720 if($ssl) 721 { 722 if(IsSet($arguments["SSLCertificateFile"])) 723 $error="establishing SSL connections using certificates is only supported when the cURL extension is enabled"; 724 elseif(IsSet($arguments["SSLKeyFile"])) 725 $error="establishing SSL connections using a private key is only supported when the cURL extension is enabled"; 726 else 727 { 728 $version=explode(".",function_exists("phpversion") ? phpversion() : "3.0.7"); 729 $php_version=intval($version[0])*1000000+intval($version[1])*1000+intval($version[2]); 730 if($php_version<4003000) 731 $error="establishing SSL connections requires at least PHP version 4.3.0 or having the cURL extension enabled"; 732 elseif(!function_exists("extension_loaded") 733 || !extension_loaded("openssl")) 734 $error="establishing SSL connections requires the OpenSSL extension enabled"; 735 } 736 } 737 if(strlen($error)==0) 738 { 739 $error=$this->Connect($host_name, $host_port, $ssl, $server_type); 740 $error_code = $this->error_code; 741 } 742 } 743 } 744 if(strlen($error)) 745 return($this->SetError($error, $error_code)); 746 $this->session=md5(uniqid("")); 747 $this->connected_host = $host_name; 748 $this->connected_port = intval($host_port); 749 $this->connected_ssl = intval($ssl); 750 return(""); 751 } 752 753 Function Close($force = 0) 754 { 755 if($this->state=="Disconnected") 756 return("1 already disconnected"); 757 if(!$this->force_close 758 && $this->keep_alive 759 && !$force 760 && $this->state == 'ResponseReceived') 761 { 762 if($this->debug) 763 $this->OutputDebug('Keeping the connection alive to '.$this->connected_host); 764 $this->state = 'Connected'; 765 return(''); 766 } 767 return($this->Disconnect()); 768 } 769 770 Function PickCookies(&$cookies,$secure) 771 { 772 if(IsSet($this->cookies[$secure])) 773 { 774 $now=gmdate("Y-m-d H-i-s"); 775 for($domain=0,Reset($this->cookies[$secure]);$domain<count($this->cookies[$secure]);Next($this->cookies[$secure]),$domain++) 776 { 777 $domain_pattern=Key($this->cookies[$secure]); 778 $match=strlen($this->request_host)-strlen($domain_pattern); 779 if($match>=0 780 && !strcmp($domain_pattern,substr($this->request_host,$match)) 781 && ($match==0 782 || $domain_pattern[0]=="." 783 || $this->request_host[$match-1]==".")) 784 { 785 for(Reset($this->cookies[$secure][$domain_pattern]),$path_part=0;$path_part<count($this->cookies[$secure][$domain_pattern]);Next($this->cookies[$secure][$domain_pattern]),$path_part++) 786 { 787 $path=Key($this->cookies[$secure][$domain_pattern]); 788 if(strlen($this->request_uri)>=strlen($path) 789 && substr($this->request_uri,0,strlen($path))==$path) 790 { 791 for(Reset($this->cookies[$secure][$domain_pattern][$path]),$cookie=0;$cookie<count($this->cookies[$secure][$domain_pattern][$path]);Next($this->cookies[$secure][$domain_pattern][$path]),$cookie++) 792 { 793 $cookie_name=Key($this->cookies[$secure][$domain_pattern][$path]); 794 $expires=$this->cookies[$secure][$domain_pattern][$path][$cookie_name]["expires"]; 795 if($expires=="" 796 || strcmp($now,$expires)<0) 797 $cookies[$cookie_name]=$this->cookies[$secure][$domain_pattern][$path][$cookie_name]; 798 } 799 } 800 } 801 } 802 } 803 } 804 } 805 806 Function GetFileDefinition($file, &$definition) 807 { 808 $name=""; 809 if(IsSet($file["FileName"])) 810 $name=basename($file["FileName"]); 811 if(IsSet($file["Name"])) 812 $name=$file["Name"]; 813 if(strlen($name)==0) 814 return("it was not specified the file part name"); 815 if(IsSet($file["Content-Type"])) 816 { 817 $content_type=$file["Content-Type"]; 818 $type=$this->Tokenize(strtolower($content_type),"/"); 819 $sub_type=$this->Tokenize(""); 820 switch($type) 821 { 822 case "text": 823 case "image": 824 case "audio": 825 case "video": 826 case "application": 827 case "message": 828 break; 829 case "automatic": 830 switch($sub_type) 831 { 832 case "name": 833 switch(GetType($dot=strrpos($name,"."))=="integer" ? strtolower(substr($name,$dot)) : "") 834 { 835 case ".xls": 836 $content_type="application/excel"; 837 break; 838 case ".hqx": 839 $content_type="application/macbinhex40"; 840 break; 841 case ".doc": 842 case ".dot": 843 case ".wrd": 844 $content_type="application/msword"; 845 break; 846 case ".pdf": 847 $content_type="application/pdf"; 848 break; 849 case ".pgp": 850 $content_type="application/pgp"; 851 break; 852 case ".ps": 853 case ".eps": 854 case ".ai": 855 $content_type="application/postscript"; 856 break; 857 case ".ppt": 858 $content_type="application/powerpoint"; 859 break; 860 case ".rtf": 861 $content_type="application/rtf"; 862 break; 863 case ".tgz": 864 case ".gtar": 865 $content_type="application/x-gtar"; 866 break; 867 case ".gz": 868 $content_type="application/x-gzip"; 869 break; 870 case ".php": 871 case ".php3": 872 $content_type="application/x-httpd-php"; 873 break; 874 case ".js": 875 $content_type="application/x-javascript"; 876 break; 877 case ".ppd": 878 case ".psd": 879 $content_type="application/x-photoshop"; 880 break; 881 case ".swf": 882 case ".swc": 883 case ".rf": 884 $content_type="application/x-shockwave-flash"; 885 break; 886 case ".tar": 887 $content_type="application/x-tar"; 888 break; 889 case ".zip": 890 $content_type="application/zip"; 891 break; 892 case ".mid": 893 case ".midi": 894 case ".kar": 895 $content_type="audio/midi"; 896 break; 897 case ".mp2": 898 case ".mp3": 899 case ".mpga": 900 $content_type="audio/mpeg"; 901 break; 902 case ".ra": 903 $content_type="audio/x-realaudio"; 904 break; 905 case ".wav": 906 $content_type="audio/wav"; 907 break; 908 case ".bmp": 909 $content_type="image/bitmap"; 910 break; 911 case ".gif": 912 $content_type="image/gif"; 913 break; 914 case ".iff": 915 $content_type="image/iff"; 916 break; 917 case ".jb2": 918 $content_type="image/jb2"; 919 break; 920 case ".jpg": 921 case ".jpe": 922 case ".jpeg": 923 $content_type="image/jpeg"; 924 break; 925 case ".jpx": 926 $content_type="image/jpx"; 927 break; 928 case ".png": 929 $content_type="image/png"; 930 break; 931 case ".tif": 932 case ".tiff": 933 $content_type="image/tiff"; 934 break; 935 case ".wbmp": 936 $content_type="image/vnd.wap.wbmp"; 937 break; 938 case ".xbm": 939 $content_type="image/xbm"; 940 break; 941 case ".css": 942 $content_type="text/css"; 943 break; 944 case ".txt": 945 $content_type="text/plain"; 946 break; 947 case ".htm": 948 case ".html": 949 $content_type="text/html"; 950 break; 951 case ".xml": 952 $content_type="text/xml"; 953 break; 954 case ".mpg": 955 case ".mpe": 956 case ".mpeg": 957 $content_type="video/mpeg"; 958 break; 959 case ".qt": 960 case ".mov": 961 $content_type="video/quicktime"; 962 break; 963 case ".avi": 964 $content_type="video/x-ms-video"; 965 break; 966 case ".eml": 967 $content_type="message/rfc822"; 968 break; 969 default: 970 $content_type="application/octet-stream"; 971 break; 972 } 973 break; 974 default: 975 return($content_type." is not a supported automatic content type detection method"); 976 } 977 break; 978 default: 979 return($content_type." is not a supported file content type"); 980 } 981 } 982 else 983 $content_type="application/octet-stream"; 984 $definition=array( 985 "Content-Type"=>$content_type, 986 "NAME"=>$name 987 ); 988 if(IsSet($file["FileName"])) 989 { 990 if(GetType($length=@filesize($file["FileName"]))!="integer") 991 { 992 $error="it was not possible to determine the length of the file ".$file["FileName"]; 993 if(IsSet($php_errormsg) 994 && strlen($php_errormsg)) 995 $error.=": ".$php_errormsg; 996 if(!file_exists($file["FileName"])) 997 $error="it was not possible to access the file ".$file["FileName"]; 998 return($error); 999 } 1000 $definition["FILENAME"]=$file["FileName"]; 1001 $definition["Content-Length"]=$length; 1002 } 1003 elseif(IsSet($file["Data"])) 1004 $definition["Content-Length"]=strlen($definition["DATA"]=$file["Data"]); 1005 else 1006 return("it was not specified a valid file name"); 1007 return(""); 1008 } 1009 1010 Function ConnectFromProxy($arguments, &$headers) 1011 { 1012 if(!$this->PutLine('CONNECT '.$this->host_name.':'.($this->host_port ? $this->host_port : 443).' HTTP/1.0') 1013 || (strlen($this->user_agent) 1014 && !$this->PutLine('User-Agent: '.$this->user_agent)) 1015 || (strlen($this->accept) 1016 && !$this->PutLine('Accept: '.$this->accept)) 1017 || (IsSet($arguments['Headers']['Proxy-Authorization']) 1018 && !$this->PutLine('Proxy-Authorization: '.$arguments['Headers']['Proxy-Authorization'])) 1019 || !$this->PutLine('')) 1020 { 1021 $this->Disconnect(); 1022 return($this->error); 1023 } 1024 $this->state = "ConnectSent"; 1025 if(strlen($error=$this->ReadReplyHeadersResponse($headers))) 1026 return($error); 1027 $proxy_authorization=""; 1028 while(!strcmp($this->response_status, "100")) 1029 { 1030 $this->state="ConnectSent"; 1031 if(strlen($error=$this->ReadReplyHeadersResponse($headers))) 1032 return($error); 1033 } 1034 switch($this->response_status) 1035 { 1036 case "200": 1037 if(!@stream_socket_enable_crypto($this->connection, 1, STREAM_CRYPTO_METHOD_SSLv23_CLIENT)) 1038 { 1039 $this->SetPHPError('it was not possible to start a SSL encrypted connection via this proxy', $php_errormsg, HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE); 1040 $this->Disconnect(); 1041 return($this->error); 1042 } 1043 $this->state = "Connected"; 1044 break; 1045 case "407": 1046 if(strlen($error=$this->Authenticate($headers, -1, $proxy_authorization, $this->proxy_request_user, $this->proxy_request_password, $this->proxy_request_realm, $this->proxy_request_workstation))) 1047 return($error); 1048 break; 1049 default: 1050 return($this->SetError("unable to send request via proxy", HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); 1051 } 1052 return(""); 1053 } 1054 1055 Function SendRequest($arguments) 1056 { 1057 if(strlen($this->error)) 1058 return($this->error); 1059 if(IsSet($arguments["ProxyUser"])) 1060 $this->proxy_request_user=$arguments["ProxyUser"]; 1061 elseif(IsSet($this->proxy_user)) 1062 $this->proxy_request_user=$this->proxy_user; 1063 if(IsSet($arguments["ProxyPassword"])) 1064 $this->proxy_request_password=$arguments["ProxyPassword"]; 1065 elseif(IsSet($this->proxy_password)) 1066 $this->proxy_request_password=$this->proxy_password; 1067 if(IsSet($arguments["ProxyRealm"])) 1068 $this->proxy_request_realm=$arguments["ProxyRealm"]; 1069 elseif(IsSet($this->proxy_realm)) 1070 $this->proxy_request_realm=$this->proxy_realm; 1071 if(IsSet($arguments["ProxyWorkstation"])) 1072 $this->proxy_request_workstation=$arguments["ProxyWorkstation"]; 1073 elseif(IsSet($this->proxy_workstation)) 1074 $this->proxy_request_workstation=$this->proxy_workstation; 1075 switch($this->state) 1076 { 1077 case "Disconnected": 1078 return($this->SetError("connection was not yet established", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1079 case "Connected": 1080 $connect = 0; 1081 break; 1082 case "ConnectedToProxy": 1083 if(strlen($error = $this->ConnectFromProxy($arguments, $headers))) 1084 return($error); 1085 $connect = 1; 1086 break; 1087 default: 1088 return($this->SetError("can not send request in the current connection state", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1089 } 1090 if(IsSet($arguments["RequestMethod"])) 1091 $this->request_method=$arguments["RequestMethod"]; 1092 if(IsSet($arguments["User-Agent"])) 1093 $this->user_agent=$arguments["User-Agent"]; 1094 if(!IsSet($arguments["Headers"]["User-Agent"]) 1095 && strlen($this->user_agent)) 1096 $arguments["Headers"]["User-Agent"]=$this->user_agent; 1097 if(IsSet($arguments["KeepAlive"])) 1098 $this->keep_alive=intval($arguments["KeepAlive"]); 1099 if(!IsSet($arguments["Headers"]["Connection"]) 1100 && $this->keep_alive) 1101 $arguments["Headers"]["Connection"]='Keep-Alive'; 1102 if(IsSet($arguments["Accept"])) 1103 $this->user_agent=$arguments["Accept"]; 1104 if(!IsSet($arguments["Headers"]["Accept"]) 1105 && strlen($this->accept)) 1106 $arguments["Headers"]["Accept"]=$this->accept; 1107 if(strlen($this->request_method)==0) 1108 return($this->SetError("it was not specified a valid request method", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1109 if(IsSet($arguments["RequestURI"])) 1110 $this->request_uri=$arguments["RequestURI"]; 1111 if(strlen($this->request_uri)==0 1112 || substr($this->request_uri,0,1)!="/") 1113 return($this->SetError("it was not specified a valid request URI", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1114 $this->request_arguments=$arguments; 1115 $this->request_headers=(IsSet($arguments["Headers"]) ? $arguments["Headers"] : array()); 1116 $body_length=0; 1117 $this->request_body=""; 1118 $get_body=1; 1119 if($this->request_method=="POST" 1120 || $this->request_method=="PUT") 1121 { 1122 if(IsSet($arguments['StreamRequest'])) 1123 { 1124 $get_body = 0; 1125 $this->request_headers["Transfer-Encoding"]="chunked"; 1126 } 1127 elseif(IsSet($arguments["PostFiles"]) 1128 || ($this->force_multipart_form_post 1129 && IsSet($arguments["PostValues"]))) 1130 { 1131 $boundary="--".md5(uniqid(time())); 1132 $this->request_headers["Content-Type"]="multipart/form-data; boundary=".$boundary.(IsSet($arguments["CharSet"]) ? "; charset=".$arguments["CharSet"] : ""); 1133 $post_parts=array(); 1134 if(IsSet($arguments["PostValues"])) 1135 { 1136 $values=$arguments["PostValues"]; 1137 if(GetType($values)!="array") 1138 return($this->SetError("it was not specified a valid POST method values array", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1139 for(Reset($values),$value=0;$value<count($values);Next($values),$value++) 1140 { 1141 $input=Key($values); 1142 $headers="--".$boundary."\r\nContent-Disposition: form-data; name=\"".$input."\"\r\n\r\n"; 1143 $data=$values[$input]; 1144 $post_parts[]=array("HEADERS"=>$headers,"DATA"=>$data); 1145 $body_length+=strlen($headers)+strlen($data)+strlen("\r\n"); 1146 } 1147 } 1148 $body_length+=strlen("--".$boundary."--\r\n"); 1149 $files=(IsSet($arguments["PostFiles"]) ? $arguments["PostFiles"] : array()); 1150 Reset($files); 1151 $end=(GetType($input=Key($files))!="string"); 1152 for(;!$end;) 1153 { 1154 if(strlen($error=$this->GetFileDefinition($files[$input],$definition))) 1155 return("3 ".$error); 1156 $headers="--".$boundary."\r\nContent-Disposition: form-data; name=\"".$input."\"; filename=\"".$definition["NAME"]."\"\r\nContent-Type: ".$definition["Content-Type"]."\r\n\r\n"; 1157 $part=count($post_parts); 1158 $post_parts[$part]=array("HEADERS"=>$headers); 1159 if(IsSet($definition["FILENAME"])) 1160 { 1161 $post_parts[$part]["FILENAME"]=$definition["FILENAME"]; 1162 $data=""; 1163 } 1164 else 1165 $data=$definition["DATA"]; 1166 $post_parts[$part]["DATA"]=$data; 1167 $body_length+=strlen($headers)+$definition["Content-Length"]+strlen("\r\n"); 1168 Next($files); 1169 $end=(GetType($input=Key($files))!="string"); 1170 } 1171 $get_body=0; 1172 } 1173 elseif(IsSet($arguments["PostValues"])) 1174 { 1175 $values=$arguments["PostValues"]; 1176 if(GetType($values)!="array") 1177 return($this->SetError("it was not specified a valid POST method values array", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1178 for(Reset($values),$value=0;$value<count($values);Next($values),$value++) 1179 { 1180 $k=Key($values); 1181 if(GetType($values[$k])=="array") 1182 { 1183 for($v = 0; $v < count($values[$k]); $v++) 1184 { 1185 if($value+$v>0) 1186 $this->request_body.="&"; 1187 $this->request_body.=UrlEncode($k)."=".UrlEncode($values[$k][$v]); 1188 } 1189 } 1190 else 1191 { 1192 if($value>0) 1193 $this->request_body.="&"; 1194 $this->request_body.=UrlEncode($k)."=".UrlEncode($values[$k]); 1195 } 1196 } 1197 $this->request_headers["Content-Type"]="application/x-www-form-urlencoded".(IsSet($arguments["CharSet"]) ? "; charset=".$arguments["CharSet"] : ""); 1198 $get_body=0; 1199 } 1200 } 1201 if($get_body 1202 && (IsSet($arguments["Body"]) 1203 || IsSet($arguments["BodyStream"]))) 1204 { 1205 if(IsSet($arguments["Body"])) 1206 $this->request_body=$arguments["Body"]; 1207 else 1208 { 1209 $stream=$arguments["BodyStream"]; 1210 $this->request_body=""; 1211 for($part=0; $part<count($stream); $part++) 1212 { 1213 if(IsSet($stream[$part]["Data"])) 1214 $this->request_body.=$stream[$part]["Data"]; 1215 elseif(IsSet($stream[$part]["File"])) 1216 { 1217 if(!($file=@fopen($stream[$part]["File"],"rb"))) 1218 return($this->SetPHPError("could not open upload file ".$stream[$part]["File"], $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE)); 1219 while(!feof($file)) 1220 { 1221 if(GetType($block=@fread($file,$this->file_buffer_length))!="string") 1222 { 1223 $error=$this->SetPHPError("could not read body stream file ".$stream[$part]["File"], $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE); 1224 fclose($file); 1225 return($error); 1226 } 1227 $this->request_body.=$block; 1228 } 1229 fclose($file); 1230 } 1231 else 1232 return("5 it was not specified a valid file or data body stream element at position ".$part); 1233 } 1234 } 1235 if(!IsSet($this->request_headers["Content-Type"])) 1236 $this->request_headers["Content-Type"]="application/octet-stream".(IsSet($arguments["CharSet"]) ? "; charset=".$arguments["CharSet"] : ""); 1237 } 1238 if(IsSet($arguments["AuthUser"])) 1239 $this->request_user=$arguments["AuthUser"]; 1240 elseif(IsSet($this->user)) 1241 $this->request_user=$this->user; 1242 if(IsSet($arguments["AuthPassword"])) 1243 $this->request_password=$arguments["AuthPassword"]; 1244 elseif(IsSet($this->password)) 1245 $this->request_password=$this->password; 1246 if(IsSet($arguments["AuthRealm"])) 1247 $this->request_realm=$arguments["AuthRealm"]; 1248 elseif(IsSet($this->realm)) 1249 $this->request_realm=$this->realm; 1250 if(IsSet($arguments["AuthWorkstation"])) 1251 $this->request_workstation=$arguments["AuthWorkstation"]; 1252 elseif(IsSet($this->workstation)) 1253 $this->request_workstation=$this->workstation; 1254 if(strlen($this->proxy_host_name)==0 1255 || $connect) 1256 $request_uri=$this->request_uri; 1257 else 1258 { 1259 switch(strtolower($this->protocol)) 1260 { 1261 case "http": 1262 $default_port=80; 1263 break; 1264 case "https": 1265 $default_port=443; 1266 break; 1267 } 1268 $request_uri=strtolower($this->protocol)."://".$this->host_name.(($this->host_port==0 || $this->host_port==$default_port) ? "" : ":".$this->host_port).$this->request_uri; 1269 } 1270 if($this->use_curl) 1271 { 1272 $version=(GetType($v=curl_version())=="array" ? (IsSet($v["version"]) ? $v["version"] : "0.0.0") : (preg_match("/^libcurl\\/([0-9]+\\.[0-9]+\\.[0-9]+)/",$v,$m) ? $m[1] : "0.0.0")); 1273 $curl_version=100000*intval($this->Tokenize($version,"."))+1000*intval($this->Tokenize("."))+intval($this->Tokenize("")); 1274 $protocol_version=($curl_version<713002 ? "1.0" : $this->protocol_version); 1275 } 1276 else 1277 $protocol_version=$this->protocol_version; 1278 $this->request=$this->request_method." ".$request_uri." HTTP/".$protocol_version; 1279 if($body_length 1280 || ($body_length=strlen($this->request_body)) 1281 || !strcmp($this->request_method, 'POST')) 1282 $this->request_headers["Content-Length"]=$body_length; 1283 for($headers=array(),$host_set=0,Reset($this->request_headers),$header=0;$header<count($this->request_headers);Next($this->request_headers),$header++) 1284 { 1285 $header_name=Key($this->request_headers); 1286 $header_value=$this->request_headers[$header_name]; 1287 if(GetType($header_value)=="array") 1288 { 1289 for(Reset($header_value),$value=0;$value<count($header_value);Next($header_value),$value++) 1290 $headers[]=$header_name.": ".$header_value[Key($header_value)]; 1291 } 1292 else 1293 $headers[]=$header_name.": ".$header_value; 1294 if(strtolower(Key($this->request_headers))=="host") 1295 { 1296 $this->request_host=strtolower($header_value); 1297 $host_set=1; 1298 } 1299 } 1300 if(!$host_set) 1301 { 1302 $headers[]="Host: ".$this->host_name; 1303 $this->request_host=strtolower($this->host_name); 1304 } 1305 if(count($this->cookies)) 1306 { 1307 $cookies=array(); 1308 $this->PickCookies($cookies,0); 1309 if(strtolower($this->protocol)=="https") 1310 $this->PickCookies($cookies,1); 1311 if(count($cookies)) 1312 { 1313 $h=count($headers); 1314 $headers[$h]="Cookie:"; 1315 for(Reset($cookies),$cookie=0;$cookie<count($cookies);Next($cookies),$cookie++) 1316 { 1317 $cookie_name=Key($cookies); 1318 $headers[$h].=" ".$cookie_name."=".$cookies[$cookie_name]["value"].";"; 1319 } 1320 } 1321 } 1322 $next_state = "RequestSent"; 1323 if($this->use_curl) 1324 { 1325 if(IsSet($arguments['StreamRequest'])) 1326 return($this->SetError("Streaming request data is not supported when using Curl", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1327 if($body_length 1328 && strlen($this->request_body)==0) 1329 { 1330 for($request_body="",$success=1,$part=0;$part<count($post_parts);$part++) 1331 { 1332 $request_body.=$post_parts[$part]["HEADERS"].$post_parts[$part]["DATA"]; 1333 if(IsSet($post_parts[$part]["FILENAME"])) 1334 { 1335 if(!($file=@fopen($post_parts[$part]["FILENAME"],"rb"))) 1336 { 1337 $this->SetPHPError("could not open upload file ".$post_parts[$part]["FILENAME"], $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE); 1338 $success=0; 1339 break; 1340 } 1341 while(!feof($file)) 1342 { 1343 if(GetType($block=@fread($file,$this->file_buffer_length))!="string") 1344 { 1345 $this->SetPHPError("could not read upload file", $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE); 1346 $success=0; 1347 break; 1348 } 1349 $request_body.=$block; 1350 } 1351 fclose($file); 1352 if(!$success) 1353 break; 1354 } 1355 $request_body.="\r\n"; 1356 } 1357 $request_body.="--".$boundary."--\r\n"; 1358 } 1359 else 1360 $request_body=$this->request_body; 1361 curl_setopt($this->connection,CURLOPT_HEADER,1); 1362 curl_setopt($this->connection,CURLOPT_RETURNTRANSFER,1); 1363 if($this->timeout) 1364 curl_setopt($this->connection,CURLOPT_TIMEOUT,$this->timeout); 1365 curl_setopt($this->connection,CURLOPT_SSL_VERIFYPEER,0); 1366 curl_setopt($this->connection,CURLOPT_SSL_VERIFYHOST,0); 1367 $request=$this->request."\r\n".implode("\r\n",$headers)."\r\n\r\n".$request_body; 1368 curl_setopt($this->connection,CURLOPT_CUSTOMREQUEST,$request); 1369 if($this->debug) 1370 $this->OutputDebug("C ".$request); 1371 if(!($success=(strlen($this->response=curl_exec($this->connection))!=0))) 1372 { 1373 $error=curl_error($this->connection); 1374 $this->SetError("Could not execute the request".(strlen($error) ? ": ".$error : ""), HTTP_CLIENT_ERROR_PROTOCOL_FAILURE); 1375 } 1376 } 1377 else 1378 { 1379 if(($success=$this->PutLine($this->request))) 1380 { 1381 for($header=0;$header<count($headers);$header++) 1382 { 1383 if(!$success=$this->PutLine($headers[$header])) 1384 break; 1385 } 1386 if($success 1387 && ($success=$this->PutLine(""))) 1388 { 1389 if(IsSet($arguments['StreamRequest'])) 1390 $next_state = "SendingRequestBody"; 1391 elseif($body_length) 1392 { 1393 if(strlen($this->request_body)) 1394 $success=$this->PutData($this->request_body); 1395 else 1396 { 1397 for($part=0;$part<count($post_parts);$part++) 1398 { 1399 if(!($success=$this->PutData($post_parts[$part]["HEADERS"])) 1400 || !($success=$this->PutData($post_parts[$part]["DATA"]))) 1401 break; 1402 if(IsSet($post_parts[$part]["FILENAME"])) 1403 { 1404 if(!($file=@fopen($post_parts[$part]["FILENAME"],"rb"))) 1405 { 1406 $this->SetPHPError("could not open upload file ".$post_parts[$part]["FILENAME"], $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE); 1407 $success=0; 1408 break; 1409 } 1410 while(!feof($file)) 1411 { 1412 if(GetType($block=@fread($file,$this->file_buffer_length))!="string") 1413 { 1414 $this->SetPHPError("could not read upload file", $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE); 1415 $success=0; 1416 break; 1417 } 1418 if(!($success=$this->PutData($block))) 1419 break; 1420 } 1421 fclose($file); 1422 if(!$success) 1423 break; 1424 } 1425 if(!($success=$this->PutLine(""))) 1426 break; 1427 } 1428 if($success) 1429 $success=$this->PutLine("--".$boundary."--"); 1430 } 1431 if($success) 1432 $sucess=$this->FlushData(); 1433 } 1434 } 1435 } 1436 } 1437 if(!$success) 1438 return($this->SetError("could not send the HTTP request: ".$this->error, $this->error_code)); 1439 $this->state=$next_state; 1440 return(""); 1441 } 1442 1443 Function SetCookie($name, $value, $expires="" , $path="/" , $domain="" , $secure=0, $verbatim=0) 1444 { 1445 if(strlen($this->error)) 1446 return($this->error); 1447 if(strlen($name)==0) 1448 return($this->SetError("it was not specified a valid cookie name", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1449 if(strlen($path)==0 1450 || strcmp($path[0],"/")) 1451 return($this->SetError($path." is not a valid path for setting cookie ".$name, HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1452 if($domain=="" 1453 || !strpos($domain,".",$domain[0]=="." ? 1 : 0)) 1454 return($this->SetError($domain." is not a valid domain for setting cookie ".$name, HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1455 $domain=strtolower($domain); 1456 if(!strcmp($domain[0],".")) 1457 $domain=substr($domain,1); 1458 if(!$verbatim) 1459 { 1460 $name=$this->CookieEncode($name,1); 1461 $value=$this->CookieEncode($value,0); 1462 } 1463 $secure=intval($secure); 1464 $this->cookies[$secure][$domain][$path][$name]=array( 1465 "name"=>$name, 1466 "value"=>$value, 1467 "domain"=>$domain, 1468 "path"=>$path, 1469 "expires"=>$expires, 1470 "secure"=>$secure 1471 ); 1472 return(""); 1473 } 1474 1475 Function SendRequestBody($data, $end_of_data) 1476 { 1477 if(strlen($this->error)) 1478 return($this->error); 1479 switch($this->state) 1480 { 1481 case "Disconnected": 1482 return($this->SetError("connection was not yet established", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1483 case "Connected": 1484 case "ConnectedToProxy": 1485 return($this->SetError("request was not sent", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1486 case "SendingRequestBody": 1487 break; 1488 case "RequestSent": 1489 return($this->SetError("request body was already sent", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1490 default: 1491 return($this->SetError("can not send the request body in the current connection state", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1492 } 1493 $length = strlen($data); 1494 if($length) 1495 { 1496 $size = dechex($length)."\r\n"; 1497 if(!$this->PutData($size) 1498 || !$this->PutData($data)) 1499 return($this->error); 1500 } 1501 if($end_of_data) 1502 { 1503 $size = "0\r\n"; 1504 if(!$this->PutData($size)) 1505 return($this->error); 1506 $this->state = "RequestSent"; 1507 } 1508 return(""); 1509 } 1510 1511 Function ReadReplyHeadersResponse(&$headers) 1512 { 1513 $headers=array(); 1514 if(strlen($this->error)) 1515 return($this->error); 1516 switch($this->state) 1517 { 1518 case "Disconnected": 1519 return($this->SetError("connection was not yet established", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1520 case "Connected": 1521 return($this->SetError("request was not sent", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1522 case "ConnectedToProxy": 1523 return($this->SetError("connection from the remote server from the proxy was not yet established", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1524 case "SendingRequestBody": 1525 return($this->SetError("request body data was not completely sent", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1526 case "ConnectSent": 1527 $connect = 1; 1528 break; 1529 case "RequestSent": 1530 $connect = 0; 1531 break; 1532 default: 1533 return($this->SetError("can not get request headers in the current connection state", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1534 } 1535 $this->content_length=$this->read_length=$this->read_response=$this->remaining_chunk=0; 1536 $this->content_length_set=$this->chunked=$this->last_chunk_read=$chunked=0; 1537 $this->force_close = $this->connection_close=0; 1538 for($this->response_status="";;) 1539 { 1540 $line=$this->GetLine(); 1541 if(GetType($line)!="string") 1542 return($this->SetError("could not read request reply: ".$this->error, $this->error_code)); 1543 if(strlen($this->response_status)==0) 1544 { 1545 if(!preg_match($match="/^http\\/[0-9]+\\.[0-9]+[ \t]+([0-9]+)[ \t]*(.*)\$/i",$line,$matches)) 1546 return($this->SetError("it was received an unexpected HTTP response status", HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); 1547 $this->response_status=$matches[1]; 1548 $this->response_message=$matches[2]; 1549 } 1550 if($line=="") 1551 { 1552 if(strlen($this->response_status)==0) 1553 return($this->SetError("it was not received HTTP response status", HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); 1554 $this->state=($connect ? "GotConnectHeaders" : "GotReplyHeaders"); 1555 break; 1556 } 1557 $header_name=strtolower($this->Tokenize($line,":")); 1558 $header_value=Trim(Chop($this->Tokenize("\r\n"))); 1559 if(IsSet($headers[$header_name])) 1560 { 1561 if(GetType($headers[$header_name])=="string") 1562 $headers[$header_name]=array($headers[$header_name]); 1563 $headers[$header_name][]=$header_value; 1564 } 1565 else 1566 $headers[$header_name]=$header_value; 1567 if(!$connect) 1568 { 1569 switch($header_name) 1570 { 1571 case "content-length": 1572 $this->content_length=intval($headers[$header_name]); 1573 $this->content_length_set=1; 1574 break; 1575 case "transfer-encoding": 1576 $encoding=$this->Tokenize($header_value,"; \t"); 1577 if(!$this->use_curl 1578 && !strcmp($encoding,"chunked")) 1579 $chunked=1; 1580 break; 1581 case "set-cookie": 1582 if($this->support_cookies) 1583 { 1584 if(GetType($headers[$header_name])=="array") 1585 $cookie_headers=$headers[$header_name]; 1586 else 1587 $cookie_headers=array($headers[$header_name]); 1588 for($cookie=0;$cookie<count($cookie_headers);$cookie++) 1589 { 1590 $cookie_name=trim($this->Tokenize($cookie_headers[$cookie],"=")); 1591 $cookie_value=$this->Tokenize(";"); 1592 $domain=$this->request_host; 1593 $path="/"; 1594 $expires=""; 1595 $secure=0; 1596 while(($name = strtolower(trim(UrlDecode($this->Tokenize("=")))))!="") 1597 { 1598 $value=UrlDecode($this->Tokenize(";")); 1599 switch($name) 1600 { 1601 case "domain": 1602 $domain=$value; 1603 break; 1604 case "path": 1605 $path=$value; 1606 break; 1607 case "expires": 1608 if(preg_match("/^((Mon|Monday|Tue|Tuesday|Wed|Wednesday|Thu|Thursday|Fri|Friday|Sat|Saturday|Sun|Sunday), )?([0-9]{2})\\-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\\-([0-9]{2,4}) ([0-9]{2})\\:([0-9]{2})\\:([0-9]{2}) GMT\$/",$value,$matches)) 1609 { 1610 $year=intval($matches[5]); 1611 if($year<1900) 1612 $year+=($year<70 ? 2000 : 1900); 1613 $expires="$year-".$this->months[$matches[4]]."-".$matches[3]." ".$matches[6].":".$matches[7].":".$matches[8]; 1614 } 1615 break; 1616 case "secure": 1617 $secure=1; 1618 break; 1619 } 1620 } 1621 if(strlen($this->SetCookie($cookie_name, $cookie_value, $expires, $path , $domain, $secure, 1))) 1622 $this->error=""; 1623 } 1624 } 1625 break; 1626 case "connection": 1627 $this->force_close = $this->connection_close=!strcmp(strtolower($header_value),"close"); 1628 break; 1629 } 1630 } 1631 } 1632 $this->chunked=$chunked; 1633 if($this->content_length_set) 1634 $this->connection_close=0; 1635 return(""); 1636 } 1637 1638 Function Redirect(&$headers) 1639 { 1640 if($this->follow_redirect) 1641 { 1642 if(!IsSet($headers["location"]) 1643 || (GetType($headers["location"])!="array" 1644 && strlen($location=$headers["location"])==0) 1645 || (GetType($headers["location"])=="array" 1646 && strlen($location=$headers["location"][0])==0)) 1647 return($this->SetError("it was received a redirect without location URL", HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); 1648 if(strcmp($location[0],"/")) 1649 { 1650 if(!($location_arguments=@parse_url($location))) 1651 return($this->SetError("the server did not return a valid redirection location URL", HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); 1652 if(!IsSet($location_arguments["scheme"])) 1653 $location=((GetType($end=strrpos($this->request_uri,"/"))=="integer" && $end>1) ? substr($this->request_uri,0,$end) : "")."/".$location; 1654 } 1655 if(!strcmp($location[0],"/")) 1656 $location=$this->protocol."://".$this->host_name.($this->host_port ? ":".$this->host_port : "").$location; 1657 $error=$this->GetRequestArguments($location,$arguments); 1658 if(strlen($error)) 1659 return($this->SetError("could not process redirect url: ".$error, HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); 1660 $arguments["RequestMethod"]="GET"; 1661 if(strlen($error=$this->Close())==0 1662 && strlen($error=$this->Open($arguments))==0 1663 && strlen($error=$this->SendRequest($arguments))==0) 1664 { 1665 $this->redirection_level++; 1666 if($this->redirection_level>$this->redirection_limit) 1667 { 1668 $error="it was exceeded the limit of request redirections"; 1669 $this->error_code = HTTP_CLIENT_ERROR_PROTOCOL_FAILURE; 1670 } 1671 else 1672 $error=$this->ReadReplyHeaders($headers); 1673 $this->redirection_level--; 1674 } 1675 if(strlen($error)) 1676 return($this->SetError($error, $this->error_code)); 1677 } 1678 return(""); 1679 } 1680 1681 Function Authenticate(&$headers, $proxy, &$proxy_authorization, &$user, &$password, &$realm, &$workstation) 1682 { 1683 if($proxy) 1684 { 1685 $authenticate_header="proxy-authenticate"; 1686 $authorization_header="Proxy-Authorization"; 1687 $authenticate_status="407"; 1688 $authentication_mechanism=$this->proxy_authentication_mechanism; 1689 } 1690 else 1691 { 1692 $authenticate_header="www-authenticate"; 1693 $authorization_header="Authorization"; 1694 $authenticate_status="401"; 1695 $authentication_mechanism=$this->authentication_mechanism; 1696 } 1697 if(IsSet($headers[$authenticate_header]) 1698 && $this->sasl_authenticate) 1699 { 1700 if(function_exists("class_exists") 1701 && !class_exists("sasl_client_class")) 1702 return($this->SetError("the SASL client class needs to be loaded to be able to authenticate".($proxy ? " with the proxy server" : "")." and access this site", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1703 if(GetType($headers[$authenticate_header])=="array") 1704 $authenticate=$headers[$authenticate_header]; 1705 else 1706 $authenticate=array($headers[$authenticate_header]); 1707 for($response="", $mechanisms=array(),$m=0;$m<count($authenticate);$m++) 1708 { 1709 $mechanism=$this->Tokenize($authenticate[$m]," "); 1710 $response=$this->Tokenize(""); 1711 if(strlen($authentication_mechanism)) 1712 { 1713 if(!strcmp($authentication_mechanism,$mechanism)) 1714 { 1715 $mechanisms[]=$mechanism; 1716 break; 1717 } 1718 } 1719 else 1720 $mechanisms[]=$mechanism; 1721 } 1722 $sasl=new sasl_client_class; 1723 if(IsSet($user)) 1724 $sasl->SetCredential("user",$user); 1725 if(IsSet($password)) 1726 $sasl->SetCredential("password",$password); 1727 if(IsSet($realm)) 1728 $sasl->SetCredential("realm",$realm); 1729 if(IsSet($workstation)) 1730 $sasl->SetCredential("workstation",$workstation); 1731 $sasl->SetCredential("uri",$this->request_uri); 1732 $sasl->SetCredential("method",$this->request_method); 1733 $sasl->SetCredential("session",$this->session); 1734 do 1735 { 1736 $status=$sasl->Start($mechanisms,$message,$interactions); 1737 } 1738 while($status==SASL_INTERACT); 1739 switch($status) 1740 { 1741 case SASL_CONTINUE: 1742 break; 1743 case SASL_NOMECH: 1744 return($this->SetError(($proxy ? "proxy " : "")."authentication error: ".(strlen($authentication_mechanism) ? "authentication mechanism ".$authentication_mechanism." may not be used: " : "").$sasl->error, HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1745 default: 1746 return($this->SetError("Could not start the SASL ".($proxy ? "proxy " : "")."authentication client: ".$sasl->error, HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1747 } 1748 if($proxy >= 0) 1749 { 1750 for(;;) 1751 { 1752 if(strlen($error=$this->ReadReplyBody($body,$this->file_buffer_length))) 1753 return($error); 1754 if(strlen($body)==0) 1755 break; 1756 } 1757 } 1758 $authorization_value=$sasl->mechanism.(IsSet($message) ? " ".($sasl->encode_response ? base64_encode($message) : $message) : ""); 1759 $request_arguments=$this->request_arguments; 1760 $arguments=$request_arguments; 1761 $arguments["Headers"][$authorization_header]=$authorization_value; 1762 if(!$proxy 1763 && strlen($proxy_authorization)) 1764 $arguments["Headers"]["Proxy-Authorization"]=$proxy_authorization; 1765 if(strlen($error=$this->Close()) 1766 || strlen($error=$this->Open($arguments))) 1767 return($this->SetError($error, $this->error_code)); 1768 $authenticated=0; 1769 if(IsSet($message)) 1770 { 1771 if($proxy < 0) 1772 { 1773 if(strlen($error=$this->ConnectFromProxy($arguments, $headers))) 1774 return($this->SetError($error, $this->error_code)); 1775 } 1776 else 1777 { 1778 if(strlen($error=$this->SendRequest($arguments)) 1779 || strlen($error=$this->ReadReplyHeadersResponse($headers))) 1780 return($this->SetError($error, $this->error_code)); 1781 } 1782 if(!IsSet($headers[$authenticate_header])) 1783 $authenticate=array(); 1784 elseif(GetType($headers[$authenticate_header])=="array") 1785 $authenticate=$headers[$authenticate_header]; 1786 else 1787 $authenticate=array($headers[$authenticate_header]); 1788 for($mechanism=0;$mechanism<count($authenticate);$mechanism++) 1789 { 1790 if(!strcmp($this->Tokenize($authenticate[$mechanism]," "),$sasl->mechanism)) 1791 { 1792 $response=$this->Tokenize(""); 1793 break; 1794 } 1795 } 1796 switch($this->response_status) 1797 { 1798 case $authenticate_status: 1799 break; 1800 case "301": 1801 case "302": 1802 case "303": 1803 case "307": 1804 if($proxy >= 0) 1805 return($this->Redirect($headers)); 1806 default: 1807 if(intval($this->response_status/100)==2) 1808 { 1809 if($proxy) 1810 $proxy_authorization=$authorization_value; 1811 $authenticated=1; 1812 break; 1813 } 1814 if($proxy 1815 && !strcmp($this->response_status,"401")) 1816 { 1817 $proxy_authorization=$authorization_value; 1818 $authenticated=1; 1819 break; 1820 } 1821 return($this->SetError(($proxy ? "proxy " : "")."authentication error: ".$this->response_status." ".$this->response_message, HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); 1822 } 1823 } 1824 for(;!$authenticated;) 1825 { 1826 do 1827 { 1828 $status=$sasl->Step($response,$message,$interactions); 1829 } 1830 while($status==SASL_INTERACT); 1831 switch($status) 1832 { 1833 case SASL_CONTINUE: 1834 $authorization_value=$sasl->mechanism.(IsSet($message) ? " ".($sasl->encode_response ? base64_encode($message) : $message) : ""); 1835 $arguments=$request_arguments; 1836 $arguments["Headers"][$authorization_header]=$authorization_value; 1837 if(!$proxy 1838 && strlen($proxy_authorization)) 1839 $arguments["Headers"]["Proxy-Authorization"]=$proxy_authorization; 1840 if($proxy < 0) 1841 { 1842 if(strlen($error=$this->ConnectFromProxy($arguments, $headers))) 1843 return($this->SetError($error, $this->error_code)); 1844 } 1845 else 1846 { 1847 if(strlen($error=$this->SendRequest($arguments)) 1848 || strlen($error=$this->ReadReplyHeadersResponse($headers))) 1849 return($this->SetError($error, $this->error_code)); 1850 } 1851 switch($this->response_status) 1852 { 1853 case $authenticate_status: 1854 if(GetType($headers[$authenticate_header])=="array") 1855 $authenticate=$headers[$authenticate_header]; 1856 else 1857 $authenticate=array($headers[$authenticate_header]); 1858 for($response="",$mechanism=0;$mechanism<count($authenticate);$mechanism++) 1859 { 1860 if(!strcmp($this->Tokenize($authenticate[$mechanism]," "),$sasl->mechanism)) 1861 { 1862 $response=$this->Tokenize(""); 1863 break; 1864 } 1865 } 1866 if($proxy >= 0) 1867 { 1868 for(;;) 1869 { 1870 if(strlen($error=$this->ReadReplyBody($body,$this->file_buffer_length))) 1871 return($error); 1872 if(strlen($body)==0) 1873 break; 1874 } 1875 } 1876 $this->state="Connected"; 1877 break; 1878 case "301": 1879 case "302": 1880 case "303": 1881 case "307": 1882 if($proxy >= 0) 1883 return($this->Redirect($headers)); 1884 default: 1885 if(intval($this->response_status/100)==2) 1886 { 1887 if($proxy) 1888 $proxy_authorization=$authorization_value; 1889 $authenticated=1; 1890 break; 1891 } 1892 if($proxy 1893 && !strcmp($this->response_status,"401")) 1894 { 1895 $proxy_authorization=$authorization_value; 1896 $authenticated=1; 1897 break; 1898 } 1899 return($this->SetError(($proxy ? "proxy " : "")."authentication error: ".$this->response_status." ".$this->response_message)); 1900 } 1901 break; 1902 default: 1903 return($this->SetError("Could not process the SASL ".($proxy ? "proxy " : "")."authentication step: ".$sasl->error, HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); 1904 } 1905 } 1906 } 1907 return(""); 1908 } 1909 1910 Function ReadReplyHeaders(&$headers) 1911 { 1912 if(strlen($error=$this->ReadReplyHeadersResponse($headers))) 1913 return($error); 1914 $proxy_authorization=""; 1915 while(!strcmp($this->response_status, "100")) 1916 { 1917 $this->state="RequestSent"; 1918 if(strlen($error=$this->ReadReplyHeadersResponse($headers))) 1919 return($error); 1920 } 1921 switch($this->response_status) 1922 { 1923 case "301": 1924 case "302": 1925 case "303": 1926 case "307": 1927 if(strlen($error=$this->Redirect($headers))) 1928 return($error); 1929 break; 1930 case "407": 1931 if(strlen($error=$this->Authenticate($headers, 1, $proxy_authorization, $this->proxy_request_user, $this->proxy_request_password, $this->proxy_request_realm, $this->proxy_request_workstation))) 1932 return($error); 1933 if(strcmp($this->response_status,"401")) 1934 return(""); 1935 case "401": 1936 return($this->Authenticate($headers, 0, $proxy_authorization, $this->request_user, $this->request_password, $this->request_realm, $this->request_workstation)); 1937 } 1938 return(""); 1939 } 1940 1941 Function ReadReplyBody(&$body,$length) 1942 { 1943 $body=""; 1944 if(strlen($this->error)) 1945 return($this->error); 1946 switch($this->state) 1947 { 1948 case "Disconnected": 1949 return($this->SetError("connection was not yet established", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1950 case "Connected": 1951 case "ConnectedToProxy": 1952 return($this->SetError("request was not sent", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1953 case "RequestSent": 1954 if(($error=$this->ReadReplyHeaders($headers))!="") 1955 return($error); 1956 break; 1957 case "GotReplyHeaders": 1958 break; 1959 case 'ResponseReceived': 1960 $body = ''; 1961 return(''); 1962 default: 1963 return($this->SetError("can not get request headers in the current connection state", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 1964 } 1965 if($this->content_length_set) 1966 $length=min($this->content_length-$this->read_length,$length); 1967 $body = ''; 1968 if($length>0) 1969 { 1970 if(!$this->EndOfInput() 1971 && ($body=$this->ReadBytes($length))=="") 1972 { 1973 if(strlen($this->error)) 1974 return($this->SetError("could not get the request reply body: ".$this->error, $this->error_code)); 1975 } 1976 $this->read_length+=strlen($body); 1977 if($this->EndOfInput()) 1978 $this->state = 'ResponseReceived'; 1979 } 1980 return(""); 1981 } 1982 1983 Function ReadWholeReplyBody(&$body) 1984 { 1985 $body = ''; 1986 for(;;) 1987 { 1988 if(strlen($error = $this->ReadReplyBody($block, $this->file_buffer_length))) 1989 return($error); 1990 if(strlen($block) == 0) 1991 return(''); 1992 $body .= $block; 1993 } 1994 } 1995 1996 Function SaveCookies(&$cookies, $domain='', $secure_only=0, $persistent_only=0) 1997 { 1998 $now=gmdate("Y-m-d H-i-s"); 1999 $cookies=array(); 2000 for($secure_cookies=0,Reset($this->cookies);$secure_cookies<count($this->cookies);Next($this->cookies),$secure_cookies++) 2001 { 2002 $secure=Key($this->cookies); 2003 if(!$secure_only 2004 || $secure) 2005 { 2006 for($cookie_domain=0,Reset($this->cookies[$secure]);$cookie_domain<count($this->cookies[$secure]);Next($this->cookies[$secure]),$cookie_domain++) 2007 { 2008 $domain_pattern=Key($this->cookies[$secure]); 2009 $match=strlen($domain)-strlen($domain_pattern); 2010 if(strlen($domain)==0 2011 || ($match>=0 2012 && !strcmp($domain_pattern,substr($domain,$match)) 2013 && ($match==0 2014 || $domain_pattern[0]=="." 2015 || $domain[$match-1]=="."))) 2016 { 2017 for(Reset($this->cookies[$secure][$domain_pattern]),$path_part=0;$path_part<count($this->cookies[$secure][$domain_pattern]);Next($this->cookies[$secure][$domain_pattern]),$path_part++) 2018 { 2019 $path=Key($this->cookies[$secure][$domain_pattern]); 2020 for(Reset($this->cookies[$secure][$domain_pattern][$path]),$cookie=0;$cookie<count($this->cookies[$secure][$domain_pattern][$path]);Next($this->cookies[$secure][$domain_pattern][$path]),$cookie++) 2021 { 2022 $cookie_name=Key($this->cookies[$secure][$domain_pattern][$path]); 2023 $expires=$this->cookies[$secure][$domain_pattern][$path][$cookie_name]["expires"]; 2024 if((!$persistent_only 2025 && strlen($expires)==0) 2026 || (strlen($expires) 2027 && strcmp($now,$expires)<0)) 2028 $cookies[$secure][$domain_pattern][$path][$cookie_name]=$this->cookies[$secure][$domain_pattern][$path][$cookie_name]; 2029 } 2030 } 2031 } 2032 } 2033 } 2034 } 2035 } 2036 2037 Function SavePersistentCookies(&$cookies, $domain='', $secure_only=0) 2038 { 2039 $this->SaveCookies($cookies, $domain, $secure_only, 1); 2040 } 2041 2042 Function GetPersistentCookies(&$cookies, $domain='', $secure_only=0) 2043 { 2044 $this->SavePersistentCookies($cookies, $domain, $secure_only); 2045 } 2046 2047 Function RestoreCookies($cookies, $clear=1) 2048 { 2049 $new_cookies=($clear ? array() : $this->cookies); 2050 for($secure_cookies=0, Reset($cookies); $secure_cookies<count($cookies); Next($cookies), $secure_cookies++) 2051 { 2052 $secure=Key($cookies); 2053 if(GetType($secure)!="integer") 2054 return($this->SetError("invalid cookie secure value type (".serialize($secure).")", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 2055 for($cookie_domain=0,Reset($cookies[$secure]);$cookie_domain<count($cookies[$secure]);Next($cookies[$secure]),$cookie_domain++) 2056 { 2057 $domain_pattern=Key($cookies[$secure]); 2058 if(GetType($domain_pattern)!="string") 2059 return($this->SetError("invalid cookie domain value type (".serialize($domain_pattern).")", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 2060 for(Reset($cookies[$secure][$domain_pattern]),$path_part=0;$path_part<count($cookies[$secure][$domain_pattern]);Next($cookies[$secure][$domain_pattern]),$path_part++) 2061 { 2062 $path=Key($cookies[$secure][$domain_pattern]); 2063 if(GetType($path)!="string" 2064 || strcmp(substr($path, 0, 1), "/")) 2065 return($this->SetError("invalid cookie path value type (".serialize($path).")", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 2066 for(Reset($cookies[$secure][$domain_pattern][$path]),$cookie=0;$cookie<count($cookies[$secure][$domain_pattern][$path]);Next($cookies[$secure][$domain_pattern][$path]),$cookie++) 2067 { 2068 $cookie_name=Key($cookies[$secure][$domain_pattern][$path]); 2069 $expires=$cookies[$secure][$domain_pattern][$path][$cookie_name]["expires"]; 2070 $value=$cookies[$secure][$domain_pattern][$path][$cookie_name]["value"]; 2071 if(GetType($expires)!="string" 2072 || (strlen($expires) 2073 && !preg_match("/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\$/", $expires))) 2074 return($this->SetError("invalid cookie expiry value type (".serialize($expires).")", HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); 2075 $new_cookies[$secure][$domain_pattern][$path][$cookie_name]=array( 2076 "name"=>$cookie_name, 2077 "value"=>$value, 2078 "domain"=>$domain_pattern, 2079 "path"=>$path, 2080 "expires"=>$expires, 2081 "secure"=>$secure 2082 ); 2083 } 2084 } 2085 } 2086 } 2087 $this->cookies=$new_cookies; 2088 return(""); 2089 } 2090}; 2091 2092?>