PageRenderTime 49ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/public/external/pydio/core/classes/http_class/http_class.php

https://github.com/costinu/cms
PHP | 1883 lines | 1832 code | 42 blank | 9 comment | 484 complexity | a4cff61c9334d287a97a6faeb4236763 MD5 | raw file
Possible License(s): BSD-2-Clause, Apache-2.0, LGPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, AGPL-3.0

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.88 2011/10/24 08:26:56 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. public $host_name="";
  19. public $host_port=0;
  20. public $proxy_host_name="";
  21. public $proxy_host_port=80;
  22. public $socks_host_name = '';
  23. public $socks_host_port = 1080;
  24. public $socks_version = '5';
  25. public $protocol="http";
  26. public $request_method="GET";
  27. public $user_agent='httpclient (http://www.phpclasses.org/httpclient $Revision: 1.88 $)';
  28. public $accept='';
  29. public $authentication_mechanism="";
  30. public $user;
  31. public $password;
  32. public $realm;
  33. public $workstation;
  34. public $proxy_authentication_mechanism="";
  35. public $proxy_user;
  36. public $proxy_password;
  37. public $proxy_realm;
  38. public $proxy_workstation;
  39. public $request_uri="";
  40. public $request="";
  41. public $request_headers=array();
  42. public $request_user;
  43. public $request_password;
  44. public $request_realm;
  45. public $request_workstation;
  46. public $proxy_request_user;
  47. public $proxy_request_password;
  48. public $proxy_request_realm;
  49. public $proxy_request_workstation;
  50. public $request_body="";
  51. public $request_arguments=array();
  52. public $protocol_version="1.1";
  53. public $timeout=0;
  54. public $data_timeout=0;
  55. public $debug=0;
  56. public $log_debug=0;
  57. public $debug_response_body=1;
  58. public $html_debug=0;
  59. public $support_cookies=1;
  60. public $cookies=array();
  61. public $error="";
  62. public $error_code = HTTP_CLIENT_ERROR_NO_ERROR;
  63. public $exclude_address="";
  64. public $follow_redirect=0;
  65. public $redirection_limit=5;
  66. public $response_status="";
  67. public $response_message="";
  68. public $file_buffer_length=8000;
  69. public $force_multipart_form_post=0;
  70. public $prefer_curl = 0;
  71. public $keep_alive = 1;
  72. /* private variables - DO NOT ACCESS */
  73. public $state="Disconnected";
  74. public $use_curl=0;
  75. public $connection=0;
  76. public $content_length=0;
  77. public $response="";
  78. public $read_response=0;
  79. public $read_length=0;
  80. public $request_host="";
  81. public $next_token="";
  82. public $redirection_level=0;
  83. public $chunked=0;
  84. public $remaining_chunk=0;
  85. public $last_chunk_read=0;
  86. public $months=array(
  87. "Jan"=>"01",
  88. "Feb"=>"02",
  89. "Mar"=>"03",
  90. "Apr"=>"04",
  91. "May"=>"05",
  92. "Jun"=>"06",
  93. "Jul"=>"07",
  94. "Aug"=>"08",
  95. "Sep"=>"09",
  96. "Oct"=>"10",
  97. "Nov"=>"11",
  98. "Dec"=>"12");
  99. public $session='';
  100. public $connection_close=0;
  101. public $force_close = 0;
  102. public $connected_host = '';
  103. public $connected_port = -1;
  104. public $connected_ssl = 0;
  105. /* Private methods - DO NOT CALL */
  106. public Function Tokenize($string,$separator="")
  107. {
  108. if (!strcmp($separator,"")) {
  109. $separator=$string;
  110. $string=$this->next_token;
  111. }
  112. for ($character=0;$character<strlen($separator);$character++) {
  113. if(GetType($position=strpos($string,$separator[$character]))=="integer")
  114. $found=(IsSet($found) ? min($found,$position) : $position);
  115. }
  116. if (IsSet($found)) {
  117. $this->next_token=substr($string,$found+1);
  118. return(substr($string,0,$found));
  119. } else {
  120. $this->next_token="";
  121. return($string);
  122. }
  123. }
  124. public Function CookieEncode($value, $name)
  125. {
  126. return($name ? str_replace("=", "%25", $value) : str_replace(";", "%3B", $value));
  127. }
  128. public Function SetError($error, $error_code = HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR)
  129. {
  130. $this->error_code = $error_code;
  131. return($this->error=$error);
  132. }
  133. public Function SetPHPError($error, &$php_error_message, $error_code = HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR)
  134. {
  135. if(IsSet($php_error_message)
  136. && strlen($php_error_message))
  137. $error.=": ".$php_error_message;
  138. return($this->SetError($error, $error_code));
  139. }
  140. public Function SetDataAccessError($error,$check_connection=0)
  141. {
  142. $this->error=$error;
  143. $this->error_code = HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE;
  144. if(!$this->use_curl
  145. && function_exists("socket_get_status"))
  146. {
  147. $status=socket_get_status($this->connection);
  148. if($status["timed_out"])
  149. $this->error.=": data access time out";
  150. elseif ($status["eof"]) {
  151. if($check_connection)
  152. $this->error="";
  153. else
  154. $this->error.=": the server disconnected";
  155. }
  156. }
  157. }
  158. public Function OutputDebug($message)
  159. {
  160. if($this->log_debug)
  161. error_log($message);
  162. else {
  163. $message.="\n";
  164. if($this->html_debug)
  165. $message=str_replace("\n","<br />\n",HtmlEntities($message));
  166. echo $message;
  167. flush();
  168. }
  169. }
  170. public Function GetLine()
  171. {
  172. for ($line="";;) {
  173. if ($this->use_curl) {
  174. $eol=strpos($this->response,"\n",$this->read_response);
  175. $data=($eol ? substr($this->response,$this->read_response,$eol+1-$this->read_response) : "");
  176. $this->read_response+=strlen($data);
  177. } else {
  178. if (feof($this->connection)) {
  179. $this->SetDataAccessError("reached the end of data while reading from the HTTP server connection");
  180. return(0);
  181. }
  182. $data=fgets($this->connection,100);
  183. }
  184. if(GetType($data)!="string"
  185. || strlen($data)==0)
  186. {
  187. $this->SetDataAccessError("it was not possible to read line from the HTTP server");
  188. return(0);
  189. }
  190. $line.=$data;
  191. $length=strlen($line);
  192. if($length
  193. && !strcmp(substr($line,$length-1,1),"\n"))
  194. {
  195. $length-=(($length>=2 && !strcmp(substr($line,$length-2,1),"\r")) ? 2 : 1);
  196. $line=substr($line,0,$length);
  197. if($this->debug)
  198. $this->OutputDebug("S $line");
  199. return($line);
  200. }
  201. }
  202. }
  203. public Function PutLine($line)
  204. {
  205. if($this->debug)
  206. $this->OutputDebug("C $line");
  207. if (!fputs($this->connection,$line."\r\n")) {
  208. $this->SetDataAccessError("it was not possible to send a line to the HTTP server");
  209. return(0);
  210. }
  211. return(1);
  212. }
  213. public Function PutData($data)
  214. {
  215. if (strlen($data)) {
  216. if($this->debug)
  217. $this->OutputDebug('C '.$data);
  218. if (!fputs($this->connection,$data)) {
  219. $this->SetDataAccessError("it was not possible to send data to the HTTP server");
  220. return(0);
  221. }
  222. }
  223. return(1);
  224. }
  225. public Function FlushData()
  226. {
  227. if (!fflush($this->connection)) {
  228. $this->SetDataAccessError("it was not possible to send data to the HTTP server");
  229. return(0);
  230. }
  231. return(1);
  232. }
  233. public Function ReadChunkSize()
  234. {
  235. if ($this->remaining_chunk==0) {
  236. $debug=$this->debug;
  237. if(!$this->debug_response_body)
  238. $this->debug=0;
  239. $line=$this->GetLine();
  240. $this->debug=$debug;
  241. if(GetType($line)!="string")
  242. return($this->SetError("could not read chunk start: ".$this->error, $this->error_code));
  243. $this->remaining_chunk=hexdec($line);
  244. if ($this->remaining_chunk == 0) {
  245. if(!$this->debug_response_body)
  246. $this->debug=0;
  247. $line=$this->GetLine();
  248. $this->debug=$debug;
  249. if(GetType($line)!="string")
  250. return($this->SetError("could not read chunk end: ".$this->error, $this->error_code));
  251. }
  252. }
  253. return("");
  254. }
  255. public Function ReadBytes($length)
  256. {
  257. if ($this->use_curl) {
  258. $bytes=substr($this->response,$this->read_response,min($length,strlen($this->response)-$this->read_response));
  259. $this->read_response+=strlen($bytes);
  260. if($this->debug
  261. && $this->debug_response_body
  262. && strlen($bytes))
  263. $this->OutputDebug("S ".$bytes);
  264. } else {
  265. if ($this->chunked) {
  266. for ($bytes="",$remaining=$length;$remaining;) {
  267. if(strlen($this->ReadChunkSize()))
  268. return("");
  269. if ($this->remaining_chunk==0) {
  270. $this->last_chunk_read=1;
  271. break;
  272. }
  273. $ask=min($this->remaining_chunk,$remaining);
  274. $chunk=@fread($this->connection,$ask);
  275. $read=strlen($chunk);
  276. if ($read==0) {
  277. $this->SetDataAccessError("it was not possible to read data chunk from the HTTP server");
  278. return("");
  279. }
  280. if($this->debug
  281. && $this->debug_response_body)
  282. $this->OutputDebug("S ".$chunk);
  283. $bytes.=$chunk;
  284. $this->remaining_chunk-=$read;
  285. $remaining-=$read;
  286. if ($this->remaining_chunk==0) {
  287. if(feof($this->connection))
  288. 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));
  289. $data=@fread($this->connection,2);
  290. if (strcmp($data,"\r\n")) {
  291. $this->SetDataAccessError("it was not possible to read end of data chunk from the HTTP server");
  292. return("");
  293. }
  294. }
  295. }
  296. } else {
  297. $bytes=@fread($this->connection,$length);
  298. if (strlen($bytes)) {
  299. if($this->debug
  300. && $this->debug_response_body)
  301. $this->OutputDebug("S ".$bytes);
  302. } else
  303. $this->SetDataAccessError("it was not possible to read data from the HTTP server", $this->connection_close);
  304. }
  305. }
  306. return($bytes);
  307. }
  308. public Function EndOfInput()
  309. {
  310. if($this->use_curl)
  311. return($this->read_response>=strlen($this->response));
  312. if($this->chunked)
  313. return($this->last_chunk_read);
  314. if($this->content_length_set)
  315. return($this->content_length <= $this->read_length);
  316. return(feof($this->connection));
  317. }
  318. public Function Resolve($domain, &$ip, $server_type)
  319. {
  320. if(preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/',$domain))
  321. $ip=$domain;
  322. else {
  323. if($this->debug)
  324. $this->OutputDebug('Resolving '.$server_type.' server domain "'.$domain.'"...');
  325. if(!strcmp($ip=@gethostbyname($domain),$domain))
  326. $ip="";
  327. }
  328. if(strlen($ip)==0
  329. || (strlen($this->exclude_address)
  330. && !strcmp(@gethostbyname($this->exclude_address),$ip)))
  331. return($this->SetError("could not resolve the host domain \"".$domain."\"", HTTP_CLIENT_ERROR_INVALID_SERVER_ADDRESS));
  332. return('');
  333. }
  334. public Function Connect($host_name, $host_port, $ssl, $server_type = 'HTTP')
  335. {
  336. $domain=$host_name;
  337. $port = $host_port;
  338. if(strlen($error = $this->Resolve($domain, $ip, $server_type)))
  339. return($error);
  340. if (strlen($this->socks_host_name)) {
  341. switch ($this->socks_version) {
  342. case '4':
  343. $version = 4;
  344. break;
  345. case '5':
  346. $version = 5;
  347. break;
  348. default:
  349. return('it was not specified a supported SOCKS protocol version');
  350. break;
  351. }
  352. $host_ip = $ip;
  353. $port = $this->socks_host_port;
  354. $host_server_type = $server_type;
  355. $server_type = 'SOCKS';
  356. if(strlen($error = $this->Resolve($this->socks_host_name, $ip, $server_type)))
  357. return($error);
  358. }
  359. if($this->debug)
  360. $this->OutputDebug('Connecting to '.$server_type.' server IP '.$ip.' port '.$port.'...');
  361. if($ssl)
  362. $ip="ssl://".$host_name;
  363. if (($this->connection=($this->timeout ? @fsockopen($ip, $port, $errno, $error, $this->timeout) : @fsockopen($ip, $port, $errno)))==0) {
  364. $error_code = HTTP_CLIENT_ERROR_CANNOT_CONNECT;
  365. switch ($errno) {
  366. case -3:
  367. return($this->SetError("socket could not be created", $error_code));
  368. case -4:
  369. return($this->SetError("dns lookup on hostname \"".$host_name."\" failed", $error_code));
  370. case -5:
  371. return($this->SetError("connection refused or timed out", $error_code));
  372. case -6:
  373. return($this->SetError("fdopen() call failed", $error_code));
  374. case -7:
  375. return($this->SetError("setvbuf() call failed", $error_code));
  376. default:
  377. return($this->SetPHPError($errno." could not connect to the host \"".$host_name."\"",$php_errormsg, $error_code));
  378. }
  379. } else {
  380. if($this->data_timeout
  381. && function_exists("socket_set_timeout"))
  382. socket_set_timeout($this->connection,$this->data_timeout,0);
  383. if (strlen($this->socks_host_name)) {
  384. if($this->debug)
  385. $this->OutputDebug('Connected to the SOCKS server '.$this->socks_host_name);
  386. $send_error = 'it was not possible to send data to the SOCKS server';
  387. $receive_error = 'it was not possible to receive data from the SOCKS server';
  388. switch ($version) {
  389. case 4:
  390. $command = 1;
  391. $user = '';
  392. if(!fputs($this->connection, chr($version).chr($command).pack('nN', $host_port, ip2long($host_ip)).$user.Chr(0)))
  393. $error = $this->SetDataAccessError($send_error);
  394. else {
  395. $response = fgets($this->connection, 9);
  396. if(strlen($response) != 8)
  397. $error = $this->SetDataAccessError($receive_error);
  398. else {
  399. $socks_errors = array(
  400. "\x5a"=>'',
  401. "\x5b"=>'request rejected',
  402. "\x5c"=>'request failed because client is not running identd (or not reachable from the server)',
  403. "\x5d"=>'request failed because client\'s identd could not confirm the user ID string in the request',
  404. );
  405. $error_code = $response[1];
  406. $error = (IsSet($socks_errors[$error_code]) ? $socks_errors[$error_code] : 'unknown');
  407. if(strlen($error))
  408. $error = 'SOCKS error: '.$error;
  409. }
  410. }
  411. break;
  412. case 5:
  413. if($this->debug)
  414. $this->OutputDebug('Negotiating the authentication method ...');
  415. $methods = 1;
  416. $method = 0;
  417. if(!fputs($this->connection, chr($version).chr($methods).chr($method)))
  418. $error = $this->SetDataAccessError($send_error);
  419. else {
  420. $response = fgets($this->connection, 3);
  421. if(strlen($response) != 2)
  422. $error = $this->SetDataAccessError($receive_error);
  423. elseif(Ord($response[1]) != $method)
  424. $error = 'the SOCKS server requires an authentication method that is not yet supported';
  425. else {
  426. if($this->debug)
  427. $this->OutputDebug('Connecting to '.$host_server_type.' server IP '.$host_ip.' port '.$host_port.'...');
  428. $command = 1;
  429. $address_type = 1;
  430. if(!fputs($this->connection, chr($version).chr($command)."\x00".chr($address_type).pack('Nn', ip2long($host_ip), $host_port)))
  431. $error = $this->SetDataAccessError($send_error);
  432. else {
  433. $response = fgets($this->connection, 11);
  434. if(strlen($response) != 10)
  435. $error = $this->SetDataAccessError($receive_error);
  436. else {
  437. $socks_errors = array(
  438. "\x00"=>'',
  439. "\x01"=>'general SOCKS server failure',
  440. "\x02"=>'connection not allowed by ruleset',
  441. "\x03"=>'Network unreachable',
  442. "\x04"=>'Host unreachable',
  443. "\x05"=>'Connection refused',
  444. "\x06"=>'TTL expired',
  445. "\x07"=>'Command not supported',
  446. "\x08"=>'Address type not supported'
  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. }
  455. }
  456. break;
  457. default:
  458. $error = 'support for SOCKS protocol version '.$this->socks_version.' is not yet implemented';
  459. break;
  460. }
  461. if (strlen($error)) {
  462. fclose($this->connection);
  463. return($error);
  464. }
  465. }
  466. if($this->debug)
  467. $this->OutputDebug("Connected to $host_name");
  468. if(strlen($this->proxy_host_name)
  469. && !strcmp(strtolower($this->protocol), 'https'))
  470. {
  471. if(function_exists('stream_socket_enable_crypto')
  472. && in_array('ssl', stream_get_transports()))
  473. $this->state = "ConnectedToProxy";
  474. else {
  475. $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.");
  476. $this->state="Connected";
  477. }
  478. } else
  479. $this->state="Connected";
  480. return("");
  481. }
  482. }
  483. public Function Disconnect()
  484. {
  485. if($this->debug)
  486. $this->OutputDebug("Disconnected from ".$this->connected_host);
  487. if ($this->use_curl) {
  488. curl_close($this->connection);
  489. $this->response="";
  490. } else
  491. fclose($this->connection);
  492. $this->state="Disconnected";
  493. return("");
  494. }
  495. /* Public methods */
  496. public Function GetRequestArguments($url, &$arguments)
  497. {
  498. $this->error = '';
  499. $this->error_code = HTTP_CLIENT_ERROR_NO_ERROR;
  500. $arguments=array();
  501. $url = str_replace(' ', '%20', $url);
  502. $parameters=@parse_url($url);
  503. if(!$parameters)
  504. return($this->SetError("it was not specified a valid URL", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  505. if(!IsSet($parameters["scheme"]))
  506. return($this->SetError("it was not specified the protocol type argument", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  507. switch (strtolower($parameters["scheme"])) {
  508. case "http":
  509. case "https":
  510. $arguments["Protocol"]=$parameters["scheme"];
  511. break;
  512. default:
  513. return($parameters["scheme"]." connection scheme is not yet supported");
  514. }
  515. if(!IsSet($parameters["host"]))
  516. return($this->SetError("it was not specified the connection host argument", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  517. $arguments["HostName"]=$parameters["host"];
  518. $arguments["Headers"]=array("Host"=>$parameters["host"].(IsSet($parameters["port"]) ? ":".$parameters["port"] : ""));
  519. if (IsSet($parameters["user"])) {
  520. $arguments["AuthUser"]=UrlDecode($parameters["user"]);
  521. if(!IsSet($parameters["pass"]))
  522. $arguments["AuthPassword"]="";
  523. }
  524. if (IsSet($parameters["pass"])) {
  525. if(!IsSet($parameters["user"]))
  526. $arguments["AuthUser"]="";
  527. $arguments["AuthPassword"]=UrlDecode($parameters["pass"]);
  528. }
  529. if (IsSet($parameters["port"])) {
  530. if(strcmp($parameters["port"],strval(intval($parameters["port"]))))
  531. return($this->SetError("it was not specified a valid connection host argument", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  532. $arguments["HostPort"]=intval($parameters["port"]);
  533. } else
  534. $arguments["HostPort"]=0;
  535. $arguments["RequestURI"]=(IsSet($parameters["path"]) ? $parameters["path"] : "/").(IsSet($parameters["query"]) ? "?".$parameters["query"] : "");
  536. if(strlen($this->user_agent))
  537. $arguments["Headers"]["User-Agent"]=$this->user_agent;
  538. if(strlen($this->accept))
  539. $arguments["Headers"]["Accept"]=$this->accept;
  540. return("");
  541. }
  542. public Function Open($arguments)
  543. {
  544. if(strlen($this->error))
  545. return($this->error);
  546. $error_code = HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR;
  547. if(IsSet($arguments["HostName"]))
  548. $this->host_name=$arguments["HostName"];
  549. if(IsSet($arguments["HostPort"]))
  550. $this->host_port=$arguments["HostPort"];
  551. if(IsSet($arguments["ProxyHostName"]))
  552. $this->proxy_host_name=$arguments["ProxyHostName"];
  553. if(IsSet($arguments["ProxyHostPort"]))
  554. $this->proxy_host_port=$arguments["ProxyHostPort"];
  555. if(IsSet($arguments["SOCKSHostName"]))
  556. $this->socks_host_name=$arguments["SOCKSHostName"];
  557. if(IsSet($arguments["SOCKSHostPort"]))
  558. $this->socks_host_port=$arguments["SOCKSHostPort"];
  559. if(IsSet($arguments["SOCKSVersion"]))
  560. $this->socks_version=$arguments["SOCKSVersion"];
  561. if(IsSet($arguments["Protocol"]))
  562. $this->protocol=$arguments["Protocol"];
  563. switch (strtolower($this->protocol)) {
  564. case "http":
  565. $default_port=80;
  566. break;
  567. case "https":
  568. $default_port=443;
  569. break;
  570. default:
  571. return($this->SetError("it was not specified a valid connection protocol", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  572. }
  573. if (strlen($this->proxy_host_name)==0) {
  574. if(strlen($this->host_name)==0)
  575. return($this->SetError("it was not specified a valid hostname", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  576. $host_name=$this->host_name;
  577. $host_port=($this->host_port ? $this->host_port : $default_port);
  578. $server_type = 'HTTP';
  579. } else {
  580. $host_name=$this->proxy_host_name;
  581. $host_port=$this->proxy_host_port;
  582. $server_type = 'HTTP proxy';
  583. }
  584. $ssl=(strtolower($this->protocol)=="https" && strlen($this->proxy_host_name)==0);
  585. if($ssl
  586. && strlen($this->socks_host_name))
  587. return($this->SetError('establishing SSL connections via a SOCKS server is not yet supported', HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  588. $this->use_curl=($ssl && $this->prefer_curl && function_exists("curl_init"));
  589. switch ($this->state) {
  590. case 'Connected':
  591. if(!strcmp($host_name, $this->connected_host)
  592. && intval($host_port) == $this->connected_port
  593. && intval($ssl) == $this->connected_ssl)
  594. {
  595. if($this->debug)
  596. $this->OutputDebug("Reusing connection to ".$this->connected_host);
  597. return('');
  598. }
  599. if(strlen($error = $this->Disconnect()))
  600. return($error);
  601. case "Disconnected":
  602. break;
  603. default:
  604. return("1 already connected");
  605. }
  606. if($this->debug)
  607. $this->OutputDebug("Connecting to ".$this->host_name);
  608. if ($this->use_curl) {
  609. $error=(($this->connection=curl_init($this->protocol."://".$this->host_name.($host_port==$default_port ? "" : ":".strval($host_port))."/")) ? "" : "Could not initialize a CURL session");
  610. if (strlen($error)==0) {
  611. if(IsSet($arguments["SSLCertificateFile"]))
  612. curl_setopt($this->connection,CURLOPT_SSLCERT,$arguments["SSLCertificateFile"]);
  613. if(IsSet($arguments["SSLCertificatePassword"]))
  614. curl_setopt($this->connection,CURLOPT_SSLCERTPASSWD,$arguments["SSLCertificatePassword"]);
  615. if(IsSet($arguments["SSLKeyFile"]))
  616. curl_setopt($this->connection,CURLOPT_SSLKEY,$arguments["SSLKeyFile"]);
  617. if(IsSet($arguments["SSLKeyPassword"]))
  618. curl_setopt($this->connection,CURLOPT_SSLKEYPASSWD,$arguments["SSLKeyPassword"]);
  619. }
  620. $this->state="Connected";
  621. } else {
  622. $error="";
  623. if(strlen($this->proxy_host_name)
  624. && (IsSet($arguments["SSLCertificateFile"])
  625. || IsSet($arguments["SSLCertificateFile"])))
  626. $error="establishing SSL connections using certificates or private keys via non-SSL proxies is not supported";
  627. else {
  628. if ($ssl) {
  629. if(IsSet($arguments["SSLCertificateFile"]))
  630. $error="establishing SSL connections using certificates is only supported when the cURL extension is enabled";
  631. elseif(IsSet($arguments["SSLKeyFile"]))
  632. $error="establishing SSL connections using a private key is only supported when the cURL extension is enabled";
  633. else {
  634. $version=explode(".",function_exists("phpversion") ? phpversion() : "3.0.7");
  635. $php_version=intval($version[0])*1000000+intval($version[1])*1000+intval($version[2]);
  636. if($php_version<4003000)
  637. $error="establishing SSL connections requires at least PHP version 4.3.0 or having the cURL extension enabled";
  638. elseif(!function_exists("extension_loaded")
  639. || !extension_loaded("openssl"))
  640. $error="establishing SSL connections requires the OpenSSL extension enabled";
  641. }
  642. }
  643. if (strlen($error)==0) {
  644. $error=$this->Connect($host_name, $host_port, $ssl, $server_type);
  645. $error_code = $this->error_code;
  646. }
  647. }
  648. }
  649. if(strlen($error))
  650. return($this->SetError($error, $error_code));
  651. $this->session=md5(uniqid(""));
  652. $this->connected_host = $host_name;
  653. $this->connected_port = intval($host_port);
  654. $this->connected_ssl = intval($ssl);
  655. return("");
  656. }
  657. public Function Close($force = 0)
  658. {
  659. if($this->state=="Disconnected")
  660. return("1 already disconnected");
  661. if(!$this->force_close
  662. && $this->keep_alive
  663. && !$force
  664. && $this->state == 'ResponseReceived')
  665. {
  666. if($this->debug)
  667. $this->OutputDebug('Keeping the connection alive to '.$this->connected_host);
  668. $this->state = 'Connected';
  669. return('');
  670. }
  671. return($this->Disconnect());
  672. }
  673. public Function PickCookies(&$cookies,$secure)
  674. {
  675. if (IsSet($this->cookies[$secure])) {
  676. $now=gmdate("Y-m-d H-i-s");
  677. for ($domain=0,Reset($this->cookies[$secure]);$domain<count($this->cookies[$secure]);Next($this->cookies[$secure]),$domain++) {
  678. $domain_pattern=Key($this->cookies[$secure]);
  679. $match=strlen($this->request_host)-strlen($domain_pattern);
  680. if($match>=0
  681. && !strcmp($domain_pattern,substr($this->request_host,$match))
  682. && ($match==0
  683. || $domain_pattern[0]=="."
  684. || $this->request_host[$match-1]=="."))
  685. {
  686. 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++) {
  687. $path=Key($this->cookies[$secure][$domain_pattern]);
  688. if(strlen($this->request_uri)>=strlen($path)
  689. && substr($this->request_uri,0,strlen($path))==$path)
  690. {
  691. 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++) {
  692. $cookie_name=Key($this->cookies[$secure][$domain_pattern][$path]);
  693. $expires=$this->cookies[$secure][$domain_pattern][$path][$cookie_name]["expires"];
  694. if($expires==""
  695. || strcmp($now,$expires)<0)
  696. $cookies[$cookie_name]=$this->cookies[$secure][$domain_pattern][$path][$cookie_name];
  697. }
  698. }
  699. }
  700. }
  701. }
  702. }
  703. }
  704. public Function GetFileDefinition($file, &$definition)
  705. {
  706. $name="";
  707. if(IsSet($file["FileName"]))
  708. $name=basename($file["FileName"]);
  709. if(IsSet($file["Name"]))
  710. $name=$file["Name"];
  711. if(strlen($name)==0)
  712. return("it was not specified the file part name");
  713. if (IsSet($file["Content-Type"])) {
  714. $content_type=$file["Content-Type"];
  715. $type=$this->Tokenize(strtolower($content_type),"/");
  716. $sub_type=$this->Tokenize("");
  717. switch ($type) {
  718. case "text":
  719. case "image":
  720. case "audio":
  721. case "video":
  722. case "application":
  723. case "message":
  724. break;
  725. case "automatic":
  726. switch ($sub_type) {
  727. case "name":
  728. switch (GetType($dot=strrpos($name,"."))=="integer" ? strtolower(substr($name,$dot)) : "") {
  729. case ".xls":
  730. $content_type="application/excel";
  731. break;
  732. case ".hqx":
  733. $content_type="application/macbinhex40";
  734. break;
  735. case ".doc":
  736. case ".dot":
  737. case ".wrd":
  738. $content_type="application/msword";
  739. break;
  740. case ".pdf":
  741. $content_type="application/pdf";
  742. break;
  743. case ".pgp":
  744. $content_type="application/pgp";
  745. break;
  746. case ".ps":
  747. case ".eps":
  748. case ".ai":
  749. $content_type="application/postscript";
  750. break;
  751. case ".ppt":
  752. $content_type="application/powerpoint";
  753. break;
  754. case ".rtf":
  755. $content_type="application/rtf";
  756. break;
  757. case ".tgz":
  758. case ".gtar":
  759. $content_type="application/x-gtar";
  760. break;
  761. case ".gz":
  762. $content_type="application/x-gzip";
  763. break;
  764. case ".php":
  765. case ".php3":
  766. $content_type="application/x-httpd-php";
  767. break;
  768. case ".js":
  769. $content_type="application/x-javascript";
  770. break;
  771. case ".ppd":
  772. case ".psd":
  773. $content_type="application/x-photoshop";
  774. break;
  775. case ".swf":
  776. case ".swc":
  777. case ".rf":
  778. $content_type="application/x-shockwave-flash";
  779. break;
  780. case ".tar":
  781. $content_type="application/x-tar";
  782. break;
  783. case ".zip":
  784. $content_type="application/zip";
  785. break;
  786. case ".mid":
  787. case ".midi":
  788. case ".kar":
  789. $content_type="audio/midi";
  790. break;
  791. case ".mp2":
  792. case ".mp3":
  793. case ".mpga":
  794. $content_type="audio/mpeg";
  795. break;
  796. case ".ra":
  797. $content_type="audio/x-realaudio";
  798. break;
  799. case ".wav":
  800. $content_type="audio/wav";
  801. break;
  802. case ".bmp":
  803. $content_type="image/bitmap";
  804. break;
  805. case ".gif":
  806. $content_type="image/gif";
  807. break;
  808. case ".iff":
  809. $content_type="image/iff";
  810. break;
  811. case ".jb2":
  812. $content_type="image/jb2";
  813. break;
  814. case ".jpg":
  815. case ".jpe":
  816. case ".jpeg":
  817. $content_type="image/jpeg";
  818. break;
  819. case ".jpx":
  820. $content_type="image/jpx";
  821. break;
  822. case ".png":
  823. $content_type="image/png";
  824. break;
  825. case ".tif":
  826. case ".tiff":
  827. $content_type="image/tiff";
  828. break;
  829. case ".wbmp":
  830. $content_type="image/vnd.wap.wbmp";
  831. break;
  832. case ".xbm":
  833. $content_type="image/xbm";
  834. break;
  835. case ".css":
  836. $content_type="text/css";
  837. break;
  838. case ".txt":
  839. $content_type="text/plain";
  840. break;
  841. case ".htm":
  842. case ".html":
  843. $content_type="text/html";
  844. break;
  845. case ".xml":
  846. $content_type="text/xml";
  847. break;
  848. case ".mpg":
  849. case ".mpe":
  850. case ".mpeg":
  851. $content_type="video/mpeg";
  852. break;
  853. case ".qt":
  854. case ".mov":
  855. $content_type="video/quicktime";
  856. break;
  857. case ".avi":
  858. $content_type="video/x-ms-video";
  859. break;
  860. case ".eml":
  861. $content_type="message/rfc822";
  862. break;
  863. default:
  864. $content_type="application/octet-stream";
  865. break;
  866. }
  867. break;
  868. default:
  869. return($content_type." is not a supported automatic content type detection method");
  870. }
  871. break;
  872. default:
  873. return($content_type." is not a supported file content type");
  874. }
  875. } else
  876. $content_type="application/octet-stream";
  877. $definition=array(
  878. "Content-Type"=>$content_type,
  879. "NAME"=>$name
  880. );
  881. if (IsSet($file["FileName"])) {
  882. if (GetType($length=@filesize($file["FileName"]))!="integer") {
  883. $error="it was not possible to determine the length of the file ".$file["FileName"];
  884. if(IsSet($php_errormsg)
  885. && strlen($php_errormsg))
  886. $error.=": ".$php_errormsg;
  887. if(!file_exists($file["FileName"]))
  888. $error="it was not possible to access the file ".$file["FileName"];
  889. return($error);
  890. }
  891. $definition["FILENAME"]=$file["FileName"];
  892. $definition["Content-Length"]=$length;
  893. } elseif(IsSet($file["Data"]))
  894. $definition["Content-Length"]=strlen($definition["DATA"]=$file["Data"]);
  895. else
  896. return("it was not specified a valid file name");
  897. return("");
  898. }
  899. public Function ConnectFromProxy($arguments, &$headers)
  900. {
  901. if(!$this->PutLine('CONNECT '.$this->host_name.':'.($this->host_port ? $this->host_port : 443).' HTTP/1.0')
  902. || (strlen($this->user_agent)
  903. && !$this->PutLine('User-Agent: '.$this->user_agent))
  904. || (strlen($this->accept)
  905. && !$this->PutLine('Accept: '.$this->accept))
  906. || (IsSet($arguments['Headers']['Proxy-Authorization'])
  907. && !$this->PutLine('Proxy-Authorization: '.$arguments['Headers']['Proxy-Authorization']))
  908. || !$this->PutLine(''))
  909. {
  910. $this->Disconnect();
  911. return($this->error);
  912. }
  913. $this->state = "ConnectSent";
  914. if(strlen($error=$this->ReadReplyHeadersResponse($headers)))
  915. return($error);
  916. $proxy_authorization="";
  917. while (!strcmp($this->response_status, "100")) {
  918. $this->state="ConnectSent";
  919. if(strlen($error=$this->ReadReplyHeadersResponse($headers)))
  920. return($error);
  921. }
  922. switch ($this->response_status) {
  923. case "200":
  924. if (!@stream_socket_enable_crypto($this->connection, 1, STREAM_CRYPTO_METHOD_SSLv23_CLIENT)) {
  925. $this->SetPHPError('it was not possible to start a SSL encrypted connection via this proxy', $php_errormsg, HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE);
  926. $this->Disconnect();
  927. return($this->error);
  928. }
  929. $this->state = "Connected";
  930. break;
  931. case "407":
  932. 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)))
  933. return($error);
  934. break;
  935. default:
  936. return($this->SetError("unable to send request via proxy", HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  937. }
  938. return("");
  939. }
  940. public Function SendRequest($arguments)
  941. {
  942. if(strlen($this->error))
  943. return($this->error);
  944. if(IsSet($arguments["ProxyUser"]))
  945. $this->proxy_request_user=$arguments["ProxyUser"];
  946. elseif(IsSet($this->proxy_user))
  947. $this->proxy_request_user=$this->proxy_user;
  948. if(IsSet($arguments["ProxyPassword"]))
  949. $this->proxy_request_password=$arguments["ProxyPassword"];
  950. elseif(IsSet($this->proxy_password))
  951. $this->proxy_request_password=$this->proxy_password;
  952. if(IsSet($arguments["ProxyRealm"]))
  953. $this->proxy_request_realm=$arguments["ProxyRealm"];
  954. elseif(IsSet($this->proxy_realm))
  955. $this->proxy_request_realm=$this->proxy_realm;
  956. if(IsSet($arguments["ProxyWorkstation"]))
  957. $this->proxy_request_workstation=$arguments["ProxyWorkstation"];
  958. elseif(IsSet($this->proxy_workstation))
  959. $this->proxy_request_workstation=$this->proxy_workstation;
  960. switch ($this->state) {
  961. case "Disconnected":
  962. return($this->SetError("connection was not yet established", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  963. case "Connected":
  964. $connect = 0;
  965. break;
  966. case "ConnectedToProxy":
  967. if(strlen($error = $this->ConnectFromProxy($arguments, $headers)))
  968. return($error);
  969. $connect = 1;
  970. break;
  971. default:
  972. return($this->SetError("can not send request in the current connection state", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  973. }
  974. if(IsSet($arguments["RequestMethod"]))
  975. $this->request_method=$arguments["RequestMethod"];
  976. if(IsSet($arguments["User-Agent"]))
  977. $this->user_agent=$arguments["User-Agent"];
  978. if(!IsSet($arguments["Headers"]["User-Agent"])
  979. && strlen($this->user_agent))
  980. $arguments["Headers"]["User-Agent"]=$this->user_agent;
  981. if(IsSet($arguments["KeepAlive"]))
  982. $this->keep_alive=intval($arguments["KeepAlive"]);
  983. if(!IsSet($arguments["Headers"]["Connection"])
  984. && $this->keep_alive)
  985. $arguments["Headers"]["Connection"]='Keep-Alive';
  986. if(IsSet($arguments["Accept"]))
  987. $this->user_agent=$arguments["Accept"];
  988. if(!IsSet($arguments["Headers"]["Accept"])
  989. && strlen($this->accept))
  990. $arguments["Headers"]["Accept"]=$this->accept;
  991. if(strlen($this->request_method)==0)
  992. return($this->SetError("it was not specified a valid request method", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  993. if(IsSet($arguments["RequestURI"]))
  994. $this->request_uri=$arguments["RequestURI"];
  995. if(strlen($this->request_uri)==0
  996. || substr($this->request_uri,0,1)!="/")
  997. return($this->SetError("it was not specified a valid request URI", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  998. $this->request_arguments=$arguments;
  999. $this->request_headers=(IsSet($arguments["Headers"]) ? $arguments["Headers"] : array());
  1000. $body_length=0;
  1001. $this->request_body="";
  1002. $get_body=1;
  1003. if($this->request_method=="POST"
  1004. || $this->request_method=="PUT")
  1005. {
  1006. if (IsSet($arguments['StreamRequest'])) {
  1007. $get_body = 0;
  1008. $this->request_headers["Transfer-Encoding"]="chunked";
  1009. } elseif(IsSet($arguments["PostFiles"])
  1010. || ($this->force_multipart_form_post
  1011. && IsSet($arguments["PostValues"])))
  1012. {
  1013. $boundary="--".md5(uniqid(time()));
  1014. $this->request_headers["Content-Type"]="multipart/form-data; boundary=".$boundary.(IsSet($arguments["CharSet"]) ? "; charset=".$arguments["CharSet"] : "");
  1015. $post_parts=array();
  1016. if (IsSet($arguments["PostValues"])) {
  1017. $values=$arguments["PostValues"];
  1018. if(GetType($values)!="array")
  1019. return($this->SetError("it was not specified a valid POST method values array", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1020. for (Reset($values),$value=0;$value<count($values);Next($values),$value++) {
  1021. $input=Key($values);
  1022. $headers="--".$boundary."\r\nContent-Disposition: form-data; name=\"".$input."\"\r\n\r\n";
  1023. $data=$values[$input];
  1024. $post_parts[]=array("HEADERS"=>$headers,"DATA"=>$data);
  1025. $body_length+=strlen($headers)+strlen($data)+strlen("\r\n");
  1026. }
  1027. }
  1028. $body_length+=strlen("--".$boundary."--\r\n");
  1029. $files=(IsSet($arguments["PostFiles"]) ? $arguments["PostFiles"] : array());
  1030. Reset($files);
  1031. $end=(GetType($input=Key($files))!="string");
  1032. for (;!$end;) {
  1033. if(strlen($error=$this->GetFileDefinition($files[$input],$definition)))
  1034. return("3 ".$error);
  1035. $headers="--".$boundary."\r\nContent-Disposition: form-data; name=\"".$input."\"; filename=\"".$definition["NAME"]."\"\r\nContent-Type: ".$definition["Content-Type"]."\r\n\r\n";
  1036. $part=count($post_parts);
  1037. $post_parts[$part]=array("HEADERS"=>$headers);
  1038. if (IsSet($definition["FILENAME"])) {
  1039. $post_parts[$part]["FILENAME"]=$definition["FILENAME"];
  1040. $data="";
  1041. } else
  1042. $data=$definition["DATA"];
  1043. $post_parts[$part]["DATA"]=$data;
  1044. $body_length+=strlen($headers)+$definition["Content-Length"]+strlen("\r\n");
  1045. Next($files);
  1046. $end=(GetType($input=Key($files))!="string");
  1047. }
  1048. $get_body=0;
  1049. } elseif (IsSet($arguments["PostValues"])) {
  1050. $values=$arguments["PostValues"];
  1051. if(GetType($values)!="array")
  1052. return($this->SetError("it was not specified a valid POST method values array", HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1053. for (Reset($values),$value=0;$value<count($values);Next($values),$value++) {
  1054. $k=Key($values);
  1055. if (GetType($values[$k])=="array") {
  1056. for ($v = 0; $v < count($values[$k]); $v++) {
  1057. if($value+$v>0)
  1058. $this->request_body.="&";
  1059. $this->request_body.=UrlEncode($k)."=".UrlEncode($values[$k][$v]);
  1060. }
  1061. } else {
  1062. if($value>0)
  1063. $this->request_body.="&";
  1064. $this->request_body.

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