PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/magpie/extlib/Snoopy.class.inc

https://github.com/radicaldesigns/amp
PHP | 899 lines | 741 code | 41 blank | 117 comment | 20 complexity | 90bed0cd1d142cea9d0e44d12c88d21c MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, BSD-3-Clause, LGPL-2.0, CC-BY-SA-3.0, AGPL-1.0
  1. <?php
  2. /*************************************************
  3. Snoopy - the PHP net client
  4. Author: Monte Ohrt <monte@ispi.net>
  5. Copyright (c): 1999-2000 ispi, all rights reserved
  6. Version: 1.0
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. You may contact the author of Snoopy by e-mail at:
  21. monte@ispi.net
  22. Or, write to:
  23. Monte Ohrt
  24. CTO, ispi
  25. 237 S. 70th suite 220
  26. Lincoln, NE 68510
  27. The latest version of Snoopy can be obtained from:
  28. http://snoopy.sourceforge.com
  29. *************************************************/
  30. class Snoopy
  31. {
  32. /**** Public variables ****/
  33. /* user definable vars */
  34. var $host = "www.php.net"; // host name we are connecting to
  35. var $port = 80; // port we are connecting to
  36. var $proxy_host = ""; // proxy host to use
  37. var $proxy_port = ""; // proxy port to use
  38. var $agent = "Snoopy v1.0"; // agent we masquerade as
  39. var $referer = ""; // referer info to pass
  40. var $cookies = array(); // array of cookies to pass
  41. // $cookies["username"]="joe";
  42. var $rawheaders = array(); // array of raw headers to send
  43. // $rawheaders["Content-type"]="text/html";
  44. var $maxredirs = 5; // http redirection depth maximum. 0 = disallow
  45. var $lastredirectaddr = ""; // contains address of last redirected address
  46. var $offsiteok = true; // allows redirection off-site
  47. var $maxframes = 0; // frame content depth maximum. 0 = disallow
  48. var $expandlinks = true; // expand links to fully qualified URLs.
  49. // this only applies to fetchlinks()
  50. // or submitlinks()
  51. var $passcookies = true; // pass set cookies back through redirects
  52. // NOTE: this currently does not respect
  53. // dates, domains or paths.
  54. var $user = ""; // user for http authentication
  55. var $pass = ""; // password for http authentication
  56. // http accept types
  57. var $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
  58. var $results = ""; // where the content is put
  59. var $error = ""; // error messages sent here
  60. var $response_code = ""; // response code returned from server
  61. var $headers = array(); // headers returned from server sent here
  62. var $maxlength = 500000; // max return data length (body)
  63. var $read_timeout = 0; // timeout on read operations, in seconds
  64. // supported only since PHP 4 Beta 4
  65. // set to 0 to disallow timeouts
  66. var $timed_out = false; // if a read operation timed out
  67. var $status = 0; // http request status
  68. var $curl_path = "/usr/bin/curl";
  69. // Snoopy will use cURL for fetching
  70. // SSL content if a full system path to
  71. // the cURL binary is supplied here.
  72. // set to false if you do not have
  73. // cURL installed. See http://curl.haxx.se
  74. // for details on installing cURL.
  75. // Snoopy does *not* use the cURL
  76. // library functions built into php,
  77. // as these functions are not stable
  78. // as of this Snoopy release.
  79. // send Accept-encoding: gzip?
  80. var $use_gzip = true;
  81. /**** Private variables ****/
  82. var $_maxlinelen = 4096; // max line length (headers)
  83. var $_httpmethod = "GET"; // default http request method
  84. var $_httpversion = "HTTP/1.0"; // default http request version
  85. var $_submit_method = "POST"; // default submit method
  86. var $_submit_type = "application/x-www-form-urlencoded"; // default submit type
  87. var $_mime_boundary = ""; // MIME boundary for multipart/form-data submit type
  88. var $_redirectaddr = false; // will be set if page fetched is a redirect
  89. var $_redirectdepth = 0; // increments on an http redirect
  90. var $_frameurls = array(); // frame src urls
  91. var $_framedepth = 0; // increments on frame depth
  92. var $_isproxy = false; // set if using a proxy server
  93. var $_fp_timeout = 30; // timeout for socket connection
  94. /*======================================================================*\
  95. Function: fetch
  96. Purpose: fetch the contents of a web page
  97. (and possibly other protocols in the
  98. future like ftp, nntp, gopher, etc.)
  99. Input: $URI the location of the page to fetch
  100. Output: $this->results the output text from the fetch
  101. \*======================================================================*/
  102. function fetch($URI)
  103. {
  104. //preg_match("|^([^:]+)://([^:/]+)(:[\d]+)*(.*)|",$URI,$URI_PARTS);
  105. $URI_PARTS = parse_url($URI);
  106. if (!empty($URI_PARTS["user"]))
  107. $this->user = $URI_PARTS["user"];
  108. if (!empty($URI_PARTS["pass"]))
  109. $this->pass = $URI_PARTS["pass"];
  110. switch($URI_PARTS["scheme"])
  111. {
  112. case "http":
  113. $this->host = $URI_PARTS["host"];
  114. if(!empty($URI_PARTS["port"]))
  115. $this->port = $URI_PARTS["port"];
  116. if($this->_connect($fp))
  117. {
  118. if($this->_isproxy)
  119. {
  120. // using proxy, send entire URI
  121. $this->_httprequest($URI,$fp,$URI,$this->_httpmethod);
  122. }
  123. else
  124. {
  125. $path = $URI_PARTS["path"].(isset($URI_PARTS["query"]) ? "?".$URI_PARTS["query"] : "");
  126. // no proxy, send only the path
  127. $this->_httprequest($path, $fp, $URI, $this->_httpmethod);
  128. }
  129. $this->_disconnect($fp);
  130. if($this->_redirectaddr)
  131. {
  132. /* url was redirected, check if we've hit the max depth */
  133. if($this->maxredirs > $this->_redirectdepth)
  134. {
  135. // only follow redirect if it's on this site, or offsiteok is true
  136. if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
  137. {
  138. /* follow the redirect */
  139. $this->_redirectdepth++;
  140. $this->lastredirectaddr=$this->_redirectaddr;
  141. $this->fetch($this->_redirectaddr);
  142. }
  143. }
  144. }
  145. if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
  146. {
  147. $frameurls = $this->_frameurls;
  148. $this->_frameurls = array();
  149. while(list(,$frameurl) = each($frameurls))
  150. {
  151. if($this->_framedepth < $this->maxframes)
  152. {
  153. $this->fetch($frameurl);
  154. $this->_framedepth++;
  155. }
  156. else
  157. break;
  158. }
  159. }
  160. }
  161. else
  162. {
  163. return false;
  164. }
  165. return true;
  166. break;
  167. case "https":
  168. if(!$this->curl_path || (!is_executable($this->curl_path))) {
  169. $this->error = "Bad curl ($this->curl_path), can't fetch HTTPS \n";
  170. return false;
  171. }
  172. $this->host = $URI_PARTS["host"];
  173. if(!empty($URI_PARTS["port"]))
  174. $this->port = $URI_PARTS["port"];
  175. if($this->_isproxy)
  176. {
  177. // using proxy, send entire URI
  178. $this->_httpsrequest($URI,$URI,$this->_httpmethod);
  179. }
  180. else
  181. {
  182. $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
  183. // no proxy, send only the path
  184. $this->_httpsrequest($path, $URI, $this->_httpmethod);
  185. }
  186. if($this->_redirectaddr)
  187. {
  188. /* url was redirected, check if we've hit the max depth */
  189. if($this->maxredirs > $this->_redirectdepth)
  190. {
  191. // only follow redirect if it's on this site, or offsiteok is true
  192. if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
  193. {
  194. /* follow the redirect */
  195. $this->_redirectdepth++;
  196. $this->lastredirectaddr=$this->_redirectaddr;
  197. $this->fetch($this->_redirectaddr);
  198. }
  199. }
  200. }
  201. if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
  202. {
  203. $frameurls = $this->_frameurls;
  204. $this->_frameurls = array();
  205. while(list(,$frameurl) = each($frameurls))
  206. {
  207. if($this->_framedepth < $this->maxframes)
  208. {
  209. $this->fetch($frameurl);
  210. $this->_framedepth++;
  211. }
  212. else
  213. break;
  214. }
  215. }
  216. return true;
  217. break;
  218. default:
  219. // not a valid protocol
  220. $this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n';
  221. return false;
  222. break;
  223. }
  224. return true;
  225. }
  226. /*======================================================================*\
  227. Private functions
  228. \*======================================================================*/
  229. /*======================================================================*\
  230. Function: _striplinks
  231. Purpose: strip the hyperlinks from an html document
  232. Input: $document document to strip.
  233. Output: $match an array of the links
  234. \*======================================================================*/
  235. function _striplinks($document)
  236. {
  237. preg_match_all("'<\s*a\s+.*href\s*=\s* # find <a href=
  238. ([\"\'])? # find single or double quote
  239. (?(1) (.*?)\\1 | ([^\s\>]+)) # if quote found, match up to next matching
  240. # quote, otherwise match up to next space
  241. 'isx",$document,$links);
  242. // catenate the non-empty matches from the conditional subpattern
  243. while(list($key,$val) = each($links[2]))
  244. {
  245. if(!empty($val))
  246. $match[] = $val;
  247. }
  248. while(list($key,$val) = each($links[3]))
  249. {
  250. if(!empty($val))
  251. $match[] = $val;
  252. }
  253. // return the links
  254. return $match;
  255. }
  256. /*======================================================================*\
  257. Function: _stripform
  258. Purpose: strip the form elements from an html document
  259. Input: $document document to strip.
  260. Output: $match an array of the links
  261. \*======================================================================*/
  262. function _stripform($document)
  263. {
  264. preg_match_all("'<\/?(FORM|INPUT|SELECT|TEXTAREA|(OPTION))[^<>]*>(?(2)(.*(?=<\/?(option|select)[^<>]*>[\r\n]*)|(?=[\r\n]*))|(?=[\r\n]*))'Usi",$document,$elements);
  265. // catenate the matches
  266. $match = implode("\r\n",$elements[0]);
  267. // return the links
  268. return $match;
  269. }
  270. /*======================================================================*\
  271. Function: _striptext
  272. Purpose: strip the text from an html document
  273. Input: $document document to strip.
  274. Output: $text the resulting text
  275. \*======================================================================*/
  276. function _striptext($document)
  277. {
  278. // I didn't use preg eval (//e) since that is only available in PHP 4.0.
  279. // so, list your entities one by one here. I included some of the
  280. // more common ones.
  281. $search = array("'<script[^>]*?>.*?</script>'si", // strip out javascript
  282. "'<[\/\!]*?[^<>]*?>'si", // strip out html tags
  283. "'([\r\n])[\s]+'", // strip out white space
  284. "'&(quote|#34);'i", // replace html entities
  285. "'&(amp|#38);'i",
  286. "'&(lt|#60);'i",
  287. "'&(gt|#62);'i",
  288. "'&(nbsp|#160);'i",
  289. "'&(iexcl|#161);'i",
  290. "'&(cent|#162);'i",
  291. "'&(pound|#163);'i",
  292. "'&(copy|#169);'i"
  293. );
  294. $replace = array( "",
  295. "",
  296. "\\1",
  297. "\"",
  298. "&",
  299. "<",
  300. ">",
  301. " ",
  302. chr(161),
  303. chr(162),
  304. chr(163),
  305. chr(169));
  306. $text = preg_replace($search,$replace,$document);
  307. return $text;
  308. }
  309. /*======================================================================*\
  310. Function: _expandlinks
  311. Purpose: expand each link into a fully qualified URL
  312. Input: $links the links to qualify
  313. $URI the full URI to get the base from
  314. Output: $expandedLinks the expanded links
  315. \*======================================================================*/
  316. function _expandlinks($links,$URI)
  317. {
  318. preg_match("/^[^\?]+/",$URI,$match);
  319. $match = preg_replace("|/[^\/\.]+\.[^\/\.]+$|","",$match[0]);
  320. $search = array( "|^http://".preg_quote($this->host)."|i",
  321. "|^(?!http://)(\/)?(?!mailto:)|i",
  322. "|/\./|",
  323. "|/[^\/]+/\.\./|"
  324. );
  325. $replace = array( "",
  326. $match."/",
  327. "/",
  328. "/"
  329. );
  330. $expandedLinks = preg_replace($search,$replace,$links);
  331. return $expandedLinks;
  332. }
  333. /*======================================================================*\
  334. Function: _httprequest
  335. Purpose: go get the http data from the server
  336. Input: $url the url to fetch
  337. $fp the current open file pointer
  338. $URI the full URI
  339. $body body contents to send if any (POST)
  340. Output:
  341. \*======================================================================*/
  342. function _httprequest($url,$fp,$URI,$http_method,$content_type="",$body="")
  343. {
  344. if($this->passcookies && $this->_redirectaddr)
  345. $this->setcookies();
  346. $URI_PARTS = parse_url($URI);
  347. if(empty($url))
  348. $url = "/";
  349. $headers = $http_method." ".$url." ".$this->_httpversion."\r\n";
  350. if(!empty($this->agent))
  351. $headers .= "User-Agent: ".$this->agent."\r\n";
  352. if(!empty($this->host) && !isset($this->rawheaders['Host']))
  353. $headers .= "Host: ".$this->host."\r\n";
  354. if(!empty($this->accept))
  355. $headers .= "Accept: ".$this->accept."\r\n";
  356. if($this->use_gzip) {
  357. // make sure PHP was built with --with-zlib
  358. // and we can handle gzipp'ed data
  359. if ( function_exists(gzinflate) ) {
  360. $headers .= "Accept-encoding: gzip\r\n";
  361. }
  362. else {
  363. trigger_error(
  364. "use_gzip is on, but PHP was built without zlib support.".
  365. " Requesting file(s) without gzip encoding.",
  366. E_USER_NOTICE);
  367. }
  368. }
  369. if(!empty($this->referer))
  370. $headers .= "Referer: ".$this->referer."\r\n";
  371. if(!empty($this->cookies))
  372. {
  373. if(!is_array($this->cookies))
  374. $this->cookies = (array)$this->cookies;
  375. reset($this->cookies);
  376. if ( count($this->cookies) > 0 ) {
  377. $cookie_headers .= 'Cookie: ';
  378. foreach ( $this->cookies as $cookieKey => $cookieVal ) {
  379. $cookie_headers .= $cookieKey."=".urlencode($cookieVal)."; ";
  380. }
  381. $headers .= substr($cookie_headers,0,-2) . "\r\n";
  382. }
  383. }
  384. if(!empty($this->rawheaders))
  385. {
  386. if(!is_array($this->rawheaders))
  387. $this->rawheaders = (array)$this->rawheaders;
  388. while(list($headerKey,$headerVal) = each($this->rawheaders))
  389. $headers .= $headerKey.": ".$headerVal."\r\n";
  390. }
  391. if(!empty($content_type)) {
  392. $headers .= "Content-type: $content_type";
  393. if ($content_type == "multipart/form-data")
  394. $headers .= "; boundary=".$this->_mime_boundary;
  395. $headers .= "\r\n";
  396. }
  397. if(!empty($body))
  398. $headers .= "Content-length: ".strlen($body)."\r\n";
  399. if(!empty($this->user) || !empty($this->pass))
  400. $headers .= "Authorization: BASIC ".base64_encode($this->user.":".$this->pass)."\r\n";
  401. $headers .= "\r\n";
  402. // set the read timeout if needed
  403. if ($this->read_timeout > 0)
  404. socket_set_timeout($fp, $this->read_timeout);
  405. $this->timed_out = false;
  406. fwrite($fp,$headers.$body,strlen($headers.$body));
  407. $this->_redirectaddr = false;
  408. unset($this->headers);
  409. // content was returned gzip encoded?
  410. $is_gzipped = false;
  411. while($currentHeader = fgets($fp,$this->_maxlinelen))
  412. {
  413. if ($this->read_timeout > 0 && $this->_check_timeout($fp))
  414. {
  415. $this->status=-100;
  416. return false;
  417. }
  418. // if($currentHeader == "\r\n")
  419. if(preg_match("/^\r?\n$/", $currentHeader) )
  420. break;
  421. // if a header begins with Location: or URI:, set the redirect
  422. if(preg_match("/^(Location:|URI:)/i",$currentHeader))
  423. {
  424. // get URL portion of the redirect
  425. preg_match("/^(Location:|URI:)\s+(.*)/",chop($currentHeader),$matches);
  426. // look for :// in the Location header to see if hostname is included
  427. if(!preg_match("|\:\/\/|",$matches[2]))
  428. {
  429. // no host in the path, so prepend
  430. $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port;
  431. // eliminate double slash
  432. if(!preg_match("|^/|",$matches[2]))
  433. $this->_redirectaddr .= "/".$matches[2];
  434. else
  435. $this->_redirectaddr .= $matches[2];
  436. }
  437. else
  438. $this->_redirectaddr = $matches[2];
  439. }
  440. if(preg_match("|^HTTP/|",$currentHeader))
  441. {
  442. if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$currentHeader, $status))
  443. {
  444. $this->status= $status[1];
  445. }
  446. $this->response_code = $currentHeader;
  447. }
  448. if (preg_match("/Content-Encoding: gzip/", $currentHeader) ) {
  449. $is_gzipped = true;
  450. }
  451. $this->headers[] = $currentHeader;
  452. }
  453. # $results = fread($fp, $this->maxlength);
  454. $results = "";
  455. while ( $data = fread($fp, $this->maxlength) ) {
  456. $results .= $data;
  457. if (
  458. strlen($results) > $this->maxlength ) {
  459. break;
  460. }
  461. }
  462. // gunzip
  463. if ( $is_gzipped ) {
  464. // per http://www.php.net/manual/en/function.gzencode.php
  465. $results = substr($results, 10);
  466. $results = gzinflate($results);
  467. }
  468. if ($this->read_timeout > 0 && $this->_check_timeout($fp))
  469. {
  470. $this->status=-100;
  471. return false;
  472. }
  473. // check if there is a a redirect meta tag
  474. if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]+URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match))
  475. {
  476. $this->_redirectaddr = $this->_expandlinks($match[1],$URI);
  477. }
  478. // have we hit our frame depth and is there frame src to fetch?
  479. if(($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i",$results,$match))
  480. {
  481. $this->results[] = $results;
  482. for($x=0; $x<count($match[1]); $x++)
  483. $this->_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host);
  484. }
  485. // have we already fetched framed content?
  486. elseif(is_array($this->results))
  487. $this->results[] = $results;
  488. // no framed content
  489. else
  490. $this->results = $results;
  491. return true;
  492. }
  493. /*======================================================================*\
  494. Function: _httpsrequest
  495. Purpose: go get the https data from the server using curl
  496. Input: $url the url to fetch
  497. $URI the full URI
  498. $body body contents to send if any (POST)
  499. Output:
  500. \*======================================================================*/
  501. function _httpsrequest($url,$URI,$http_method,$content_type="",$body="")
  502. {
  503. if($this->passcookies && $this->_redirectaddr)
  504. $this->setcookies();
  505. $headers = array();
  506. $URI_PARTS = parse_url($URI);
  507. if(empty($url))
  508. $url = "/";
  509. // GET ... header not needed for curl
  510. //$headers[] = $http_method." ".$url." ".$this->_httpversion;
  511. if(!empty($this->agent))
  512. $headers[] = "User-Agent: ".$this->agent;
  513. if(!empty($this->host))
  514. $headers[] = "Host: ".$this->host;
  515. if(!empty($this->accept))
  516. $headers[] = "Accept: ".$this->accept;
  517. if(!empty($this->referer))
  518. $headers[] = "Referer: ".$this->referer;
  519. if(!empty($this->cookies))
  520. {
  521. if(!is_array($this->cookies))
  522. $this->cookies = (array)$this->cookies;
  523. reset($this->cookies);
  524. if ( count($this->cookies) > 0 ) {
  525. $cookie_str = 'Cookie: ';
  526. foreach ( $this->cookies as $cookieKey => $cookieVal ) {
  527. $cookie_str .= $cookieKey."=".urlencode($cookieVal)."; ";
  528. }
  529. $headers[] = substr($cookie_str,0,-2);
  530. }
  531. }
  532. if(!empty($this->rawheaders))
  533. {
  534. if(!is_array($this->rawheaders))
  535. $this->rawheaders = (array)$this->rawheaders;
  536. while(list($headerKey,$headerVal) = each($this->rawheaders))
  537. $headers[] = $headerKey.": ".$headerVal;
  538. }
  539. if(!empty($content_type)) {
  540. if ($content_type == "multipart/form-data")
  541. $headers[] = "Content-type: $content_type; boundary=".$this->_mime_boundary;
  542. else
  543. $headers[] = "Content-type: $content_type";
  544. }
  545. if(!empty($body))
  546. $headers[] = "Content-length: ".strlen($body);
  547. if(!empty($this->user) || !empty($this->pass))
  548. $headers[] = "Authorization: BASIC ".base64_encode($this->user.":".$this->pass);
  549. for($curr_header = 0; $curr_header < count($headers); $curr_header++)
  550. $cmdline_params .= " -H \"".$headers[$curr_header]."\"";
  551. if(!empty($body))
  552. $cmdline_params .= " -d \"$body\"";
  553. if($this->read_timeout > 0)
  554. $cmdline_params .= " -m ".$this->read_timeout;
  555. $headerfile = uniqid(time());
  556. # accept self-signed certs
  557. $cmdline_params .= " -k";
  558. exec($this->curl_path." -D \"/tmp/$headerfile\"".$cmdline_params." ".$URI,$results,$return);
  559. if($return)
  560. {
  561. $this->error = "Error: cURL could not retrieve the document, error $return.";
  562. return false;
  563. }
  564. $results = implode("\r\n",$results);
  565. $result_headers = file("/tmp/$headerfile");
  566. $this->_redirectaddr = false;
  567. unset($this->headers);
  568. for($currentHeader = 0; $currentHeader < count($result_headers); $currentHeader++)
  569. {
  570. // if a header begins with Location: or URI:, set the redirect
  571. if(preg_match("/^(Location: |URI: )/i",$result_headers[$currentHeader]))
  572. {
  573. // get URL portion of the redirect
  574. preg_match("/^(Location: |URI:)(.*)/",chop($result_headers[$currentHeader]),$matches);
  575. // look for :// in the Location header to see if hostname is included
  576. if(!preg_match("|\:\/\/|",$matches[2]))
  577. {
  578. // no host in the path, so prepend
  579. $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port;
  580. // eliminate double slash
  581. if(!preg_match("|^/|",$matches[2]))
  582. $this->_redirectaddr .= "/".$matches[2];
  583. else
  584. $this->_redirectaddr .= $matches[2];
  585. }
  586. else
  587. $this->_redirectaddr = $matches[2];
  588. }
  589. if(preg_match("|^HTTP/|",$result_headers[$currentHeader]))
  590. {
  591. $this->response_code = $result_headers[$currentHeader];
  592. if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$this->response_code, $match))
  593. {
  594. $this->status= $match[1];
  595. }
  596. }
  597. $this->headers[] = $result_headers[$currentHeader];
  598. }
  599. // check if there is a a redirect meta tag
  600. if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]+URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match))
  601. {
  602. $this->_redirectaddr = $this->_expandlinks($match[1],$URI);
  603. }
  604. // have we hit our frame depth and is there frame src to fetch?
  605. if(($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i",$results,$match))
  606. {
  607. $this->results[] = $results;
  608. for($x=0; $x<count($match[1]); $x++)
  609. $this->_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host);
  610. }
  611. // have we already fetched framed content?
  612. elseif(is_array($this->results))
  613. $this->results[] = $results;
  614. // no framed content
  615. else
  616. $this->results = $results;
  617. unlink("/tmp/$headerfile");
  618. return true;
  619. }
  620. /*======================================================================*\
  621. Function: setcookies()
  622. Purpose: set cookies for a redirection
  623. \*======================================================================*/
  624. function setcookies()
  625. {
  626. for($x=0; $x<count($this->headers); $x++)
  627. {
  628. if(preg_match("/^set-cookie:[\s]+([^=]+)=([^;]+)/i", $this->headers[$x],$match))
  629. $this->cookies[$match[1]] = $match[2];
  630. }
  631. }
  632. /*======================================================================*\
  633. Function: _check_timeout
  634. Purpose: checks whether timeout has occurred
  635. Input: $fp file pointer
  636. \*======================================================================*/
  637. function _check_timeout($fp)
  638. {
  639. if ($this->read_timeout > 0) {
  640. $fp_status = socket_get_status($fp);
  641. if ($fp_status["timed_out"]) {
  642. $this->timed_out = true;
  643. return true;
  644. }
  645. }
  646. return false;
  647. }
  648. /*======================================================================*\
  649. Function: _connect
  650. Purpose: make a socket connection
  651. Input: $fp file pointer
  652. \*======================================================================*/
  653. function _connect(&$fp)
  654. {
  655. if(!empty($this->proxy_host) && !empty($this->proxy_port))
  656. {
  657. $this->_isproxy = true;
  658. $host = $this->proxy_host;
  659. $port = $this->proxy_port;
  660. }
  661. else
  662. {
  663. $host = $this->host;
  664. $port = $this->port;
  665. }
  666. $this->status = 0;
  667. if($fp = fsockopen(
  668. $host,
  669. $port,
  670. $errno,
  671. $errstr,
  672. $this->_fp_timeout
  673. ))
  674. {
  675. // socket connection succeeded
  676. return true;
  677. }
  678. else
  679. {
  680. // socket connection failed
  681. $this->status = $errno;
  682. switch($errno)
  683. {
  684. case -3:
  685. $this->error="socket creation failed (-3)";
  686. case -4:
  687. $this->error="dns lookup failure (-4)";
  688. case -5:
  689. $this->error="connection refused or timed out (-5)";
  690. default:
  691. $this->error="connection failed (".$errno.")";
  692. }
  693. return false;
  694. }
  695. }
  696. /*======================================================================*\
  697. Function: _disconnect
  698. Purpose: disconnect a socket connection
  699. Input: $fp file pointer
  700. \*======================================================================*/
  701. function _disconnect($fp)
  702. {
  703. return(fclose($fp));
  704. }
  705. /*======================================================================*\
  706. Function: _prepare_post_body
  707. Purpose: Prepare post body according to encoding type
  708. Input: $formvars - form variables
  709. $formfiles - form upload files
  710. Output: post body
  711. \*======================================================================*/
  712. function _prepare_post_body($formvars, $formfiles)
  713. {
  714. settype($formvars, "array");
  715. settype($formfiles, "array");
  716. if (count($formvars) == 0 && count($formfiles) == 0)
  717. return;
  718. switch ($this->_submit_type) {
  719. case "application/x-www-form-urlencoded":
  720. reset($formvars);
  721. while(list($key,$val) = each($formvars)) {
  722. if (is_array($val) || is_object($val)) {
  723. while (list($cur_key, $cur_val) = each($val)) {
  724. $postdata .= urlencode($key)."[]=".urlencode($cur_val)."&";
  725. }
  726. } else
  727. $postdata .= urlencode($key)."=".urlencode($val)."&";
  728. }
  729. break;
  730. case "multipart/form-data":
  731. $this->_mime_boundary = "Snoopy".md5(uniqid(microtime()));
  732. reset($formvars);
  733. while(list($key,$val) = each($formvars)) {
  734. if (is_array($val) || is_object($val)) {
  735. while (list($cur_key, $cur_val) = each($val)) {
  736. $postdata .= "--".$this->_mime_boundary."\r\n";
  737. $postdata .= "Content-Disposition: form-data; name=\"$key\[\]\"\r\n\r\n";
  738. $postdata .= "$cur_val\r\n";
  739. }
  740. } else {
  741. $postdata .= "--".$this->_mime_boundary."\r\n";
  742. $postdata .= "Content-Disposition: form-data; name=\"$key\"\r\n\r\n";
  743. $postdata .= "$val\r\n";
  744. }
  745. }
  746. reset($formfiles);
  747. while (list($field_name, $file_names) = each($formfiles)) {
  748. settype($file_names, "array");
  749. while (list(, $file_name) = each($file_names)) {
  750. if (!is_readable($file_name)) continue;
  751. $fp = fopen($file_name, "r");
  752. $file_content = fread($fp, filesize($file_name));
  753. fclose($fp);
  754. $base_name = basename($file_name);
  755. $postdata .= "--".$this->_mime_boundary."\r\n";
  756. $postdata .= "Content-Disposition: form-data; name=\"$field_name\"; filename=\"$base_name\"\r\n\r\n";
  757. $postdata .= "$file_content\r\n";
  758. }
  759. }
  760. $postdata .= "--".$this->_mime_boundary."--\r\n";
  761. break;
  762. }
  763. return $postdata;
  764. }
  765. }
  766. ?>