1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
29: class Snoopy
30: {
31:
32:
33:
34:
35: var $host = "www.php.net";
36: var $port = 80;
37: var $proxy_host = "";
38: var $proxy_port = "";
39: var $proxy_user = "";
40: var $proxy_pass = "";
41:
42: var $agent = "Snoopy v1.2.5";
43: var $referer = "";
44: var $cookies = array();
45:
46: var $rawheaders = array();
47:
48:
49: var $maxredirs = 5;
50: var $lastredirectaddr = "";
51: var $offsiteok = true;
52: var $maxframes = 0;
53: var $expandlinks = true;
54:
55:
56: var $passcookies = true;
57:
58:
59:
60: var $user = "";
61: var $pass = "";
62:
63:
64: var $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
65:
66: var $results = "";
67:
68: var $error = "";
69: var $response_code = "";
70: var $headers = array();
71: var $maxlength = 500000;
72: var $read_timeout = 0;
73:
74:
75: var $timed_out = false;
76: var $status = 0;
77:
78: var $temp_dir = "/tmp";
79:
80:
81:
82: var $curl_path = "/usr/bin/curl";
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95: var $use_gzip = true;
96:
97:
98: var $_maxlinelen = 4096;
99:
100: var $_httpmethod = "GET";
101: var $_httpversion = "HTTP/1.0";
102: var $_submit_method = "POST";
103: var $_submit_type = "application/x-www-form-urlencoded";
104: var $_mime_boundary = "";
105: var $_redirectaddr = false;
106: var $_redirectdepth = 0;
107: var $_frameurls = array();
108: var $_framedepth = 0;
109:
110: var $_isproxy = false;
111: var $_fp_timeout = 30;
112:
113: 114: 115: 116: 117: 118: 119: 120:
121:
122: function fetch($URI)
123: {
124:
125:
126: $URI_PARTS = parse_url($URI);
127: if (!empty($URI_PARTS["user"]))
128: $this->user = $URI_PARTS["user"];
129: if (!empty($URI_PARTS["pass"]))
130: $this->pass = $URI_PARTS["pass"];
131: if (empty($URI_PARTS["query"]))
132: $URI_PARTS["query"] = '';
133: if (empty($URI_PARTS["path"]))
134: $URI_PARTS["path"] = '';
135:
136: switch (strtolower($URI_PARTS["scheme"])) {
137: case "http":
138: $this->host = $URI_PARTS["host"];
139: if (!empty($URI_PARTS["port"]))
140: $this->port = $URI_PARTS["port"];
141: if ($this->_connect($fp)) {
142: if ($this->_isproxy) {
143:
144: $this->_httprequest($URI, $fp, $URI, $this->_httpmethod);
145: } else {
146: $path = $URI_PARTS["path"] . ($URI_PARTS["query"] ? "?" . $URI_PARTS["query"] : "");
147:
148: $this->_httprequest($path, $fp, $URI, $this->_httpmethod);
149: }
150:
151: $this->_disconnect($fp);
152:
153: if ($this->_redirectaddr) {
154:
155: if ($this->maxredirs > $this->_redirectdepth) {
156:
157: if (preg_match("|^http://" . preg_quote($this->host) . "|i", $this->_redirectaddr) || $this->offsiteok) {
158:
159: $this->_redirectdepth++;
160: $this->lastredirectaddr = $this->_redirectaddr;
161: $this->fetch($this->_redirectaddr);
162: }
163: }
164: }
165:
166: if ($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) {
167: $frameurls = $this->_frameurls;
168: $this->_frameurls = array();
169:
170: while (list(, $frameurl) = each($frameurls)) {
171: if ($this->_framedepth < $this->maxframes) {
172: $this->fetch($frameurl);
173: $this->_framedepth++;
174: } else
175: break;
176: }
177: }
178: } else {
179: return false;
180: }
181: return true;
182: break;
183: case "https":
184: if (!$this->curl_path)
185: return false;
186: if (function_exists("is_executable"))
187: if (!is_executable($this->curl_path))
188: return false;
189: $this->host = $URI_PARTS["host"];
190: if (!empty($URI_PARTS["port"]))
191: $this->port = $URI_PARTS["port"];
192: if ($this->_isproxy) {
193:
194: $this->_httpsrequest($URI, $URI, $this->_httpmethod);
195: } else {
196: $path = $URI_PARTS["path"] . ($URI_PARTS["query"] ? "?" . $URI_PARTS["query"] : "");
197:
198: $this->_httpsrequest($path, $URI, $this->_httpmethod);
199: }
200:
201: if ($this->_redirectaddr) {
202:
203: if ($this->maxredirs > $this->_redirectdepth) {
204:
205: if (preg_match("|^http://" . preg_quote($this->host) . "|i", $this->_redirectaddr) || $this->offsiteok) {
206:
207: $this->_redirectdepth++;
208: $this->lastredirectaddr = $this->_redirectaddr;
209: $this->fetch($this->_redirectaddr);
210: }
211: }
212: }
213:
214: if ($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) {
215: $frameurls = $this->_frameurls;
216: $this->_frameurls = array();
217:
218: while (list(, $frameurl) = each($frameurls)) {
219: if ($this->_framedepth < $this->maxframes) {
220: $this->fetch($frameurl);
221: $this->_framedepth++;
222: } else
223: break;
224: }
225: }
226: return true;
227: break;
228: default:
229:
230: $this->error = 'Invalid protocol "' . $URI_PARTS["scheme"] . '"\n';
231: return false;
232: break;
233: }
234: return true;
235: }
236:
237: 238: 239: 240: 241: 242: 243: 244: 245: 246:
247:
248: function submit($URI, $formvars = "", $formfiles = "")
249: {
250: unset($postdata);
251:
252: $postdata = $this->_prepare_post_body($formvars, $formfiles);
253:
254: $URI_PARTS = parse_url($URI);
255: if (!empty($URI_PARTS["user"]))
256: $this->user = $URI_PARTS["user"];
257: if (!empty($URI_PARTS["pass"]))
258: $this->pass = $URI_PARTS["pass"];
259: if (empty($URI_PARTS["query"]))
260: $URI_PARTS["query"] = '';
261: if (empty($URI_PARTS["path"]))
262: $URI_PARTS["path"] = '';
263:
264: switch (strtolower($URI_PARTS["scheme"])) {
265: case "http":
266: $this->host = $URI_PARTS["host"];
267: if (!empty($URI_PARTS["port"]))
268: $this->port = $URI_PARTS["port"];
269: if ($this->_connect($fp)) {
270: if ($this->_isproxy) {
271:
272: $this->_httprequest($URI, $fp, $URI, $this->_submit_method, $this->_submit_type, $postdata);
273: } else {
274: $path = $URI_PARTS["path"] . ($URI_PARTS["query"] ? "?" . $URI_PARTS["query"] : "");
275:
276: $this->_httprequest($path, $fp, $URI, $this->_submit_method, $this->_submit_type, $postdata);
277: }
278:
279: $this->_disconnect($fp);
280:
281: if ($this->_redirectaddr) {
282:
283: if ($this->maxredirs > $this->_redirectdepth) {
284: if (!preg_match("|^" . $URI_PARTS["scheme"] . "://|", $this->_redirectaddr))
285: $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr, $URI_PARTS["scheme"] . "://" . $URI_PARTS["host"]);
286:
287:
288: if (preg_match("|^http://" . preg_quote($this->host) . "|i", $this->_redirectaddr) || $this->offsiteok) {
289:
290: $this->_redirectdepth++;
291: $this->lastredirectaddr = $this->_redirectaddr;
292: if (strpos($this->_redirectaddr, "?") > 0)
293: $this->fetch($this->_redirectaddr);
294: else
295: $this->submit($this->_redirectaddr, $formvars, $formfiles);
296: }
297: }
298: }
299:
300: if ($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) {
301: $frameurls = $this->_frameurls;
302: $this->_frameurls = array();
303:
304: while (list(, $frameurl) = each($frameurls)) {
305: if ($this->_framedepth < $this->maxframes) {
306: $this->fetch($frameurl);
307: $this->_framedepth++;
308: } else
309: break;
310: }
311: }
312:
313: } else {
314: return false;
315: }
316: return true;
317: break;
318: case "https":
319: if (!$this->curl_path)
320: return false;
321: if (function_exists("is_executable"))
322: if (!is_executable($this->curl_path))
323: return false;
324: $this->host = $URI_PARTS["host"];
325: if (!empty($URI_PARTS["port"]))
326: $this->port = $URI_PARTS["port"];
327: if ($this->_isproxy) {
328:
329: $this->_httpsrequest($URI, $URI, $this->_submit_method, $this->_submit_type, $postdata);
330: } else {
331: $path = $URI_PARTS["path"] . ($URI_PARTS["query"] ? "?" . $URI_PARTS["query"] : "");
332:
333: $this->_httpsrequest($path, $URI, $this->_submit_method, $this->_submit_type, $postdata);
334: }
335:
336: if ($this->_redirectaddr) {
337:
338: if ($this->maxredirs > $this->_redirectdepth) {
339: if (!preg_match("|^" . $URI_PARTS["scheme"] . "://|", $this->_redirectaddr))
340: $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr, $URI_PARTS["scheme"] . "://" . $URI_PARTS["host"]);
341:
342:
343: if (preg_match("|^http://" . preg_quote($this->host) . "|i", $this->_redirectaddr) || $this->offsiteok) {
344:
345: $this->_redirectdepth++;
346: $this->lastredirectaddr = $this->_redirectaddr;
347: if (strpos($this->_redirectaddr, "?") > 0)
348: $this->fetch($this->_redirectaddr);
349: else
350: $this->submit($this->_redirectaddr, $formvars, $formfiles);
351: }
352: }
353: }
354:
355: if ($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) {
356: $frameurls = $this->_frameurls;
357: $this->_frameurls = array();
358:
359: while (list(, $frameurl) = each($frameurls)) {
360: if ($this->_framedepth < $this->maxframes) {
361: $this->fetch($frameurl);
362: $this->_framedepth++;
363: } else
364: break;
365: }
366: }
367: return true;
368: break;
369:
370: default:
371:
372: $this->error = 'Invalid protocol "' . $URI_PARTS["scheme"] . '"\n';
373: return false;
374: break;
375: }
376: return true;
377: }
378:
379: 380: 381: 382: 383: 384:
385:
386: function fetchlinks($URI)
387: {
388: if ($this->fetch($URI)) {
389: if ($this->lastredirectaddr)
390: $URI = $this->lastredirectaddr;
391: if (is_array($this->results)) {
392: for ($x = 0; $x < count($this->results); $x++)
393: $this->results[$x] = $this->_striplinks($this->results[$x]);
394: } else
395: $this->results = $this->_striplinks($this->results);
396:
397: if ($this->expandlinks)
398: $this->results = $this->_expandlinks($this->results, $URI);
399: return true;
400: } else
401: return false;
402: }
403:
404: 405: 406: 407: 408: 409:
410:
411: function fetchform($URI)
412: {
413:
414: if ($this->fetch($URI)) {
415:
416: if (is_array($this->results)) {
417: for ($x = 0; $x < count($this->results); $x++)
418: $this->results[$x] = $this->_stripform($this->results[$x]);
419: } else
420: $this->results = $this->_stripform($this->results);
421:
422: return true;
423: } else
424: return false;
425: }
426:
427:
428: 429: 430: 431: 432: 433:
434:
435: function fetchtext($URI)
436: {
437: if ($this->fetch($URI)) {
438: if (is_array($this->results)) {
439: for ($x = 0; $x < count($this->results); $x++)
440: $this->results[$x] = $this->_striptext($this->results[$x]);
441: } else
442: $this->results = $this->_striptext($this->results);
443: return true;
444: } else
445: return false;
446: }
447:
448: 449: 450: 451: 452: 453:
454:
455: function submitlinks($URI, $formvars = "", $formfiles = "")
456: {
457: if ($this->submit($URI, $formvars, $formfiles)) {
458: if ($this->lastredirectaddr)
459: $URI = $this->lastredirectaddr;
460: if (is_array($this->results)) {
461: for ($x = 0; $x < count($this->results); $x++) {
462: $this->results[$x] = $this->_striplinks($this->results[$x]);
463: if ($this->expandlinks)
464: $this->results[$x] = $this->_expandlinks($this->results[$x], $URI);
465: }
466: } else {
467: $this->results = $this->_striplinks($this->results);
468: if ($this->expandlinks)
469: $this->results = $this->_expandlinks($this->results, $URI);
470: }
471: return true;
472: } else
473: return false;
474: }
475:
476: 477: 478: 479: 480: 481:
482:
483: function submittext($URI, $formvars = "", $formfiles = "")
484: {
485: if ($this->submit($URI, $formvars, $formfiles)) {
486: if ($this->lastredirectaddr)
487: $URI = $this->lastredirectaddr;
488: if (is_array($this->results)) {
489: for ($x = 0; $x < count($this->results); $x++) {
490: $this->results[$x] = $this->_striptext($this->results[$x]);
491: if ($this->expandlinks)
492: $this->results[$x] = $this->_expandlinks($this->results[$x], $URI);
493: }
494: } else {
495: $this->results = $this->_striptext($this->results);
496: if ($this->expandlinks)
497: $this->results = $this->_expandlinks($this->results, $URI);
498: }
499: return true;
500: } else
501: return false;
502: }
503:
504:
505: 506: 507: 508: 509:
510: function set_submit_multipart()
511: {
512: $this->_submit_type = "multipart/form-data";
513: }
514:
515:
516: 517: 518: 519: 520:
521: function set_submit_normal()
522: {
523: $this->_submit_type = "application/x-www-form-urlencoded";
524: }
525:
526:
527:
528:
529: 530: 531:
532:
533:
534: 535: 536: 537: 538: 539:
540:
541: function _striplinks($document)
542: {
543: preg_match_all("'<\s*a\s.*?href\s*=\s* # find <a href=
544: ([\"\'])? # find single or double quote
545: (?(1) (.*?)\\1 | ([^\s\>]+)) # if quote found, match up to next matching
546: # quote, otherwise match up to next space
547: 'isx", $document, $links);
548:
549:
550:
551:
552: while (list($key, $val) = each($links[2])) {
553: if (!empty($val))
554: $match[] = $val;
555: }
556:
557: while (list($key, $val) = each($links[3])) {
558: if (!empty($val))
559: $match[] = $val;
560: }
561:
562:
563: return $match;
564: }
565:
566: 567: 568: 569: 570: 571:
572:
573: function _stripform($document)
574: {
575: preg_match_all("'<\/?(FORM|INPUT|SELECT|TEXTAREA|(OPTION))[^<>]*>(?(2)(.*(?=<\/?(option|select)[^<>]*>[\r\n]*)|(?=[\r\n]*))|(?=[\r\n]*))'Usi", $document, $elements);
576:
577:
578: $match = implode("\r\n", $elements[0]);
579:
580:
581: return $match;
582: }
583:
584:
585: 586: 587: 588: 589: 590:
591:
592: function _striptext($document)
593: {
594:
595:
596:
597:
598:
599: $search = array("'<script[^>]*?>.*?</script>'si",
600: "'<[\/\!]*?[^<>]*?>'si",
601: "'([\r\n])[\s]+'",
602: "'&(quot|#34|#034|#x22);'i",
603: "'&(amp|#38|#038|#x26);'i",
604: "'&(lt|#60|#060|#x3c);'i",
605: "'&(gt|#62|#062|#x3e);'i",
606: "'&(nbsp|#160|#xa0);'i",
607: "'&(iexcl|#161);'i",
608: "'&(cent|#162);'i",
609: "'&(pound|#163);'i",
610: "'&(copy|#169);'i",
611: "'&(reg|#174);'i",
612: "'&(deg|#176);'i",
613: "'&(#39|#039|#x27);'",
614: "'&(euro|#8364);'i",
615: "'&a(uml|UML);'",
616: "'&o(uml|UML);'",
617: "'&u(uml|UML);'",
618: "'&A(uml|UML);'",
619: "'&O(uml|UML);'",
620: "'&U(uml|UML);'",
621: "'ß'i",
622: );
623: $replace = array("",
624: "",
625: "\\1",
626: "\"",
627: "&",
628: "<",
629: ">",
630: " ",
631: chr(161),
632: chr(162),
633: chr(163),
634: chr(169),
635: chr(174),
636: chr(176),
637: chr(39),
638: chr(128),
639: "ä",
640: "ö",
641: "ü",
642: "Ä",
643: "Ö",
644: "Ü",
645: "ß",
646: );
647:
648: $text = preg_replace($search, $replace, $document);
649:
650: return $text;
651: }
652:
653: 654: 655: 656: 657: 658: 659:
660:
661: function _expandlinks($links, $URI)
662: {
663:
664: preg_match("/^[^\?]+/", $URI, $match);
665:
666: $match = preg_replace("|/[^\/\.]+\.[^\/\.]+$|", "", $match[0]);
667: $match = preg_replace("|/$|", "", $match);
668: $match_part = parse_url($match);
669: $match_root =
670: $match_part["scheme"] . "://" . $match_part["host"];
671:
672: $search = array("|^http://" . preg_quote($this->host) . "|i",
673: "|^(\/)|i",
674: "|^(?!http://)(?!mailto:)|i",
675: "|/\./|",
676: "|/[^\/]+/\.\./|"
677: );
678:
679: $replace = array("",
680: $match_root . "/",
681: $match . "/",
682: "/",
683: "/"
684: );
685:
686: $expandedLinks = preg_replace($search, $replace, $links);
687:
688: return $expandedLinks;
689: }
690:
691: 692: 693: 694: 695: 696: 697: 698: 699:
700:
701: function _httprequest($url, $fp, $URI, $http_method, $content_type = "", $body = "")
702: {
703: $cookie_headers = '';
704: if ($this->passcookies && $this->_redirectaddr)
705: $this->setcookies();
706:
707: $URI_PARTS = parse_url($URI);
708: if (empty($url))
709: $url = "/";
710: $headers = $http_method . " " . $url . " " . $this->_httpversion . "\r\n";
711: if (!empty($this->agent))
712: $headers .= "User-Agent: " . $this->agent . "\r\n";
713: if (!empty($this->host) && !isset($this->rawheaders['Host'])) {
714: $headers .= "Host: " . $this->host;
715: if (!empty($this->port) && $this->port != '80')
716: $headers .= ":" . $this->port;
717: $headers .= "\r\n";
718: }
719: if (!empty($this->accept))
720: $headers .= "Accept: " . $this->accept . "\r\n";
721: if ($this->use_gzip) {
722:
723:
724: if (function_exists('gzinflate')) {
725: $headers .= "Accept-encoding: gzip\r\n";
726: } else {
727: trigger_error(
728: "use_gzip is on, but PHP was built without zlib support." .
729: " Requesting file(s) without gzip encoding.",
730: E_USER_NOTICE);
731: }
732: }
733: if (!empty($this->referer))
734: $headers .= "Referer: " . $this->referer . "\r\n";
735: if (!empty($this->cookies)) {
736: if (!is_array($this->cookies))
737: $this->cookies = (array)$this->cookies;
738:
739: reset($this->cookies);
740: if (count($this->cookies) > 0) {
741: $cookie_headers .= 'Cookie: ';
742: foreach ($this->cookies as $cookieKey => $cookieVal) {
743: $cookie_headers .= $cookieKey . "=" . urlencode($cookieVal) . "; ";
744: }
745: $headers .= substr($cookie_headers, 0, -2) . "\r\n";
746: }
747: }
748: if (!empty($this->rawheaders)) {
749: if (!is_array($this->rawheaders))
750: $this->rawheaders = (array)$this->rawheaders;
751: while (list($headerKey, $headerVal) = each($this->rawheaders))
752: $headers .= $headerKey . ": " . $headerVal . "\r\n";
753: }
754: if (!empty($content_type)) {
755: $headers .= "Content-type: $content_type";
756: if ($content_type == "multipart/form-data")
757: $headers .= "; boundary=" . $this->_mime_boundary;
758: $headers .= "\r\n";
759: }
760: if (!empty($body))
761: $headers .= "Content-length: " . strlen($body) . "\r\n";
762: if (!empty($this->user) || !empty($this->pass))
763: $headers .= "Authorization: Basic " . base64_encode($this->user . ":" . $this->pass) . "\r\n";
764:
765:
766: if (!empty($this->proxy_user))
767: $headers .= 'Proxy-Authorization: ' . 'Basic ' . base64_encode($this->proxy_user . ':' . $this->proxy_pass) . "\r\n";
768:
769:
770: $headers .= "\r\n";
771:
772:
773: if ($this->read_timeout > 0)
774: socket_set_timeout($fp, $this->read_timeout);
775: $this->timed_out = false;
776:
777: fwrite($fp, $headers . $body, strlen($headers . $body));
778:
779: $this->_redirectaddr = false;
780: unset($this->headers);
781:
782:
783: $is_gzipped = false;
784:
785: while ($currentHeader = fgets($fp, $this->_maxlinelen)) {
786: if ($this->read_timeout > 0 && $this->_check_timeout($fp)) {
787: $this->status = -100;
788: return false;
789: }
790:
791: if ($currentHeader == "\r\n")
792: break;
793:
794:
795: if (preg_match("/^(Location:|URI:)/i", $currentHeader)) {
796:
797: preg_match("/^(Location:|URI:)[ ]+(.*)/i", chop($currentHeader), $matches);
798:
799: if (!preg_match("|\:\/\/|", $matches[2])) {
800:
801: $this->_redirectaddr = $URI_PARTS["scheme"] . "://" . $this->host . ":" . $this->port;
802:
803: if (!preg_match("|^/|", $matches[2]))
804: $this->_redirectaddr .= "/" . $matches[2];
805: else
806: $this->_redirectaddr .= $matches[2];
807: } else
808: $this->_redirectaddr = $matches[2];
809: }
810:
811: if (preg_match("|^HTTP/|", $currentHeader)) {
812: if (preg_match("|^HTTP/[^\s]*\s(.*?)\s|", $currentHeader, $status)) {
813: $this->status = $status[1];
814: }
815: $this->response_code = $currentHeader;
816: }
817:
818: if (preg_match("/Content-Encoding: gzip/", $currentHeader)) {
819: $is_gzipped = true;
820: }
821:
822: $this->headers[] = $currentHeader;
823: }
824:
825: $results = '';
826: do {
827: $_data = fread($fp, $this->maxlength);
828: if (strlen($_data) == 0) {
829: break;
830: }
831: $results .= $_data;
832: } while (true);
833:
834:
835: if ($is_gzipped) {
836:
837: $results = substr($results, 10);
838: $results = gzinflate($results);
839: }
840:
841: if ($this->read_timeout > 0 && $this->_check_timeout($fp)) {
842: $this->status = -100;
843: return false;
844: }
845:
846:
847:
848: if (preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i", $results, $match)) {
849: $this->_redirectaddr = $this->_expandlinks($match[1], $URI);
850: }
851:
852:
853: if (($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i", $results, $match)) {
854: $this->results[] = $results;
855: for ($x = 0; $x < count($match[1]); $x++)
856: $this->_frameurls[] = $this->_expandlinks($match[1][$x], $URI_PARTS["scheme"] . "://" . $this->host);
857: }
858: elseif (is_array($this->results))
859: $this->results[] = $results;
860:
861: else
862: $this->results = $results;
863:
864: return true;
865: }
866:
867: 868: 869: 870: 871: 872: 873: 874:
875:
876: function _httpsrequest($url, $URI, $http_method, $content_type = "", $body = "")
877: {
878: if ($this->passcookies && $this->_redirectaddr)
879: $this->setcookies();
880:
881: $headers = array();
882:
883: $URI_PARTS = parse_url($URI);
884: if (empty($url))
885: $url = "/";
886:
887:
888: if (!empty($this->agent))
889: $headers[] = "User-Agent: " . $this->agent;
890: if (!empty($this->host))
891: if (!empty($this->port))
892: $headers[] = "Host: " . $this->host . ":" . $this->port;
893: else
894: $headers[] = "Host: " . $this->host;
895: if (!empty($this->accept))
896: $headers[] = "Accept: " . $this->accept;
897: if (!empty($this->referer))
898: $headers[] = "Referer: " . $this->referer;
899: if (!empty($this->cookies)) {
900: if (!is_array($this->cookies))
901: $this->cookies = (array)$this->cookies;
902:
903: reset($this->cookies);
904: if (count($this->cookies) > 0) {
905: $cookie_str = 'Cookie: ';
906: foreach ($this->cookies as $cookieKey => $cookieVal) {
907: $cookie_str .= $cookieKey . "=" . urlencode($cookieVal) . "; ";
908: }
909: $headers[] = substr($cookie_str, 0, -2);
910: }
911: }
912: if (!empty($this->rawheaders)) {
913: if (!is_array($this->rawheaders))
914: $this->rawheaders = (array)$this->rawheaders;
915: while (list($headerKey, $headerVal) = each($this->rawheaders))
916: $headers[] = $headerKey . ": " . $headerVal;
917: }
918: if (!empty($content_type)) {
919: if ($content_type == "multipart/form-data")
920: $headers[] = "Content-type: $content_type; boundary=" . $this->_mime_boundary;
921: else
922: $headers[] = "Content-type: $content_type";
923: }
924: if (!empty($body))
925: $headers[] = "Content-length: " . strlen($body);
926: if (!empty($this->user) || !empty($this->pass))
927: $headers[] = "Authorization: BASIC " . base64_encode($this->user . ":" . $this->pass);
928:
929: for ($curr_header = 0; $curr_header < count($headers); $curr_header++) {
930: $safer_header = strtr($headers[$curr_header], "\"", " ");
931: $cmdline_params .= " -H \"" . $safer_header . "\"";
932: }
933:
934: if (!empty($body))
935: $cmdline_params .= " -d \"$body\"";
936:
937: if ($this->read_timeout > 0)
938: $cmdline_params .= " -m " . $this->read_timeout;
939:
940: $headerfile = tempnam($temp_dir, "sno");
941:
942: exec($this->curl_path . " -k -D \"$headerfile\"" . $cmdline_params . " " . escapeshellarg($URI), $results, $return);
943:
944: if ($return) {
945: $this->error = "Error: cURL could not retrieve the document, error $return.";
946: return false;
947: }
948:
949:
950: $results = implode("\r\n", $results);
951:
952: $result_headers = file("$headerfile");
953:
954: $this->_redirectaddr = false;
955: unset($this->headers);
956:
957: for ($currentHeader = 0; $currentHeader < count($result_headers); $currentHeader++) {
958:
959:
960: if (preg_match("/^(Location: |URI: )/i", $result_headers[$currentHeader])) {
961:
962: preg_match("/^(Location: |URI:)\s+(.*)/", chop($result_headers[$currentHeader]), $matches);
963:
964: if (!preg_match("|\:\/\/|", $matches[2])) {
965:
966: $this->_redirectaddr = $URI_PARTS["scheme"] . "://" . $this->host . ":" . $this->port;
967:
968: if (!preg_match("|^/|", $matches[2]))
969: $this->_redirectaddr .= "/" . $matches[2];
970: else
971: $this->_redirectaddr .= $matches[2];
972: } else
973: $this->_redirectaddr = $matches[2];
974: }
975:
976: if (preg_match("|^HTTP/|", $result_headers[$currentHeader])) {
977: $this->response_code = $result_headers[$currentHeader];
978: if (preg_match("|^HTTP/[^\s]*\s(.*?)\s|", $this->response_code, $match)) {
979: $this->status = $match[1];
980: }
981: }
982:
983: $this->headers[] = $result_headers[$currentHeader];
984: }
985:
986:
987:
988: if (preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i", $results, $match)) {
989: $this->_redirectaddr = $this->_expandlinks($match[1], $URI);
990: }
991:
992:
993: if (($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i", $results, $match)) {
994: $this->results[] = $results;
995: for ($x = 0; $x < count($match[1]); $x++)
996: $this->_frameurls[] = $this->_expandlinks($match[1][$x], $URI_PARTS["scheme"] . "://" . $this->host);
997: }
998: elseif (is_array($this->results))
999: $this->results[] = $results;
1000:
1001: else
1002: $this->results = $results;
1003:
1004: unlink("$headerfile");
1005:
1006: return true;
1007: }
1008:
1009: 1010: 1011: 1012:
1013:
1014: function setcookies()
1015: {
1016: for ($x = 0; $x < count($this->headers); $x++) {
1017: if (preg_match('/^set-cookie:[\s]+([^=]+)=([^;]+)/i', $this->headers[$x], $match))
1018: $this->cookies[$match[1]] = urldecode($match[2]);
1019: }
1020: }
1021:
1022:
1023: 1024: 1025: 1026: 1027:
1028:
1029: function _check_timeout($fp)
1030: {
1031: if ($this->read_timeout > 0) {
1032: $fp_status = socket_get_status($fp);
1033: if ($fp_status["timed_out"]) {
1034: $this->timed_out = true;
1035: return true;
1036: }
1037: }
1038: return false;
1039: }
1040:
1041: 1042: 1043: 1044: 1045:
1046:
1047: function _connect(&$fp)
1048: {
1049: if (!empty($this->proxy_host) && !empty($this->proxy_port)) {
1050: $this->_isproxy = true;
1051:
1052: $host = $this->proxy_host;
1053: $port = $this->proxy_port;
1054: } else {
1055: $host = $this->host;
1056: $port = $this->port;
1057: }
1058:
1059: $this->status = 0;
1060:
1061: if ($fp = fsockopen(
1062: $host,
1063: $port,
1064: $errno,
1065: $errstr,
1066: $this->_fp_timeout
1067: )
1068: ) {
1069:
1070:
1071: return true;
1072: } else {
1073:
1074: $this->status = $errno;
1075: switch ($errno) {
1076: case -3:
1077: $this->error = "socket creation failed (-3)";
1078: case -4:
1079: $this->error = "dns lookup failure (-4)";
1080: case -5:
1081: $this->error = "connection refused or timed out (-5)";
1082: default:
1083: $this->error = "connection failed (" . $errno . ")";
1084: }
1085: return false;
1086: }
1087: }
1088:
1089: 1090: 1091: 1092: 1093:
1094:
1095: function _disconnect($fp)
1096: {
1097: return (fclose($fp));
1098: }
1099:
1100:
1101: 1102: 1103: 1104: 1105: 1106: 1107:
1108:
1109: function _prepare_post_body($formvars, $formfiles)
1110: {
1111: settype($formvars, "array");
1112: settype($formfiles, "array");
1113: $postdata = '';
1114:
1115: if (count($formvars) == 0 && count($formfiles) == 0)
1116: return;
1117:
1118: switch ($this->_submit_type) {
1119: case "application/x-www-form-urlencoded":
1120: reset($formvars);
1121: while (list($key, $val) = each($formvars)) {
1122: if (is_array($val) || is_object($val)) {
1123: while (list($cur_key, $cur_val) = each($val)) {
1124: $postdata .= urlencode($key) . "[]=" . urlencode($cur_val) . "&";
1125: }
1126: } else
1127: $postdata .= urlencode($key) . "=" . urlencode($val) . "&";
1128: }
1129: break;
1130:
1131: case "multipart/form-data":
1132: $this->_mime_boundary = "Snoopy" . md5(uniqid(microtime()));
1133:
1134: reset($formvars);
1135: while (list($key, $val) = each($formvars)) {
1136: if (is_array($val) || is_object($val)) {
1137: while (list($cur_key, $cur_val) = each($val)) {
1138: $postdata .= "--" . $this->_mime_boundary . "\r\n";
1139: $postdata .= "Content-Disposition: form-data; name=\"$key\[\]\"\r\n\r\n";
1140: $postdata .= "$cur_val\r\n";
1141: }
1142: } else {
1143: $postdata .= "--" . $this->_mime_boundary . "\r\n";
1144: $postdata .= "Content-Disposition: form-data; name=\"$key\"\r\n\r\n";
1145: $postdata .= "$val\r\n";
1146: }
1147: }
1148:
1149: reset($formfiles);
1150: while (list($field_name, $file_names) = each($formfiles)) {
1151: settype($file_names, "array");
1152: while (list(, $file_name) = each($file_names)) {
1153: if (!is_readable($file_name)) continue;
1154:
1155: $fp = fopen($file_name, "r");
1156: $file_content = fread($fp, filesize($file_name));
1157: fclose($fp);
1158: $base_name = basename($file_name);
1159:
1160: $postdata .= "--" . $this->_mime_boundary . "\r\n";
1161: $postdata .= "Content-Disposition: form-data; name=\"$field_name\"; filename=\"$base_name\"\r\n\r\n";
1162: $postdata .= "$file_content\r\n";
1163: }
1164: }
1165: $postdata .= "--" . $this->_mime_boundary . "--\r\n";
1166: break;
1167: }
1168:
1169: return $postdata;
1170: }
1171: }
1172:
1173: ?>
1174: