PageRenderTime 62ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/httpclient/http.php

https://github.com/abiggerhammer/pat-twitter
PHP | 2122 lines | 2069 code | 44 blank | 9 comment | 438 complexity | 888dd8efb744393aebcd2f075a18390f MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. * http.php
  4. *
  5. * @(#) $Header: /opt2/ena/metal/http/http.php,v 1.91 2013/07/14 13:21:38 mlemos Exp $
  6. *
  7. */
  8. define('HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR', -1);
  9. define('HTTP_CLIENT_ERROR_NO_ERROR', 0);
  10. define('HTTP_CLIENT_ERROR_INVALID_SERVER_ADDRESS', 1);
  11. define('HTTP_CLIENT_ERROR_CANNOT_CONNECT', 2);
  12. define('HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE', 3);
  13. define('HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE', 4);
  14. define('HTTP_CLIENT_ERROR_PROTOCOL_FAILURE', 5);
  15. define('HTTP_CLIENT_ERROR_INVALID_PARAMETERS', 6);
  16. class http_class
  17. {
  18. var $host_name="";
  19. var $host_port=0;
  20. var $proxy_host_name="";
  21. var $proxy_host_port=80;
  22. var $socks_host_name = '';
  23. var $socks_host_port = 1080;
  24. var $socks_version = '5';
  25. var $protocol="http";
  26. var $request_method="GET";
  27. var $user_agent='httpclient (http://www.phpclasses.org/httpclient $Revision: 1.91 $)';
  28. var $accept='';
  29. var $authentication_mechanism="";
  30. var $user;
  31. var $password;
  32. var $realm;
  33. var $workstation;
  34. var $proxy_authentication_mechanism="";
  35. var $proxy_user;
  36. var $proxy_password;
  37. var $proxy_realm;
  38. var $proxy_workstation;
  39. var $request_uri="";
  40. var $request="";
  41. var $request_headers=array();
  42. var $request_user;
  43. var $request_password;
  44. var $request_realm;
  45. var $request_workstation;
  46. var $proxy_request_user;
  47. var $proxy_request_password;
  48. var $proxy_request_realm;
  49. var $proxy_request_workstation;
  50. var $request_body="";
  51. var $request_arguments=array();
  52. var $protocol_version="1.1";
  53. var $timeout=0;
  54. var $data_timeout=0;
  55. var $debug=0;
  56. var $log_debug=0;
  57. var $debug_response_body=1;
  58. var $html_debug=0;
  59. var $support_cookies=1;
  60. var $cookies=array();
  61. var $error="";
  62. var $error_code = HTTP_CLIENT_ERROR_NO_ERROR;
  63. var $exclude_address="";
  64. var $follow_redirect=0;
  65. var $redirection_limit=5;
  66. var $response_status="";
  67. var $response_message="";
  68. var $file_buffer_length=8000;
  69. var $force_multipart_form_post=0;
  70. var $prefer_curl = 0;
  71. var $keep_alive = 1;
  72. var $sasl_authenticate = 1;
  73. /* private variables - DO NOT ACCESS */
  74. var $state="Disconnected";
  75. var $use_curl=0;
  76. var $connection=0;
  77. var $content_length=0;
  78. var $response="";
  79. var $read_response=0;
  80. var $read_length=0;
  81. var $request_host="";
  82. var $next_token="";
  83. var $redirection_level=0;
  84. var $chunked=0;
  85. var $remaining_chunk=0;
  86. var $last_chunk_read=0;
  87. var $months=array(
  88. "Jan"=>"01",
  89. "Feb"=>"02",
  90. "Mar"=>"03",
  91. "Apr"=>"04",
  92. "May"=>"05",
  93. "Jun"=>"06",
  94. "Jul"=>"07",
  95. "Aug"=>"08",
  96. "Sep"=>"09",
  97. "Oct"=>"10",
  98. "Nov"=>"11",
  99. "Dec"=>"12");
  100. var $session='';
  101. var $connection_close=0;
  102. var $force_close = 0;
  103. var $connected_host = '';
  104. var $connected_port = -1;
  105. var $connected_ssl = 0;
  106. /* Private methods - DO NOT CALL */
  107. Function Tokenize($string,$separator="")
  108. {
  109. if(!strcmp($separator,""))
  110. {
  111. $separator=$string;
  112. $string=$this->next_token;
  113. }
  114. for($character=0;$character<strlen($separator);$character++)
  115. {
  116. if(GetType($position=strpos($string,$separator[$character]))=="integer")
  117. $found=(IsSet($found) ? min($found,$position) : $position);
  118. }
  119. if(IsSet($found))
  120. {
  121. $this->next_token=substr($string,$found+1);
  122. return(substr($string,0,$found));
  123. }
  124. else
  125. {
  126. $this->next_token="";
  127. return($string);
  128. }
  129. }
  130. Function CookieEncode($value, $name)
  131. {
  132. return($name ? str_replace("=", "%25", $value) : str_replace(";", "%3B", $value));
  133. }
  134. Function SetError($error, $error_code = HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR)
  135. {
  136. $this->error_code = $error_code;
  137. return($this->error=$error);
  138. }
  139. Function SetPHPError($error, &$php_error_message, $error_code = HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR)
  140. {
  141. if(IsSet($php_error_message)
  142. && strlen($php_error_message))
  143. $error.=": ".$php_error_message;
  144. return($this->SetError($error, $error_code));
  145. }
  146. Function SetDataAccessError($error,$check_connection=0)
  147. {
  148. $this->error=$error;
  149. $this->error_code = HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE;
  150. if(!$this->use_curl
  151. && function_exists("socket_get_status"))
  152. {
  153. $status=socket_get_status($this->connection);
  154. if($status["timed_out"])
  155. $this->error.=": data access time out";
  156. elseif($status["eof"])
  157. {
  158. if($check_connection)
  159. $this->error="";
  160. else
  161. $this->error.=": the server disconnected";
  162. }
  163. }
  164. }
  165. Function OutputDebug($message)
  166. {
  167. if($this->log_debug)
  168. error_log($message);
  169. else
  170. {
  171. $message.="\n";
  172. if($this->html_debug)
  173. $message=str_replace("\n","<br />\n",HtmlEntities($message));
  174. echo $message;
  175. flush();
  176. }
  177. }
  178. Function GetLine()
  179. {
  180. for($line="";;)
  181. {
  182. if($this->use_curl)
  183. {
  184. $eol=strpos($this->response,"\n",$this->read_response);
  185. $data=($eol ? substr($this->response,$this->read_response,$eol+1-$this->read_response) : "");
  186. $this->read_response+=strlen($data);
  187. }
  188. else
  189. {
  190. if(feof($this->connection))
  191. {
  192. $this->SetDataAccessError("reached the end of data while reading from the HTTP server connection");
  193. return(0);
  194. }
  195. $data=fgets($this->connection,100);
  196. }
  197. if(GetType($data)!="string"
  198. || strlen($data)==0)
  199. {
  200. $this->SetDataAccessError("it was not possible to read line from the HTTP server");
  201. return(0);
  202. }
  203. $line.=$data;
  204. $length=strlen($line);
  205. if($length
  206. && !strcmp(substr($line,$length-1,1),"\n"))
  207. {
  208. $length-=(($length>=2 && !strcmp(substr($line,$length-2,1),"\r")) ? 2 : 1);
  209. $line=substr($line,0,$length);
  210. if($this->debug)
  211. $this->OutputDebug("S $line");
  212. return($line);
  213. }
  214. }
  215. }
  216. Function PutLine($line)
  217. {
  218. if($this->debug)
  219. $this->OutputDebug("C $line");
  220. if(!fputs($this->connection,$line."\r\n"))
  221. {
  222. $this->SetDataAccessError("it was not possible to send a line to the HTTP server");
  223. return(0);
  224. }
  225. return(1);
  226. }
  227. Function PutData($data)
  228. {
  229. if(strlen($data))
  230. {
  231. if($this->debug)
  232. $this->OutputDebug('C '.$data);
  233. if(!fputs($this->connection,$data))
  234. {
  235. $this->SetDataAccessError("it was not possible to send data to the HTTP server");
  236. return(0);
  237. }
  238. }
  239. return(1);
  240. }
  241. Function FlushData()
  242. {
  243. if(!fflush($this->connection))
  244. {
  245. $this->SetDataAccessError("it was not possible to send data to the HTTP server");
  246. return(0);
  247. }
  248. return(1);
  249. }
  250. Function ReadChunkSize()
  251. {
  252. if($this->remaining_chunk==0)
  253. {
  254. $debug=$this->debug;
  255. if(!$this->debug_response_body)
  256. $this->debug=0;
  257. $line=$this->GetLine();
  258. $this->debug=$debug;
  259. if(GetType($line)!="string")
  260. return($this->SetError("could not read chunk start: ".$this->error, $this->error_code));
  261. $this->remaining_chunk=hexdec($line);
  262. if($this->remaining_chunk == 0)
  263. {
  264. if(!$this->debug_response_body)
  265. $this->debug=0;
  266. $line=$this->GetLine();
  267. $this->debug=$debug;
  268. if(GetType($line)!="string")
  269. return($this->SetError("could not read chunk end: ".$this->error, $this->error_code));
  270. }
  271. }
  272. return("");
  273. }
  274. Function ReadBytes($length)
  275. {
  276. if($this->use_curl)
  277. {
  278. $bytes=substr($this->response,$this->read_response,min($length,strlen($this->response)-$this->read_response));
  279. $this->read_response+=strlen($bytes);
  280. if($this->debug
  281. && $this->debug_response_body
  282. && strlen($bytes))
  283. $this->OutputDebug("S ".$bytes);
  284. }
  285. else
  286. {
  287. if($this->chunked)
  288. {
  289. for($bytes="",$remaining=$length;$remaining;)
  290. {
  291. if(strlen($this->ReadChunkSize()))
  292. return("");
  293. if($this->remaining_chunk==0)
  294. {
  295. $this->last_chunk_read=1;
  296. break;
  297. }
  298. $ask=min($this->remaining_chunk,$remaining);
  299. $chunk=@fread($this->connection,$ask);
  300. $read=strlen($chunk);
  301. if($read==0)
  302. {
  303. $this->SetDataAccessError("it was not possible to read data chunk from the HTTP server");
  304. return("");
  305. }
  306. if($this->debug
  307. && $this->debug_response_body)
  308. $this->OutputDebug("S ".$chunk);
  309. $bytes.=$chunk;
  310. $this->remaining_chunk-=$read;
  311. $remaining-=$read;
  312. if($this->remaining_chunk==0)
  313. {
  314. if(feof($this->connection))
  315. 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));
  316. $data=@fread($this->connection,2);
  317. if(strcmp($data,"\r\n"))
  318. {
  319. $this->SetDataAccessError("it was not possible to read end of data chunk from the HTTP server");
  320. return("");
  321. }
  322. }
  323. }
  324. }
  325. else
  326. {
  327. $bytes=@fread($this->connection,$length);
  328. if(strlen($bytes))
  329. {
  330. if($this->debug
  331. && $this->debug_response_body)
  332. $this->OutputDebug("S ".$bytes);
  333. }
  334. else
  335. $this->SetDataAccessError("it was not possible to read data from the HTTP server", $this->connection_close);
  336. }
  337. }
  338. return($bytes);
  339. }
  340. Function EndOfInput()
  341. {
  342. if($this->use_curl)
  343. return($this->read_response>=strlen($this->response));
  344. if($this->chunked)
  345. return($this->last_chunk_read);
  346. if($this->content_length_set)
  347. return($this->content_length <= $this->read_length);
  348. return(feof($this->connection));
  349. }
  350. Function Resolve($domain, &$ip, $server_type)
  351. {
  352. if(preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/',$domain))
  353. $ip=$domain;
  354. else
  355. {
  356. if($this->debug)
  357. $this->OutputDebug('Resolving '.$server_type.' server domain "'.$domain.'"...');
  358. if(!strcmp($ip=@gethostbyname($domain),$domain))
  359. $ip="";
  360. }
  361. if(strlen($ip)==0
  362. || (strlen($this->exclude_address)
  363. && !strcmp(@gethostbyname($this->exclude_address),$ip)))
  364. return($this->SetError("could not resolve the host domain \"".$domain."\"", HTTP_CLIENT_ERROR_INVALID_SERVER_ADDRESS));
  365. return('');
  366. }
  367. Function Connect($host_name, $host_port, $ssl, $server_type = 'HTTP')
  368. {
  369. $domain=$host_name;
  370. $port = $host_port;
  371. if(strlen($error = $this->Resolve($domain, $ip, $server_type)))
  372. return($error);
  373. if(strlen($this->socks_host_name))
  374. {
  375. switch($this->socks_version)
  376. {
  377. case '4':
  378. $version = 4;
  379. break;
  380. case '5':
  381. $version = 5;
  382. break;
  383. default:
  384. return('it was not specified a supported SOCKS protocol version');
  385. break;
  386. }
  387. $host_ip = $ip;
  388. $port = $this->socks_host_port;
  389. $host_server_type = $server_type;
  390. $server_type = 'SOCKS';
  391. if(strlen($error = $this->Resolve($this->socks_host_name, $ip, $server_type)))
  392. return($error);
  393. }
  394. if($this->debug)
  395. $this->OutputDebug('Connecting to '.$server_type.' server IP '.$ip.' port '.$port.'...');
  396. if($ssl)
  397. $ip="ssl://".$host_name;
  398. if(($this->connection=($this->timeout ? @fsockopen($ip, $port, $errno, $error, $this->timeout) : @fsockopen($ip, $port, $errno)))==0)
  399. {
  400. $error_code = HTTP_CLIENT_ERROR_CANNOT_CONNECT;
  401. switch($errno)
  402. {
  403. case -3:
  404. return($this->SetError("socket could not be created", $error_code));
  405. case -4:
  406. return($this->SetError("dns lookup on hostname \"".$host_name."\" failed", $error_code));
  407. case -5:
  408. return($this->SetError("connection refused or timed out", $error_code));
  409. case -6:
  410. return($this->SetError("fdopen() call failed", $error_code));
  411. case -7:
  412. return($this->SetError("setvbuf() call failed", $error_code));
  413. default:
  414. return($this->SetPHPError($errno." could not connect to the host \"".$host_name."\"",$php_errormsg, $error_code));
  415. }
  416. }
  417. else
  418. {
  419. if($this->data_timeout
  420. && function_exists("socket_set_timeout"))
  421. socket_set_timeout($this->connection,$this->data_timeout,0);
  422. if(strlen($this->socks_host_name))
  423. {
  424. if($this->debug)
  425. $this->OutputDebug('Connected to the SOCKS server '.$this->socks_host_name);
  426. $send_error = 'it was not possible to send data to the SOCKS server';
  427. $receive_error = 'it was not possible to receive data from the SOCKS server';
  428. switch($version)
  429. {
  430. case 4:
  431. $command = 1;
  432. $user = '';
  433. if(!fputs($this->connection, chr($version).chr($command).pack('nN', $host_port, ip2long($host_ip)).$user.Chr(0)))
  434. $error = $this->SetDataAccessError($send_error);
  435. else
  436. {
  437. $response = fgets($this->connection, 9);
  438. if(strlen($response) != 8)
  439. $error = $this->SetDataAccessError($receive_error);
  440. else
  441. {
  442. $socks_errors = array(
  443. "\x5a"=>'',
  444. "\x5b"=>'request rejected',
  445. "\x5c"=>'request failed because client is not running identd (or not reachable from the server)',
  446. "\x5d"=>'request failed because client\'s identd could not confirm the user ID string in the request',
  447. );
  448. $error_code = $response[1];
  449. $error = (IsSet($socks_errors[$error_code]) ? $socks_errors[$error_code] : 'unknown');
  450. if(strlen($error))
  451. $error = 'SOCKS error: '.$error;
  452. }
  453. }
  454. break;
  455. case 5:
  456. if($this->debug)
  457. $this->OutputDebug('Negotiating the authentication method ...');
  458. $methods = 1;
  459. $method = 0;
  460. if(!fputs($this->connection, chr($version).chr($methods).chr($method)))
  461. $error = $this->SetDataAccessError($send_error);
  462. else
  463. {
  464. $response = fgets($this->connection, 3);
  465. if(strlen($response) != 2)
  466. $error = $this->SetDataAccessError($receive_error);
  467. elseif(Ord($response[1]) != $method)
  468. $error = 'the SOCKS server requires an authentication method that is not yet supported';
  469. else
  470. {
  471. if($this->debug)
  472. $this->OutputDebug('Connecting to '.$host_server_type.' server IP '.$host_ip.' port '.$host_port.'...');
  473. $command = 1;
  474. $address_type = 1;
  475. if(!fputs($this->connection, chr($version).chr($command)."\x00".chr($address_type).pack('Nn', ip2long($host_ip), $host_port)))
  476. $error = $this->SetDataAccessError($send_error);
  477. else
  478. {
  479. $response = fgets($this->connection, 11);
  480. if(strlen($response) != 10)
  481. $error = $this->SetDataAccessError($receive_error);
  482. else
  483. {
  484. $socks_errors = array(
  485. "\x00"=>'',
  486. "\x01"=>'general SOCKS server failure',
  487. "\x02"=>'connection not allowed by ruleset',
  488. "\x03"=>'Network unreachable',
  489. "\x04"=>'Host unreachable',
  490. "\x05"=>'Connection refused',
  491. "\x06"=>'TTL expired',
  492. "\x07"=>'Command not supported',
  493. "\x08"=>'Address type not supported'
  494. );
  495. $error_code = $response[1];
  496. $error = (IsSet($socks_errors[$error_code]) ? $socks_errors[$error_code] : 'unknown');
  497. if(strlen($error))
  498. $error = 'SOCKS error: '.$error;
  499. }
  500. }
  501. }
  502. }
  503. break;
  504. default:
  505. $error = 'support for SOCKS protocol version '.$this->socks_version.' is not yet implemented';
  506. break;
  507. }
  508. if(strlen($error))
  509. {
  510. fclose($this->connection);
  511. return($error);
  512. }
  513. }
  514. if($this->debug)
  515. $this->OutputDebug("Connected to $host_name");
  516. if(strlen($this->proxy_host_name)
  517. && !strcmp(strtolower($this->protocol), 'https'))
  518. {
  519. if(function_exists('stream_socket_enable_crypto')
  520. && in_array('ssl', stream_get_transports()))
  521. $this->state = "ConnectedToProxy";
  522. else
  523. {
  524. $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.");
  525. $this->state="Connected";
  526. }
  527. }
  528. else
  529. $this->state="Connected";
  530. return("");
  531. }
  532. }
  533. Function Disconnect()
  534. {
  535. if($this->debug)
  536. $this->OutputDebug("Disconnected from ".$this->connected_host);
  537. if($this->use_curl)
  538. {
  539. curl_close($this->connection);
  540. $this->response="";
  541. }
  542. else
  543. fclose($this->connection);
  544. $this->state="Disconnected";
  545. return("");
  546. }
  547. /* Public methods */
  548. Function GetRequestArguments($url, &$arguments)
  549. {
  550. $this->error = '';
  551. $this->error_code = HTTP_CLIENT_ERROR_NO_ERROR;
  552. $arguments=array();
  553. $url = str_replace(' ', '%20', $url);
  554. $parameters=@parse_url($url);
  555. if(!$parameters)
  556. return($this->SetError("it was not specified a valid URL", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  557. if(!IsSet($parameters["scheme"]))
  558. return($this->SetError("it was not specified the protocol type argument", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  559. switch(strtolower($parameters["scheme"]))
  560. {
  561. case "http":
  562. case "https":
  563. $arguments["Protocol"]=$parameters["scheme"];
  564. break;
  565. default:
  566. return($parameters["scheme"]." connection scheme is not yet supported");
  567. }
  568. if(!IsSet($parameters["host"]))
  569. return($this->SetError("it was not specified the connection host argument", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  570. $arguments["HostName"]=$parameters["host"];
  571. $arguments["Headers"]=array("Host"=>$parameters["host"].(IsSet($parameters["port"]) ? ":".$parameters["port"] : ""));
  572. if(IsSet($parameters["user"]))
  573. {
  574. $arguments["AuthUser"]=UrlDecode($parameters["user"]);
  575. if(!IsSet($parameters["pass"]))
  576. $arguments["AuthPassword"]="";
  577. }
  578. if(IsSet($parameters["pass"]))
  579. {
  580. if(!IsSet($parameters["user"]))
  581. $arguments["AuthUser"]="";
  582. $arguments["AuthPassword"]=UrlDecode($parameters["pass"]);
  583. }
  584. if(IsSet($parameters["port"]))
  585. {
  586. if(strcmp($parameters["port"],strval(intval($parameters["port"]))))
  587. return($this->SetError("it was not specified a valid connection host argument", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  588. $arguments["HostPort"]=intval($parameters["port"]);
  589. }
  590. else
  591. $arguments["HostPort"]=0;
  592. $arguments["RequestURI"]=(IsSet($parameters["path"]) ? $parameters["path"] : "/").(IsSet($parameters["query"]) ? "?".$parameters["query"] : "");
  593. if(strlen($this->user_agent))
  594. $arguments["Headers"]["User-Agent"]=$this->user_agent;
  595. if(strlen($this->accept))
  596. $arguments["Headers"]["Accept"]=$this->accept;
  597. return("");
  598. }
  599. Function Open($arguments)
  600. {
  601. if(strlen($this->error))
  602. return($this->error);
  603. $error_code = HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR;
  604. if(IsSet($arguments["HostName"]))
  605. $this->host_name=$arguments["HostName"];
  606. if(IsSet($arguments["HostPort"]))
  607. $this->host_port=$arguments["HostPort"];
  608. if(IsSet($arguments["ProxyHostName"]))
  609. $this->proxy_host_name=$arguments["ProxyHostName"];
  610. if(IsSet($arguments["ProxyHostPort"]))
  611. $this->proxy_host_port=$arguments["ProxyHostPort"];
  612. if(IsSet($arguments["SOCKSHostName"]))
  613. $this->socks_host_name=$arguments["SOCKSHostName"];
  614. if(IsSet($arguments["SOCKSHostPort"]))
  615. $this->socks_host_port=$arguments["SOCKSHostPort"];
  616. if(IsSet($arguments["SOCKSVersion"]))
  617. $this->socks_version=$arguments["SOCKSVersion"];
  618. if(IsSet($arguments["Protocol"]))
  619. $this->protocol=$arguments["Protocol"];
  620. switch(strtolower($this->protocol))
  621. {
  622. case "http":
  623. $default_port=80;
  624. break;
  625. case "https":
  626. $default_port=443;
  627. break;
  628. default:
  629. return($this->SetError("it was not specified a valid connection protocol", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  630. }
  631. if(strlen($this->proxy_host_name)==0)
  632. {
  633. if(strlen($this->host_name)==0)
  634. return($this->SetError("it was not specified a valid hostname", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  635. $host_name=$this->host_name;
  636. $host_port=($this->host_port ? $this->host_port : $default_port);
  637. $server_type = 'HTTP';
  638. }
  639. else
  640. {
  641. $host_name=$this->proxy_host_name;
  642. $host_port=$this->proxy_host_port;
  643. $server_type = 'HTTP proxy';
  644. }
  645. $ssl=(strtolower($this->protocol)=="https" && strlen($this->proxy_host_name)==0);
  646. if($ssl
  647. && strlen($this->socks_host_name))
  648. return($this->SetError('establishing SSL connections via a SOCKS server is not yet supported', HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  649. $this->use_curl=($ssl && $this->prefer_curl && function_exists("curl_init"));
  650. switch($this->state)
  651. {
  652. case 'Connected':
  653. if(!strcmp($host_name, $this->connected_host)
  654. && intval($host_port) == $this->connected_port
  655. && intval($ssl) == $this->connected_ssl)
  656. {
  657. if($this->debug)
  658. $this->OutputDebug("Reusing connection to ".$this->connected_host);
  659. return('');
  660. }
  661. if(strlen($error = $this->Disconnect()))
  662. return($error);
  663. case "Disconnected":
  664. break;
  665. default:
  666. return("1 already connected");
  667. }
  668. if($this->debug)
  669. $this->OutputDebug("Connecting to ".$this->host_name);
  670. if($this->use_curl)
  671. {
  672. $error=(($this->connection=curl_init($this->protocol."://".$this->host_name.($host_port==$default_port ? "" : ":".strval($host_port))."/")) ? "" : "Could not initialize a CURL session");
  673. if(strlen($error)==0)
  674. {
  675. if(IsSet($arguments["SSLCertificateFile"]))
  676. curl_setopt($this->connection,CURLOPT_SSLCERT,$arguments["SSLCertificateFile"]);
  677. if(IsSet($arguments["SSLCertificatePassword"]))
  678. curl_setopt($this->connection,CURLOPT_SSLCERTPASSWD,$arguments["SSLCertificatePassword"]);
  679. if(IsSet($arguments["SSLKeyFile"]))
  680. curl_setopt($this->connection,CURLOPT_SSLKEY,$arguments["SSLKeyFile"]);
  681. if(IsSet($arguments["SSLKeyPassword"]))
  682. curl_setopt($this->connection,CURLOPT_SSLKEYPASSWD,$arguments["SSLKeyPassword"]);
  683. }
  684. $this->state="Connected";
  685. }
  686. else
  687. {
  688. $error="";
  689. if(strlen($this->proxy_host_name)
  690. && (IsSet($arguments["SSLCertificateFile"])
  691. || IsSet($arguments["SSLCertificateFile"])))
  692. $error="establishing SSL connections using certificates or private keys via non-SSL proxies is not supported";
  693. else
  694. {
  695. if($ssl)
  696. {
  697. if(IsSet($arguments["SSLCertificateFile"]))
  698. $error="establishing SSL connections using certificates is only supported when the cURL extension is enabled";
  699. elseif(IsSet($arguments["SSLKeyFile"]))
  700. $error="establishing SSL connections using a private key is only supported when the cURL extension is enabled";
  701. else
  702. {
  703. $version=explode(".",function_exists("phpversion") ? phpversion() : "3.0.7");
  704. $php_version=intval($version[0])*1000000+intval($version[1])*1000+intval($version[2]);
  705. if($php_version<4003000)
  706. $error="establishing SSL connections requires at least PHP version 4.3.0 or having the cURL extension enabled";
  707. elseif(!function_exists("extension_loaded")
  708. || !extension_loaded("openssl"))
  709. $error="establishing SSL connections requires the OpenSSL extension enabled";
  710. }
  711. }
  712. if(strlen($error)==0)
  713. {
  714. $error=$this->Connect($host_name, $host_port, $ssl, $server_type);
  715. $error_code = $this->error_code;
  716. }
  717. }
  718. }
  719. if(strlen($error))
  720. return($this->SetError($error, $error_code));
  721. $this->session=md5(uniqid(""));
  722. $this->connected_host = $host_name;
  723. $this->connected_port = intval($host_port);
  724. $this->connected_ssl = intval($ssl);
  725. return("");
  726. }
  727. Function Close($force = 0)
  728. {
  729. if($this->state=="Disconnected")
  730. return("1 already disconnected");
  731. if(!$this->force_close
  732. && $this->keep_alive
  733. && !$force
  734. && $this->state == 'ResponseReceived')
  735. {
  736. if($this->debug)
  737. $this->OutputDebug('Keeping the connection alive to '.$this->connected_host);
  738. $this->state = 'Connected';
  739. return('');
  740. }
  741. return($this->Disconnect());
  742. }
  743. Function PickCookies(&$cookies,$secure)
  744. {
  745. if(IsSet($this->cookies[$secure]))
  746. {
  747. $now=gmdate("Y-m-d H-i-s");
  748. for($domain=0,Reset($this->cookies[$secure]);$domain<count($this->cookies[$secure]);Next($this->cookies[$secure]),$domain++)
  749. {
  750. $domain_pattern=Key($this->cookies[$secure]);
  751. $match=strlen($this->request_host)-strlen($domain_pattern);
  752. if($match>=0
  753. && !strcmp($domain_pattern,substr($this->request_host,$match))
  754. && ($match==0
  755. || $domain_pattern[0]=="."
  756. || $this->request_host[$match-1]=="."))
  757. {
  758. 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++)
  759. {
  760. $path=Key($this->cookies[$secure][$domain_pattern]);
  761. if(strlen($this->request_uri)>=strlen($path)
  762. && substr($this->request_uri,0,strlen($path))==$path)
  763. {
  764. 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++)
  765. {
  766. $cookie_name=Key($this->cookies[$secure][$domain_pattern][$path]);
  767. $expires=$this->cookies[$secure][$domain_pattern][$path][$cookie_name]["expires"];
  768. if($expires==""
  769. || strcmp($now,$expires)<0)
  770. $cookies[$cookie_name]=$this->cookies[$secure][$domain_pattern][$path][$cookie_name];
  771. }
  772. }
  773. }
  774. }
  775. }
  776. }
  777. }
  778. Function GetFileDefinition($file, &$definition)
  779. {
  780. $name="";
  781. if(IsSet($file["FileName"]))
  782. $name=basename($file["FileName"]);
  783. if(IsSet($file["Name"]))
  784. $name=$file["Name"];
  785. if(strlen($name)==0)
  786. return("it was not specified the file part name");
  787. if(IsSet($file["Content-Type"]))
  788. {
  789. $content_type=$file["Content-Type"];
  790. $type=$this->Tokenize(strtolower($content_type),"/");
  791. $sub_type=$this->Tokenize("");
  792. switch($type)
  793. {
  794. case "text":
  795. case "image":
  796. case "audio":
  797. case "video":
  798. case "application":
  799. case "message":
  800. break;
  801. case "automatic":
  802. switch($sub_type)
  803. {
  804. case "name":
  805. switch(GetType($dot=strrpos($name,"."))=="integer" ? strtolower(substr($name,$dot)) : "")
  806. {
  807. case ".xls":
  808. $content_type="application/excel";
  809. break;
  810. case ".hqx":
  811. $content_type="application/macbinhex40";
  812. break;
  813. case ".doc":
  814. case ".dot":
  815. case ".wrd":
  816. $content_type="application/msword";
  817. break;
  818. case ".pdf":
  819. $content_type="application/pdf";
  820. break;
  821. case ".pgp":
  822. $content_type="application/pgp";
  823. break;
  824. case ".ps":
  825. case ".eps":
  826. case ".ai":
  827. $content_type="application/postscript";
  828. break;
  829. case ".ppt":
  830. $content_type="application/powerpoint";
  831. break;
  832. case ".rtf":
  833. $content_type="application/rtf";
  834. break;
  835. case ".tgz":
  836. case ".gtar":
  837. $content_type="application/x-gtar";
  838. break;
  839. case ".gz":
  840. $content_type="application/x-gzip";
  841. break;
  842. case ".php":
  843. case ".php3":
  844. $content_type="application/x-httpd-php";
  845. break;
  846. case ".js":
  847. $content_type="application/x-javascript";
  848. break;
  849. case ".ppd":
  850. case ".psd":
  851. $content_type="application/x-photoshop";
  852. break;
  853. case ".swf":
  854. case ".swc":
  855. case ".rf":
  856. $content_type="application/x-shockwave-flash";
  857. break;
  858. case ".tar":
  859. $content_type="application/x-tar";
  860. break;
  861. case ".zip":
  862. $content_type="application/zip";
  863. break;
  864. case ".mid":
  865. case ".midi":
  866. case ".kar":
  867. $content_type="audio/midi";
  868. break;
  869. case ".mp2":
  870. case ".mp3":
  871. case ".mpga":
  872. $content_type="audio/mpeg";
  873. break;
  874. case ".ra":
  875. $content_type="audio/x-realaudio";
  876. break;
  877. case ".wav":
  878. $content_type="audio/wav";
  879. break;
  880. case ".bmp":
  881. $content_type="image/bitmap";
  882. break;
  883. case ".gif":
  884. $content_type="image/gif";
  885. break;
  886. case ".iff":
  887. $content_type="image/iff";
  888. break;
  889. case ".jb2":
  890. $content_type="image/jb2";
  891. break;
  892. case ".jpg":
  893. case ".jpe":
  894. case ".jpeg":
  895. $content_type="image/jpeg";
  896. break;
  897. case ".jpx":
  898. $content_type="image/jpx";
  899. break;
  900. case ".png":
  901. $content_type="image/png";
  902. break;
  903. case ".tif":
  904. case ".tiff":
  905. $content_type="image/tiff";
  906. break;
  907. case ".wbmp":
  908. $content_type="image/vnd.wap.wbmp";
  909. break;
  910. case ".xbm":
  911. $content_type="image/xbm";
  912. break;
  913. case ".css":
  914. $content_type="text/css";
  915. break;
  916. case ".txt":
  917. $content_type="text/plain";
  918. break;
  919. case ".htm":
  920. case ".html":
  921. $content_type="text/html";
  922. break;
  923. case ".xml":
  924. $content_type="text/xml";
  925. break;
  926. case ".mpg":
  927. case ".mpe":
  928. case ".mpeg":
  929. $content_type="video/mpeg";
  930. break;
  931. case ".qt":
  932. case ".mov":
  933. $content_type="video/quicktime";
  934. break;
  935. case ".avi":
  936. $content_type="video/x-ms-video";
  937. break;
  938. case ".eml":
  939. $content_type="message/rfc822";
  940. break;
  941. default:
  942. $content_type="application/octet-stream";
  943. break;
  944. }
  945. break;
  946. default:
  947. return($content_type." is not a supported automatic content type detection method");
  948. }
  949. break;
  950. default:
  951. return($content_type." is not a supported file content type");
  952. }
  953. }
  954. else
  955. $content_type="application/octet-stream";
  956. $definition=array(
  957. "Content-Type"=>$content_type,
  958. "NAME"=>$name
  959. );
  960. if(IsSet($file["FileName"]))
  961. {
  962. if(GetType($length=@filesize($file["FileName"]))!="integer")
  963. {
  964. $error="it was not possible to determine the length of the file ".$file["FileName"];
  965. if(IsSet($php_errormsg)
  966. && strlen($php_errormsg))
  967. $error.=": ".$php_errormsg;
  968. if(!file_exists($file["FileName"]))
  969. $error="it was not possible to access the file ".$file["FileName"];
  970. return($error);
  971. }
  972. $definition["FILENAME"]=$file["FileName"];
  973. $definition["Content-Length"]=$length;
  974. }
  975. elseif(IsSet($file["Data"]))
  976. $definition["Content-Length"]=strlen($definition["DATA"]=$file["Data"]);
  977. else
  978. return("it was not specified a valid file name");
  979. return("");
  980. }
  981. Function ConnectFromProxy($arguments, &$headers)
  982. {
  983. if(!$this->PutLine('CONNECT '.$this->host_name.':'.($this->host_port ? $this->host_port : 443).' HTTP/1.0')
  984. || (strlen($this->user_agent)
  985. && !$this->PutLine('User-Agent: '.$this->user_agent))
  986. || (strlen($this->accept)
  987. && !$this->PutLine('Accept: '.$this->accept))
  988. || (IsSet($arguments['Headers']['Proxy-Authorization'])
  989. && !$this->PutLine('Proxy-Authorization: '.$arguments['Headers']['Proxy-Authorization']))
  990. || !$this->PutLine(''))
  991. {
  992. $this->Disconnect();
  993. return($this->error);
  994. }
  995. $this->state = "ConnectSent";
  996. if(strlen($error=$this->ReadReplyHeadersResponse($headers)))
  997. return($error);
  998. $proxy_authorization="";
  999. while(!strcmp($this->response_status, "100"))
  1000. {
  1001. $this->state="ConnectSent";
  1002. if(strlen($error=$this->ReadReplyHeadersResponse($headers)))
  1003. return($error);
  1004. }
  1005. switch($this->response_status)
  1006. {
  1007. case "200":
  1008. if(!@stream_socket_enable_crypto($this->connection, 1, STREAM_CRYPTO_METHOD_SSLv23_CLIENT))
  1009. {
  1010. $this->SetPHPError('it was not possible to start a SSL encrypted connection via this proxy', $php_errormsg, HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE);
  1011. $this->Disconnect();
  1012. return($this->error);
  1013. }
  1014. $this->state = "Connected";
  1015. break;
  1016. case "407":
  1017. 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)))
  1018. return($error);
  1019. break;
  1020. default:
  1021. return($this->SetError("unable to send request via proxy", HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  1022. }
  1023. return("");
  1024. }
  1025. Function SendRequest($arguments)
  1026. {
  1027. if(strlen($this->error))
  1028. return($this->error);
  1029. if(IsSet($arguments["ProxyUser"]))
  1030. $this->proxy_request_user=$arguments["ProxyUser"];
  1031. elseif(IsSet($this->proxy_user))
  1032. $this->proxy_request_user=$this->proxy_user;
  1033. if(IsSet($arguments["ProxyPassword"]))
  1034. $this->proxy_request_password=$arguments["ProxyPassword"];
  1035. elseif(IsSet($this->proxy_password))
  1036. $this->proxy_request_password=$this->proxy_password;
  1037. if(IsSet($arguments["ProxyRealm"]))
  1038. $this->proxy_request_realm=$arguments["ProxyRealm"];
  1039. elseif(IsSet($this->proxy_realm))
  1040. $this->proxy_request_realm=$this->proxy_realm;
  1041. if(IsSet($arguments["ProxyWorkstation"]))
  1042. $this->proxy_request_workstation=$arguments["ProxyWorkstation"];
  1043. elseif(IsSet($this->proxy_workstation))
  1044. $this->proxy_request_workstation=$this->proxy_workstation;
  1045. switch($this->state)
  1046. {
  1047. case "Disconnected":
  1048. return($this->SetError("connection was not yet established", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1049. case "Connected":
  1050. $connect = 0;
  1051. break;
  1052. case "ConnectedToProxy":
  1053. if(strlen($error = $this->ConnectFromProxy($arguments, $headers)))
  1054. return($error);
  1055. $connect = 1;
  1056. break;
  1057. default:
  1058. return($this->SetError("can not send request in the current connection state", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1059. }
  1060. if(IsSet($arguments["RequestMethod"]))
  1061. $this->request_method=$arguments["RequestMethod"];
  1062. if(IsSet($arguments["User-Agent"]))
  1063. $this->user_agent=$arguments["User-Agent"];
  1064. if(!IsSet($arguments["Headers"]["User-Agent"])
  1065. && strlen($this->user_agent))
  1066. $arguments["Headers"]["User-Agent"]=$this->user_agent;
  1067. if(IsSet($arguments["KeepAlive"]))
  1068. $this->keep_alive=intval($arguments["KeepAlive"]);
  1069. if(!IsSet($arguments["Headers"]["Connection"])
  1070. && $this->keep_alive)
  1071. $arguments["Headers"]["Connection"]='Keep-Alive';
  1072. if(IsSet($arguments["Accept"]))
  1073. $this->user_agent=$arguments["Accept"];
  1074. if(!IsSet($arguments["Headers"]["Accept"])
  1075. && strlen($this->accept))
  1076. $arguments["Headers"]["Accept"]=$this->accept;
  1077. if(strlen($this->request_method)==0)
  1078. return($this->SetError("it was not specified a valid request method", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1079. if(IsSet($arguments["RequestURI"]))
  1080. $this->request_uri=$arguments["RequestURI"];
  1081. if(strlen($this->request_uri)==0
  1082. || substr($this->request_uri,0,1)!="/")
  1083. return($this->SetError("it was not specified a valid request URI", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1084. $this->request_arguments=$arguments;
  1085. $this->request_headers=(IsSet($arguments["Headers"]) ? $arguments["Headers"] : array());
  1086. $body_length=0;
  1087. $this->request_body="";
  1088. $get_body=1;
  1089. if($this->request_method=="POST"
  1090. || $this->request_method=="PUT")
  1091. {
  1092. if(IsSet($arguments['StreamRequest']))
  1093. {
  1094. $get_body = 0;
  1095. $this->request_headers["Transfer-Encoding"]="chunked";
  1096. }
  1097. elseif(IsSet($arguments["PostFiles"])
  1098. || ($this->force_multipart_form_post
  1099. && IsSet($arguments["PostValues"])))
  1100. {
  1101. $boundary="--".md5(uniqid(time()));
  1102. $this->request_headers["Content-Type"]="multipart/form-data; boundary=".$boundary.(IsSet($arguments["CharSet"]) ? "; charset=".$arguments["CharSet"] : "");
  1103. $post_parts=array();
  1104. if(IsSet($arguments["PostValues"]))
  1105. {
  1106. $values=$arguments["PostValues"];
  1107. if(GetType($values)!="array")
  1108. return($this->SetError("it was not specified a valid POST method values array", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1109. for(Reset($values),$value=0;$value<count($values);Next($values),$value++)
  1110. {
  1111. $input=Key($values);
  1112. $headers="--".$boundary."\r\nContent-Disposition: form-data; name=\"".$input."\"\r\n\r\n";
  1113. $data=$values[$input];
  1114. $post_parts[]=array("HEADERS"=>$headers,"DATA"=>$data);
  1115. $body_length+=strlen($headers)+strlen($data)+strlen("\r\n");
  1116. }
  1117. }
  1118. $body_length+=strlen("--".$boundary."--\r\n");
  1119. $files=(IsSet($arguments["PostFiles"]) ? $arguments["PostFiles"] : array());
  1120. Reset($files);
  1121. $end=(GetType($input=Key($files))!="string");
  1122. for(;!$end;)
  1123. {
  1124. if(strlen($error=$this->GetFileDefinition($files[$input],$definition)))
  1125. return("3 ".$error);
  1126. $headers="--".$boundary."\r\nContent-Disposition: form-data; name=\"".$input."\"; filename=\"".$definition["NAME"]."\"\r\nContent-Type: ".$definition["Content-Type"]."\r\n\r\n";
  1127. $part=count($post_parts);
  1128. $post_parts[$part]=array("HEADERS"=>$headers);
  1129. if(IsSet($definition["FILENAME"]))
  1130. {
  1131. $post_parts[$part]["FILENAME"]=$definition["FILENAME"];
  1132. $data="";
  1133. }
  1134. else
  1135. $data=$definition["DATA"];
  1136. $post_parts[$part]["DATA"]=$data;
  1137. $body_length+=strlen($headers)+$definition["Content-Length"]+strlen("\r\n");
  1138. Next($files);
  1139. $end=(GetType($input=Key($files))!="string");
  1140. }
  1141. $get_body=0;
  1142. }
  1143. elseif(IsSet($arguments["PostValues"]))
  1144. {
  1145. $values=$arguments["PostValues"];
  1146. if(GetType($values)!="array")
  1147. return($this->SetError("it was not specified a valid POST method values array", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1148. for(Reset($values),$value=0;$value<count($values);Next($values),$value++)
  1149. {
  1150. $k=Key($values);
  1151. if(GetType($values[$k])=="array")
  1152. {
  1153. for($v = 0; $v < count($values[$k]); $v++)
  1154. {
  1155. if($value+$v>0)
  1156. $this->request_body.="&";
  1157. $this->request_body.=UrlEncode($k)."=".UrlEncode($values[$k][$v]);
  1158. }
  1159. }
  1160. else
  1161. {
  1162. if($value>0)
  1163. $this->request_body.="&";
  1164. $this->request_body.=UrlEncode($k)."=".UrlEncode($values[$k]);
  1165. }
  1166. }
  1167. $this->request_headers["Content-Type"]="application/x-www-form-urlencoded".(IsSet($arguments["CharSet"]) ? "; charset=".$arguments["CharSet"] : "");
  1168. $get_body=0;
  1169. }
  1170. }
  1171. if($get_body
  1172. && (IsSet($arguments["Body"])
  1173. || IsSet($arguments["BodyStream"])))
  1174. {
  1175. if(IsSet($arguments["Body"]))
  1176. $this->request_body=$arguments["Body"];
  1177. else
  1178. {
  1179. $stream=$arguments["BodyStream"];
  1180. $this->request_body="";
  1181. for($part=0; $part<count($stream); $part++)
  1182. {
  1183. if(IsSet($stream[$part]["Data"]))
  1184. $this->request_body.=$stream[$part]["Data"];
  1185. elseif(IsSet($stream[$part]["File"]))
  1186. {
  1187. if(!($file=@fopen($stream[$part]["File"],"rb")))
  1188. return($this->SetPHPError("could not open upload file ".$stream[$part]["File"], $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE));
  1189. while(!feof($file))
  1190. {
  1191. if(GetType($block=@fread($file,$this->file_buffer_length))!="string")
  1192. {
  1193. $error=$this->SetPHPError("could not read body stream file ".$stream[$part]["File"], $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  1194. fclose($file);
  1195. return($error);
  1196. }
  1197. $this->request_body.=$block;
  1198. }
  1199. fclose($file);
  1200. }
  1201. else
  1202. return("5 it was not specified a valid file or data body stream element at position ".$part);
  1203. }
  1204. }
  1205. if(!IsSet($this->request_headers["Content-Type"]))
  1206. $this->request_headers["Content-Type"]="application/octet-stream".(IsSet($arguments["CharSet"]) ? "; charset=".$arguments["CharSet"] : "");
  1207. }
  1208. if(IsSet($arguments["AuthUser"]))
  1209. $this->request_user=$arguments["AuthUser"];
  1210. elseif(IsSet($this->user))
  1211. $this->request_user=$this->user;
  1212. if(IsSet($arguments["AuthPassword"]))
  1213. $this->request_password=$arguments["AuthPassword"];
  1214. elseif(IsSet($this->password))
  1215. $this->request_password=$this->password;
  1216. if(IsSet($arguments["AuthRealm"]))
  1217. $this->request_realm=$arguments["AuthRealm"];
  1218. elseif(IsSet($this->realm))
  1219. $this->request_realm=$this->realm;
  1220. if(IsSet($arguments["AuthWorkstation"]))
  1221. $this->request_workstation=$arguments["AuthWorkstation"];
  1222. elseif(IsSet($this->workstation))
  1223. $this->request_workstation=$this->workstation;
  1224. if(strlen($this->proxy_host_name)==0
  1225. || $connect)
  1226. $request_uri=$this->request_uri;
  1227. else
  1228. {
  1229. switch(strtolower($this->protocol))
  1230. {
  1231. case "http":
  1232. $default_port=80;
  1233. break;
  1234. case "https":
  1235. $default_port=443;
  1236. break;
  1237. }
  1238. $request_uri=strtolower($this->protocol)."://".$this->host_name.(($this->host_port==0 || $this->host_port==$default_port) ? "" : ":".$this->host_port).$this->request_uri;
  1239. }
  1240. if($this->use_curl)
  1241. {
  1242. $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"));
  1243. $curl_version=100000*intval($this->Tokenize($version,"."))+1000*intval($this->Tokenize("."))+intval($this->Tokenize(""));
  1244. $protocol_version=($curl_version<713002 ? "1.0" : $this->protocol_version);
  1245. }
  1246. else
  1247. $protocol_version=$this->protocol_version;
  1248. $this->request=$this->request_method." ".$request_uri." HTTP/".$protocol_version;
  1249. if($body_length
  1250. || ($body_length=strlen($this->request_body))
  1251. || !strcmp($this->request_method, 'POST'))
  1252. $this->request_headers["Content-Length"]=$body_length;
  1253. for($headers=array(),$host_set=0,Reset($this->request_headers),$header=0;$header<count($this->request_headers);Next($this->request_headers),$header++)
  1254. {
  1255. $header_name=Key($this->request_headers);
  1256. $header_value=$this->request_headers[$header_name];
  1257. if(GetType($header_value)=="array")
  1258. {
  1259. for(Reset($header_value),$value=0;$value<count($header_value);Next($header_value),$value++)
  1260. $headers[]=$header_name.": ".$header_value[Key($header_value)];
  1261. }
  1262. else
  1263. $headers[]=$header_name.": ".$header_value;
  1264. if(strtolower(Key($this->request_headers))=="host")
  1265. {
  1266. $this->request_host=strtolower($header_value);
  1267. $host_set=1;
  1268. }
  1269. }
  1270. if(!$host_set)
  1271. {
  1272. $headers[]="Host: ".$this->host_name;
  1273. $this->request_host=strtolower($this->host_name);
  1274. }
  1275. if(count($this->cookies))
  1276. {
  1277. $cookies=array();
  1278. $this->PickCookies($cookies,0);
  1279. if(strtolower($this->protocol)=="https")
  1280. $this->PickCookies($cookies,1);
  1281. if(count($cookies))
  1282. {
  1283. $h=count($headers);
  1284. $headers[$h]="Cookie:";
  1285. for(Reset($cookies),$cookie=0;$cookie<count($cookies);Next($cookies),$cookie++)
  1286. {
  1287. $cookie_name=Key($cookies);
  1288. $headers[$h].=" ".$cookie_name."=".$cookies[$cookie_name]["value"].";";
  1289. }
  1290. }
  1291. }
  1292. $next_state = "RequestSent";
  1293. if($this->use_curl)
  1294. {
  1295. if(IsSet($arguments['StreamRequest']))
  1296. return($this->SetError("Streaming request data is not supported when using Curl", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1297. if($body_length
  1298. && strlen($this->request_body)==0)
  1299. {
  1300. for($request_body="",$success=1,$part=0;$part<count($post_parts);$part++)
  1301. {
  1302. $request_body.=$post_parts[$part]["HEADERS"].$post_parts[$part]["DATA"];
  1303. if(IsSet($post_parts[$part]["FILENAME"]))
  1304. {
  1305. if(!($file=@fopen($post_parts[$part]["FILENAME"],"rb")))
  1306. {
  1307. $this->SetPHPError("could not open upload file ".$post_parts[$part]["FILENAME"], $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  1308. $success=0;
  1309. break;
  1310. }
  1311. while(!feof($file))
  1312. {
  1313. if(GetType($block=@fread($file,$this->file_buffer_length))!="string")
  1314. {
  1315. $this->SetPHPError("could not read upload file", $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  1316. $success=0;
  1317. break;
  1318. }
  1319. $request_body.=$block;
  1320. }
  1321. fclose($file);
  1322. if(!$success)
  1323. break;
  1324. }
  1325. $request_body.="\r\n";
  1326. }
  1327. $request_body.="--".$boundary."--\r\n";
  1328. }
  1329. else
  1330. $request_body=$this->request_body;
  1331. curl_setopt($this->connection,CURLOPT_HEADER,1);
  1332. curl_setopt($this->connection,CURLOPT_RETURNTRANSFER,1);
  1333. if($this->timeout)
  1334. curl_setopt($this->connection,CURLOPT_TIMEOUT,$this->timeout);
  1335. curl_setopt($this->connection,CURLOPT_SSL_VERIFYPEER,0);
  1336. curl_setopt($this->connection,CURLOPT_SSL_VERIFYHOST,0);
  1337. $request=$this->request."\r\n".implode("\r\n",$headers)."\r\n\r\n".$request_body;
  1338. curl_setopt($this->connection,CURLOPT_CUSTOMREQUEST,$request);
  1339. if($this->debug)
  1340. $this->OutputDebug("C ".$request);
  1341. if(!($success=(strlen($this->response=curl_exec($this->connection))!=0)))
  1342. {
  1343. $error=curl_error($this->connection);
  1344. $this->SetError("Could not execute the request".(strlen($error) ? ": ".$error : ""), HTTP_CLIENT_ERROR_PROTOCOL_FAILURE);
  1345. }
  1346. }
  1347. else
  1348. {
  1349. if(($success=$this->PutLine($this->request)))
  1350. {
  1351. for($header=0;$header<count($headers);$header++)
  1352. {
  1353. if(!$success=$this->PutLine($headers[$header]))
  1354. break;
  1355. }
  1356. if($success
  1357. && ($success=$this->PutLine("")))
  1358. {
  1359. if(IsSet($arguments['StreamRequest']))
  1360. $next_state = "SendingRequestBody";
  1361. elseif($body_length)
  1362. {
  1363. if(strlen($this->request_body))
  1364. $success=$this->PutData($this->request_body);
  1365. else
  1366. {
  1367. for($part=0;$part<count($post_parts);$part++)
  1368. {
  1369. if(!($success=$this->PutData($post_parts[$part]["HEADERS"]))
  1370. || !($success=$this->PutData($post_parts[$part]["DATA"])))
  1371. break;
  1372. if(IsSet($post_parts[$part]["FILENAME"]))
  1373. {
  1374. if(!($file=@fopen($post_parts[$part]["FILENAME"],"rb")))
  1375. {
  1376. $this->SetPHPError("could not open upload file ".$post_parts[$part]["FILENAME"], $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  1377. $success=0;
  1378. break;
  1379. }
  1380. while(!feof($file))
  1381. {
  1382. if(GetType($block=@fread($file,$this->file_buffer_length))!="string")
  1383. {
  1384. $this->SetPHPError("could not read upload file", $php_errormsg, HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  1385. $success=0;
  1386. break;
  1387. }
  1388. if(!($success=$this->PutData($block)))
  1389. break;
  1390. }
  1391. fclose($file);
  1392. if(!$success)
  1393. break;
  1394. }
  1395. if(!($success=$this->PutLine("")))
  1396. break;
  1397. }
  1398. if($success)
  1399. $success=$this->PutLine("--".$boundary."--");
  1400. }
  1401. if($success)
  1402. $sucess=$this->FlushData();
  1403. }
  1404. }
  1405. }
  1406. }
  1407. if(!$success)
  1408. return($this->SetError("could not send the HTTP request: ".$this->error, $this->error_code));
  1409. $this->state=$next_state;
  1410. return("");
  1411. }
  1412. Function SetCookie($name, $value, $expires="" , $path="/" , $domain="" , $secure=0, $verbatim=0)
  1413. {
  1414. if(strlen($this->error))
  1415. return($this->error);
  1416. if(strlen($name)==0)
  1417. return($this->SetError("it was not specified a valid cookie name", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1418. if(strlen($path)==0
  1419. || strcmp($path[0],"/"))
  1420. return($this->SetError($path." is not a valid path for setting cookie ".$name, HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1421. if($domain==""
  1422. || !strpos($domain,".",$domain[0]=="." ? 1 : 0))
  1423. return($this->SetError($domain." is not a valid domain for setting cookie ".$name, HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1424. $domain=strtolower($domain);
  1425. if(!strcmp($domain[0],"."))
  1426. $domain=substr($domain,1);
  1427. if(!$verbatim)
  1428. {
  1429. $name=$this->CookieEncode($name,1);
  1430. $value=$this->CookieEncode($value,0);
  1431. }
  1432. $secure=intval($secure);
  1433. $this->cookies[$secure][$domain][$path][$name]=array(
  1434. "name"=>$name,
  1435. "value"=>$value,
  1436. "domain"=>$domain,
  1437. "path"=>$path,
  1438. "expires"=>$expires,
  1439. "secure"=>$secure
  1440. );
  1441. return("");
  1442. }
  1443. Function SendRequestBody($data, $end_of_data)
  1444. {
  1445. if(strlen($this->error))
  1446. return($this->error);
  1447. switch($this->state)
  1448. {
  1449. case "Disconnected":
  1450. return($this->SetError("connection was not yet established", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1451. case "Connected":
  1452. case "ConnectedToProxy":
  1453. return($this->SetError("request was not sent", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1454. case "SendingRequestBody":
  1455. break;
  1456. case "RequestSent":
  1457. return($this->SetError("request body was already sent", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1458. default:
  1459. return($this->SetError("can not send the request body in the current connection state", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1460. }
  1461. $length = strlen($data);
  1462. if($length)
  1463. {
  1464. $size = dechex($length)."\r\n";
  1465. if(!$this->PutData($size)
  1466. || !$this->PutData($data))
  1467. return($this->error);
  1468. }
  1469. if($end_of_data)
  1470. {
  1471. $size = "0\r\n";
  1472. if(!$this->PutData($size))
  1473. return($this->error);
  1474. $this->state = "RequestSent";
  1475. }
  1476. return("");
  1477. }
  1478. Function ReadReplyHeadersResponse(&$headers)
  1479. {
  1480. $headers=array();
  1481. if(strlen($this->error))
  1482. return($this->error);
  1483. switch($this->state)
  1484. {
  1485. case "Disconnected":
  1486. return($this->SetError("connection was not yet established", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1487. case "Connected":
  1488. return($this->SetError("request was not sent", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1489. case "ConnectedToProxy":
  1490. return($this->SetError("connection from the remote server from the proxy was not yet established", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1491. case "SendingRequestBody":
  1492. return($this->SetError("request body data was not completely sent", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1493. case "ConnectSent":
  1494. $connect = 1;
  1495. break;
  1496. case "RequestSent":
  1497. $connect = 0;
  1498. break;
  1499. default:
  1500. return($this->SetError("can not get request headers in the current connection state", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1501. }
  1502. $this->content_length=$this->read_length=$this->read_response=$this->remaining_chunk=0;
  1503. $this->content_length_set=$this->chunked=$this->last_chunk_read=$chunked=0;
  1504. $this->force_close = $this->connection_close=0;
  1505. for($this->response_status="";;)
  1506. {
  1507. $line=$this->GetLine();
  1508. if(GetType($line)!="string")
  1509. return($this->SetError("could not read request reply: ".$this->error, $this->error_code));
  1510. if(strlen($this->response_status)==0)
  1511. {
  1512. if(!preg_match($match="/^http\\/[0-9]+\\.[0-9]+[ \t]+([0-9]+)[ \t]*(.*)\$/i",$line,$matches))
  1513. return($this->SetError("it was received an unexpected HTTP response status", HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  1514. $this->response_status=$matches[1];
  1515. $this->response_message=$matches[2];
  1516. }
  1517. if($line=="")
  1518. {
  1519. if(strlen($this->response_status)==0)
  1520. return($this->SetError("it was not received HTTP response status", HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  1521. $this->state=($connect ? "GotConnectHeaders" : "GotReplyHeaders");
  1522. break;
  1523. }
  1524. $header_name=strtolower($this->Tokenize($line,":"));
  1525. $header_value=Trim(Chop($this->Tokenize("\r\n")));
  1526. if(IsSet($headers[$header_name]))
  1527. {
  1528. if(GetType($headers[$header_name])=="string")
  1529. $headers[$header_name]=array($headers[$header_name]);

Large files files are truncated, but you can click here to view the full file