source: temp/test-xoops.ec-cube.net/html/class/snoopy.php @ 405

Revision 405, 38.1 KB checked in by root, 20 years ago (diff)
Line 
1<?php
2
3/*************************************************
4
5Snoopy - the PHP net client
6Author: Monte Ohrt <[email protected]>
7Copyright (c): 1999-2000 ispi, all rights reserved
8Version: 1.01
9
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
24You may contact the author of Snoopy by e-mail at:
25[email protected]
26
27Or, write to:
28Monte Ohrt
29CTO, ispi
30237 S. 70th suite 220
31Lincoln, NE 68510
32
33The latest version of Snoopy can be obtained from:
34http://snoopy.sourceforge.net/
35
36*************************************************/
37
38class Snoopy
39{
40    /**** Public variables ****/
41   
42    /* user definable vars */
43
44    var $host           =   "www.php.net";      // host name we are connecting to
45    var $port           =   80;                 // port we are connecting to
46    var $host_port      =   "";                 // port for Host Header
47    var $proxy_host     =   "";                 // proxy host to use
48    var $proxy_port     =   "";                 // proxy port to use
49    var $proxy_user     =   "";                 // proxy user to use
50    var $proxy_pass     =   "";                 // proxy password to use
51   
52    var $agent          =   "Snoopy v1.2.3";    // agent we masquerade as
53    var $referer        =   "";                 // referer info to pass
54    var $cookies        =   array();            // array of cookies to pass
55                                                // $cookies["username"]="joe";
56    var $rawheaders     =   array();            // array of raw headers to send
57                                                // $rawheaders["Content-type"]="text/html";
58
59    var $maxredirs      =   5;                  // http redirection depth maximum. 0 = disallow
60    var $lastredirectaddr   =   "";             // contains address of last redirected address
61    var $offsiteok      =   true;               // allows redirection off-site
62    var $maxframes      =   0;                  // frame content depth maximum. 0 = disallow
63    var $expandlinks    =   true;               // expand links to fully qualified URLs.
64                                                // this only applies to fetchlinks()
65                                                // submitlinks(), and submittext()
66    var $passcookies    =   true;               // pass set cookies back through redirects
67                                                // NOTE: this currently does not respect
68                                                // dates, domains or paths.
69   
70    var $user           =   "";                 // user for http authentication
71    var $pass           =   "";                 // password for http authentication
72   
73    // http accept types
74    var $accept         =   "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
75   
76    var $results        =   "";                 // where the content is put
77       
78    var $error          =   "";                 // error messages sent here
79    var $response_code  =   "";                 // response code returned from server
80    var $headers        =   array();            // headers returned from server sent here
81    var $maxlength      =   500000;             // max return data length (body)
82    var $read_timeout   =   0;                  // timeout on read operations, in seconds
83                                                // supported only since PHP 4 Beta 4
84                                                // set to 0 to disallow timeouts
85    var $timed_out      =   false;              // if a read operation timed out
86    var $status         =   0;                  // http request status
87
88    var $temp_dir       =   "/tmp";             // temporary directory that the webserver
89                                                // has permission to write to.
90                                                // under Windows, this should be C:\temp
91
92    var $curl_path      =   "/usr/local/bin/curl";
93                                                // Snoopy will use cURL for fetching
94                                                // SSL content if a full system path to
95                                                // the cURL binary is supplied here.
96                                                // set to false if you do not have
97                                                // cURL installed. See http://curl.haxx.se
98                                                // for details on installing cURL.
99                                                // Snoopy does *not* use the cURL
100                                                // library functions built into php,
101                                                // as these functions are not stable
102                                                // as of this Snoopy release.
103   
104    /**** Private variables ****/   
105   
106    var $_maxlinelen    =   4096;               // max line length (headers)
107   
108    var $_httpmethod    =   "GET";              // default http request method
109    var $_httpversion   =   "HTTP/1.0";         // default http request version
110    var $_submit_method =   "POST";             // default submit method
111    var $_submit_type   =   "application/x-www-form-urlencoded";    // default submit type
112    var $_mime_boundary =   "";                 // MIME boundary for multipart/form-data submit type
113    var $_redirectaddr  =   false;              // will be set if page fetched is a redirect
114    var $_redirectdepth =   0;                  // increments on an http redirect
115    var $_frameurls     =   array();            // frame src urls
116    var $_framedepth    =   0;                  // increments on frame depth
117   
118    var $_isproxy       =   false;              // set if using a proxy server
119    var $_fp_timeout    =   30;                 // timeout for socket connection
120
121/*======================================================================*\
122    Function:   fetch
123    Purpose:    fetch the contents of a web page
124                (and possibly other protocols in the
125                future like ftp, nntp, gopher, etc.)
126    Input:      $URI    the location of the page to fetch
127    Output:     $this->results  the output text from the fetch
128\*======================================================================*/
129
130    function fetch($URI)
131    {
132   
133        //preg_match("|^([^:]+)://([^:/]+)(:[\d]+)*(.*)|",$URI,$URI_PARTS);
134        $URI_PARTS = parse_url($URI);
135        if (!empty($URI_PARTS["user"]))
136            $this->user = $URI_PARTS["user"];
137        if (!empty($URI_PARTS["pass"]))
138            $this->pass = $URI_PARTS["pass"];
139        if (empty($URI_PARTS["query"]))
140            $URI_PARTS["query"] = '';
141        if (empty($URI_PARTS["path"]))
142            $URI_PARTS["path"] = '';
143               
144        switch(strtolower($URI_PARTS["scheme"]))
145        {
146            case "http":
147                $this->host = $URI_PARTS["host"];
148                if(!empty($URI_PARTS["port"])) {
149                    $this->port = $URI_PARTS["port"];
150                    $this->host_port = $URI_PARTS["port"];
151                }
152                if($this->_connect($fp))
153                {
154                    if($this->_isproxy)
155                    {
156                        // using proxy, send entire URI
157                        $this->_httprequest($URI,$fp,$URI,$this->_httpmethod);
158                    }
159                    else
160                    {
161                        $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
162                        // no proxy, send only the path
163                        $this->_httprequest($path, $fp, $URI, $this->_httpmethod);
164                    }
165                   
166                    $this->_disconnect($fp);
167
168                    if($this->_redirectaddr)
169                    {
170                        /* url was redirected, check if we've hit the max depth */
171                        if($this->maxredirs > $this->_redirectdepth)
172                        {
173                            // only follow redirect if it's on this site, or offsiteok is true
174                            if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
175                            {
176                                /* follow the redirect */
177                                $this->_redirectdepth++;
178                                $this->lastredirectaddr=$this->_redirectaddr;
179                                $this->fetch($this->_redirectaddr);
180                            }
181                        }
182                    }
183
184                    if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
185                    {
186                        $frameurls = $this->_frameurls;
187                        $this->_frameurls = array();
188                       
189                        while(list(,$frameurl) = each($frameurls))
190                        {
191                            if($this->_framedepth < $this->maxframes)
192                            {
193                                $this->fetch($frameurl);
194                                $this->_framedepth++;
195                            }
196                            else
197                                break;
198                        }
199                    }                   
200                }
201                else
202                {
203                    return false;
204                }
205                return true;                   
206                break;
207            case "https":
208                if(!$this->curl_path)
209                    return false;
210                if(function_exists("is_executable"))
211                    if (!is_executable($this->curl_path))
212                        return false;
213                $this->host = $URI_PARTS["host"];
214                if(!empty($URI_PARTS["port"])) {
215                    $this->port = $URI_PARTS["port"];
216                    $this->host_port = $URI_PARTS["port"];
217                }
218                if($this->_isproxy)
219                {
220                    // using proxy, send entire URI
221                    $this->_httpsrequest($URI,$URI,$this->_httpmethod);
222                }
223                else
224                {
225                    $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
226                    // no proxy, send only the path
227                    $this->_httpsrequest($path, $URI, $this->_httpmethod);
228                }
229
230                if($this->_redirectaddr)
231                {
232                    /* url was redirected, check if we've hit the max depth */
233                    if($this->maxredirs > $this->_redirectdepth)
234                    {
235                        // only follow redirect if it's on this site, or offsiteok is true
236                        if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
237                        {
238                            /* follow the redirect */
239                            $this->_redirectdepth++;
240                            $this->lastredirectaddr=$this->_redirectaddr;
241                            $this->fetch($this->_redirectaddr);
242                        }
243                    }
244                }
245
246                if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
247                {
248                    $frameurls = $this->_frameurls;
249                    $this->_frameurls = array();
250
251                    while(list(,$frameurl) = each($frameurls))
252                    {
253                        if($this->_framedepth < $this->maxframes)
254                        {
255                            $this->fetch($frameurl);
256                            $this->_framedepth++;
257                        }
258                        else
259                            break;
260                    }
261                }                   
262                return true;                   
263                break;
264            default:
265                // not a valid protocol
266                $this->error    =   'Invalid protocol "'.$URI_PARTS["scheme"].'"\n';
267                return false;
268                break;
269        }       
270        return true;
271    }
272
273/*======================================================================*\
274    Function:   submit
275    Purpose:    submit an http form
276    Input:      $URI    the location to post the data
277                $formvars   the formvars to use.
278                    format: $formvars["var"] = "val";
279                $formfiles  an array of files to submit
280                    format: $formfiles["var"] = "/dir/filename.ext";
281    Output:     $this->results  the text output from the post
282\*======================================================================*/
283
284    function submit($URI, $formvars="", $formfiles="")
285    {
286        unset($postdata);
287       
288        $postdata = $this->_prepare_post_body($formvars, $formfiles);
289           
290        $URI_PARTS = parse_url($URI);
291        if (!empty($URI_PARTS["user"]))
292            $this->user = $URI_PARTS["user"];
293        if (!empty($URI_PARTS["pass"]))
294            $this->pass = $URI_PARTS["pass"];
295        if (empty($URI_PARTS["query"]))
296            $URI_PARTS["query"] = '';
297        if (empty($URI_PARTS["path"]))
298            $URI_PARTS["path"] = '';
299
300        switch(strtolower($URI_PARTS["scheme"]))
301        {
302            case "http":
303                $this->host = $URI_PARTS["host"];
304                if(!empty($URI_PARTS["port"])) {
305                    $this->port = $URI_PARTS["port"];
306                    $this->host_port = $URI_PARTS["port"];
307                }
308                if($this->_connect($fp))
309                {
310                    if($this->_isproxy)
311                    {
312                        // using proxy, send entire URI
313                        $this->_httprequest($URI,$fp,$URI,$this->_submit_method,$this->_submit_type,$postdata);
314                    }
315                    else
316                    {
317                        $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
318                        // no proxy, send only the path
319                        $this->_httprequest($path, $fp, $URI, $this->_submit_method, $this->_submit_type, $postdata);
320                    }
321                   
322                    $this->_disconnect($fp);
323
324                    if($this->_redirectaddr)
325                    {
326                        /* url was redirected, check if we've hit the max depth */
327                        if($this->maxredirs > $this->_redirectdepth)
328                        {                       
329                            if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr))
330                                $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);                     
331                           
332                            // only follow redirect if it's on this site, or offsiteok is true
333                            if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
334                            {
335                                /* follow the redirect */
336                                $this->_redirectdepth++;
337                                $this->lastredirectaddr=$this->_redirectaddr;
338                                if( strpos( $this->_redirectaddr, "?" ) > 0 )
339                                    $this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get
340                                else
341                                    $this->submit($this->_redirectaddr,$formvars, $formfiles);
342                            }
343                        }
344                    }
345
346                    if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
347                    {
348                        $frameurls = $this->_frameurls;
349                        $this->_frameurls = array();
350                       
351                        while(list(,$frameurl) = each($frameurls))
352                        {                                                       
353                            if($this->_framedepth < $this->maxframes)
354                            {
355                                $this->fetch($frameurl);
356                                $this->_framedepth++;
357                            }
358                            else
359                                break;
360                        }
361                    }                   
362                   
363                }
364                else
365                {
366                    return false;
367                }
368                return true;                   
369                break;
370            case "https":
371                if(!$this->curl_path)
372                    return false;
373                if(function_exists("is_executable"))
374                    if (!is_executable($this->curl_path))
375                        return false;
376                $this->host = $URI_PARTS["host"];
377                if(!empty($URI_PARTS["port"])) {
378                    $this->port = $URI_PARTS["port"];
379                    $this->host_port = $URI_PARTS["port"];
380                }
381                if($this->_isproxy)
382                {
383                    // using proxy, send entire URI
384                    $this->_httpsrequest($URI, $URI, $this->_submit_method, $this->_submit_type, $postdata);
385                }
386                else
387                {
388                    $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
389                    // no proxy, send only the path
390                    $this->_httpsrequest($path, $URI, $this->_submit_method, $this->_submit_type, $postdata);
391                }
392
393                if($this->_redirectaddr)
394                {
395                    /* url was redirected, check if we've hit the max depth */
396                    if($this->maxredirs > $this->_redirectdepth)
397                    {                       
398                        if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr))
399                            $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]);                     
400
401                        // only follow redirect if it's on this site, or offsiteok is true
402                        if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok)
403                        {
404                            /* follow the redirect */
405                            $this->_redirectdepth++;
406                            $this->lastredirectaddr=$this->_redirectaddr;
407                            if( strpos( $this->_redirectaddr, "?" ) > 0 )
408                                $this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get
409                            else
410                                $this->submit($this->_redirectaddr,$formvars, $formfiles);
411                        }
412                    }
413                }
414
415                if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0)
416                {
417                    $frameurls = $this->_frameurls;
418                    $this->_frameurls = array();
419
420                    while(list(,$frameurl) = each($frameurls))
421                    {                                                       
422                        if($this->_framedepth < $this->maxframes)
423                        {
424                            $this->fetch($frameurl);
425                            $this->_framedepth++;
426                        }
427                        else
428                            break;
429                    }
430                }                   
431                return true;                   
432                break;
433               
434            default:
435                // not a valid protocol
436                $this->error    =   'Invalid protocol "'.$URI_PARTS["scheme"].'"\n';
437                return false;
438                break;
439        }       
440        return true;
441    }
442
443/*======================================================================*\
444    Function:   fetchlinks
445    Purpose:    fetch the links from a web page
446    Input:      $URI    where you are fetching from
447    Output:     $this->results  an array of the URLs
448\*======================================================================*/
449
450    function fetchlinks($URI)
451    {
452        if ($this->fetch($URI))
453        {           
454            if($this->lastredirectaddr)
455                $URI = $this->lastredirectaddr;
456            if(is_array($this->results))
457            {
458                for($x=0;$x<count($this->results);$x++)
459                    $this->results[$x] = $this->_striplinks($this->results[$x]);
460            }
461            else
462                $this->results = $this->_striplinks($this->results);
463
464            if($this->expandlinks)
465                $this->results = $this->_expandlinks($this->results, $URI);
466            return true;
467        }
468        else
469            return false;
470    }
471
472/*======================================================================*\
473    Function:   fetchform
474    Purpose:    fetch the form elements from a web page
475    Input:      $URI    where you are fetching from
476    Output:     $this->results  the resulting html form
477\*======================================================================*/
478
479    function fetchform($URI)
480    {
481       
482        if ($this->fetch($URI))
483        {           
484
485            if(is_array($this->results))
486            {
487                for($x=0;$x<count($this->results);$x++)
488                    $this->results[$x] = $this->_stripform($this->results[$x]);
489            }
490            else
491                $this->results = $this->_stripform($this->results);
492           
493            return true;
494        }
495        else
496            return false;
497    }
498   
499   
500/*======================================================================*\
501    Function:   fetchtext
502    Purpose:    fetch the text from a web page, stripping the links
503    Input:      $URI    where you are fetching from
504    Output:     $this->results  the text from the web page
505\*======================================================================*/
506
507    function fetchtext($URI)
508    {
509        if($this->fetch($URI))
510        {           
511            if(is_array($this->results))
512            {
513                for($x=0;$x<count($this->results);$x++)
514                    $this->results[$x] = $this->_striptext($this->results[$x]);
515            }
516            else
517                $this->results = $this->_striptext($this->results);
518            return true;
519        }
520        else
521            return false;
522    }
523
524/*======================================================================*\
525    Function:   submitlinks
526    Purpose:    grab links from a form submission
527    Input:      $URI    where you are submitting from
528    Output:     $this->results  an array of the links from the post
529\*======================================================================*/
530
531    function submitlinks($URI, $formvars="", $formfiles="")
532    {
533        if($this->submit($URI,$formvars, $formfiles))
534        {           
535            if($this->lastredirectaddr)
536                $URI = $this->lastredirectaddr;
537            if(is_array($this->results))
538            {
539                for($x=0;$x<count($this->results);$x++)
540                {
541                    $this->results[$x] = $this->_striplinks($this->results[$x]);
542                    if($this->expandlinks)
543                        $this->results[$x] = $this->_expandlinks($this->results[$x],$URI);
544                }
545            }
546            else
547            {
548                $this->results = $this->_striplinks($this->results);
549                if($this->expandlinks)
550                    $this->results = $this->_expandlinks($this->results,$URI);
551            }
552            return true;
553        }
554        else
555            return false;
556    }
557
558/*======================================================================*\
559    Function:   submittext
560    Purpose:    grab text from a form submission
561    Input:      $URI    where you are submitting from
562    Output:     $this->results  the text from the web page
563\*======================================================================*/
564
565    function submittext($URI, $formvars = "", $formfiles = "")
566    {
567        if($this->submit($URI,$formvars, $formfiles))
568        {           
569            if($this->lastredirectaddr)
570                $URI = $this->lastredirectaddr;
571            if(is_array($this->results))
572            {
573                for($x=0;$x<count($this->results);$x++)
574                {
575                    $this->results[$x] = $this->_striptext($this->results[$x]);
576                    if($this->expandlinks)
577                        $this->results[$x] = $this->_expandlinks($this->results[$x],$URI);
578                }
579            }
580            else
581            {
582                $this->results = $this->_striptext($this->results);
583                if($this->expandlinks)
584                    $this->results = $this->_expandlinks($this->results,$URI);
585            }
586            return true;
587        }
588        else
589            return false;
590    }
591
592   
593
594/*======================================================================*\
595    Function:   set_submit_multipart
596    Purpose:    Set the form submission content type to
597                multipart/form-data
598\*======================================================================*/
599    function set_submit_multipart()
600    {
601        $this->_submit_type = "multipart/form-data";
602    }
603
604   
605/*======================================================================*\
606    Function:   set_submit_normal
607    Purpose:    Set the form submission content type to
608                application/x-www-form-urlencoded
609\*======================================================================*/
610    function set_submit_normal()
611    {
612        $this->_submit_type = "application/x-www-form-urlencoded";
613    }
614
615   
616// XOOPS2 Hack begin
617// Added on March 4, 2003 by [email protected]
618/*======================================================================*\
619    Function:   set_submit_xml
620    Purpose:    Set the submission content type to
621                text/xml
622\*======================================================================*/
623    function set_submit_xml()
624    {
625        $this->_submit_type = "text/xml";
626    }
627// XOOPS2 Hack end
628   
629
630/*======================================================================*\
631    Private functions
632\*======================================================================*/
633   
634   
635/*======================================================================*\
636    Function:   _striplinks
637    Purpose:    strip the hyperlinks from an html document
638    Input:      $document   document to strip.
639    Output:     $match      an array of the links
640\*======================================================================*/
641
642    function _striplinks($document)
643    {   
644        preg_match_all("'<\s*a\s.*?href\s*=\s*          # find <a href=
645                        ([\"\'])?                   # find single or double quote
646                        (?(1) (.*?)\\1 | ([^\s\>]+))        # if quote found, match up to next matching
647                                                    # quote, otherwise match up to next space
648                        'isx",$document,$links);
649                       
650
651        // catenate the non-empty matches from the conditional subpattern
652
653        while(list($key,$val) = each($links[2]))
654        {
655            if(!empty($val))
656                $match[] = $val;
657        }               
658       
659        while(list($key,$val) = each($links[3]))
660        {
661            if(!empty($val))
662                $match[] = $val;
663        }       
664       
665        // return the links
666        return $match;
667    }
668
669/*======================================================================*\
670    Function:   _stripform
671    Purpose:    strip the form elements from an html document
672    Input:      $document   document to strip.
673    Output:     $match      an array of the links
674\*======================================================================*/
675
676    function _stripform($document)
677    {   
678        preg_match_all("'<\/?(FORM|INPUT|SELECT|TEXTAREA|(OPTION))[^<>]*>(?(2)(.*(?=<\/?(option|select)[^<>]*>[\r\n]*)|(?=[\r\n]*))|(?=[\r\n]*))'Usi",$document,$elements);
679       
680        // catenate the matches
681        $match = implode("\r\n",$elements[0]);
682               
683        // return the links
684        return $match;
685    }
686
687   
688   
689/*======================================================================*\
690    Function:   _striptext
691    Purpose:    strip the text from an html document
692    Input:      $document   document to strip.
693    Output:     $text       the resulting text
694\*======================================================================*/
695
696    function _striptext($document)
697    {
698       
699        // I didn't use preg eval (//e) since that is only available in PHP 4.0.
700        // so, list your entities one by one here. I included some of the
701        // more common ones.
702                               
703        $search = array("'<script[^>]*?>.*?</script>'si",   // strip out javascript
704                        "'<[\/\!]*?[^<>]*?>'si",            // strip out html tags
705                        "'([\r\n])[\s]+'",                  // strip out white space
706                        "'&(quot|#34|#034|#x22);'i",        // replace html entities
707                        "'&(amp|#38|#038|#x26);'i",         // added hexadecimal values
708                        "'&(lt|#60|#060|#x3c);'i",
709                        "'&(gt|#62|#062|#x3e);'i",
710                        "'&(nbsp|#160|#xa0);'i",
711                        "'&(iexcl|#161);'i",
712                        "'&(cent|#162);'i",
713                        "'&(pound|#163);'i",
714                        "'&(copy|#169);'i",
715                        "'&(reg|#174);'i",
716                        "'&(deg|#176);'i",
717                        "'&(#39|#039|#x27);'",
718                        "'&(euro|#8364);'i",                // europe
719                        "'&a(uml|UML);'",                   // german
720                        "'&o(uml|UML);'",
721                        "'&u(uml|UML);'",
722                        "'&A(uml|UML);'",
723                        "'&O(uml|UML);'",
724                        "'&U(uml|UML);'",
725                        "'&szlig;'i",
726                        );
727        $replace = array(   "",
728                            "",
729                            "\\1",
730                            "\"",
731                            "&",
732                            "<",
733                            ">",
734                            " ",
735                            chr(161),
736                            chr(162),
737                            chr(163),
738                            chr(169),
739                            chr(174),
740                            chr(176),
741                            chr(39),
742                            chr(128),
743                            chr(228),
744                            chr(246),
745                            chr(252),
746                            chr(196),
747                            chr(214),
748                            chr(220),
749                            chr(223),
750                        );
751                   
752        $text = preg_replace($search,$replace,$document);
753                               
754        return $text;
755    }
756
757/*======================================================================*\
758    Function:   _expandlinks
759    Purpose:    expand each link into a fully qualified URL
760    Input:      $links          the links to qualify
761                $URI            the full URI to get the base from
762    Output:     $expandedLinks  the expanded links
763\*======================================================================*/
764
765    function _expandlinks($links,$URI)
766    {
767       
768        preg_match("/^[^\?]+/",$URI,$match);
769
770        $match = preg_replace("|/[^\/\.]+\.[^\/\.]+$|","",$match[0]);
771        $match = preg_replace("|/$|","",$match);
772        $match_part = parse_url($match);
773        $match_root =
774        $match_part["scheme"]."://".$match_part["host"];
775               
776        $search = array(    "|^http://".preg_quote($this->host)."|i",
777                            "|^(\/)|i",
778                            "|^(?!http://)(?!mailto:)|i",
779                            "|/\./|",
780                            "|/[^\/]+/\.\./|"
781                        );
782                       
783        $replace = array(   "",
784                            $match_root."/",
785                            $match."/",
786                            "/",
787                            "/"
788                        );         
789               
790        $expandedLinks = preg_replace($search,$replace,$links);
791
792        return $expandedLinks;
793    }
794
795/*======================================================================*\
796    Function:   _httprequest
797    Purpose:    go get the http data from the server
798    Input:      $url        the url to fetch
799                $fp         the current open file pointer
800                $URI        the full URI
801                $body       body contents to send if any (POST)
802    Output:     
803\*======================================================================*/
804   
805    function _httprequest($url,$fp,$URI,$http_method,$content_type="",$body="")
806    {
807        $cookie_headers = '';
808        if($this->passcookies && $this->_redirectaddr)
809            $this->setcookies();
810           
811        $URI_PARTS = parse_url($URI);
812        if(empty($url))
813            $url = "/";
814        $headers = $http_method." ".$url." ".$this->_httpversion."\r\n";       
815        if(!empty($this->agent))
816            $headers .= "User-Agent: ".$this->agent."\r\n";
817        if(!empty($this->host) && !isset($this->rawheaders['Host'])) {
818            $headers .= "Host: ".$this->host;
819            if(!empty($this->host_port))
820                $headers .= ":".$this->host_port;
821            $headers .= "\r\n";
822        }
823        if(!empty($this->accept))
824            $headers .= "Accept: ".$this->accept."\r\n";
825        if(!empty($this->referer))
826            $headers .= "Referer: ".$this->referer."\r\n";
827        if(!empty($this->cookies))
828        {           
829            if(!is_array($this->cookies))
830                $this->cookies = (array)$this->cookies;
831   
832            reset($this->cookies);
833            if ( count($this->cookies) > 0 ) {
834                $cookie_headers .= 'Cookie: ';
835                foreach ( $this->cookies as $cookieKey => $cookieVal ) {
836                $cookie_headers .= $cookieKey."=".urlencode($cookieVal)."; ";
837                }
838                $headers .= substr($cookie_headers,0,-2) . "\r\n";
839            }
840        }
841        if(!empty($this->rawheaders))
842        {
843            if(!is_array($this->rawheaders))
844                $this->rawheaders = (array)$this->rawheaders;
845            while(list($headerKey,$headerVal) = each($this->rawheaders))
846                $headers .= $headerKey.": ".$headerVal."\r\n";
847        }
848        if(!empty($content_type)) {
849            $headers .= "Content-type: $content_type";
850            if ($content_type == "multipart/form-data")
851                $headers .= "; boundary=".$this->_mime_boundary;
852            $headers .= "\r\n";
853        }
854        if(!empty($body))   
855            $headers .= "Content-length: ".strlen($body)."\r\n";
856        if(!empty($this->user) || !empty($this->pass)) 
857            $headers .= "Authorization: Basic ".base64_encode($this->user.":".$this->pass)."\r\n";
858       
859        //add proxy auth headers
860        if(!empty($this->proxy_user))   
861            $headers .= 'Proxy-Authorization: ' . 'Basic ' . base64_encode($this->proxy_user . ':' . $this->proxy_pass)."\r\n";
862
863
864        $headers .= "\r\n";
865       
866        // set the read timeout if needed
867        if ($this->read_timeout > 0)
868            socket_set_timeout($fp, $this->read_timeout);
869        $this->timed_out = false;
870       
871        fwrite($fp,$headers.$body,strlen($headers.$body));
872       
873        $this->_redirectaddr = false;
874        unset($this->headers);
875                       
876        while($currentHeader = fgets($fp,$this->_maxlinelen))
877        {
878            if ($this->read_timeout > 0 && $this->_check_timeout($fp))
879            {
880                $this->status=-100;
881                return false;
882            }
883               
884            if($currentHeader == "\r\n")
885                break;
886                       
887            // if a header begins with Location: or URI:, set the redirect
888            if(preg_match("/^(Location:|URI:)/i",$currentHeader))
889            {
890                // get URL portion of the redirect
891                preg_match("/^(Location:|URI:)[ ]+(.*)/i",chop($currentHeader),$matches);
892                // look for :// in the Location header to see if hostname is included
893                if(!preg_match("|\:\/\/|",$matches[2]))
894                {
895                    // no host in the path, so prepend
896                    $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host;
897                    if(!empty($this->host_port))
898                        $this->_redirectaddr .= ":".$this->host_port;
899                    // eliminate double slash
900                    if(!preg_match("|^/|",$matches[2]))
901                            $this->_redirectaddr .= "/".$matches[2];
902                    else
903                            $this->_redirectaddr .= $matches[2];
904                }
905                else
906                    $this->_redirectaddr = $matches[2];
907            }
908       
909            if(preg_match("|^HTTP/|",$currentHeader))
910            {
911                if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$currentHeader, $status))
912                {
913                    $this->status= $status[1];
914                }               
915                $this->response_code = $currentHeader;
916            }
917               
918            $this->headers[] = $currentHeader;
919        }
920
921        $results = '';
922        do {
923            $_data = fread($fp, $this->maxlength);
924            if (strlen($_data) == 0) {
925                break;
926            }
927            $results .= $_data;
928        } while(true);
929
930        if ($this->read_timeout > 0 && $this->_check_timeout($fp))
931        {
932            $this->status=-100;
933            return false;
934        }
935       
936        // check if there is a a redirect meta tag
937       
938        if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match))
939
940        {
941            $this->_redirectaddr = $this->_expandlinks($match[1],$URI);
942        }
943
944        // have we hit our frame depth and is there frame src to fetch?
945        if(($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i",$results,$match))
946        {
947            $this->results[] = $results;
948            for($x=0; $x<count($match[1]); $x++)
949                $this->_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host);
950        }
951        // have we already fetched framed content?
952        elseif(is_array($this->results))
953            $this->results[] = $results;
954        // no framed content
955        else
956            $this->results = $results;
957       
958        return true;
959    }
960
961/*======================================================================*\
962    Function:   _httpsrequest
963    Purpose:    go get the https data from the server using curl
964    Input:      $url        the url to fetch
965                $URI        the full URI
966                $body       body contents to send if any (POST)
967    Output:     
968\*======================================================================*/
969   
970    function _httpsrequest($url,$URI,$http_method,$content_type="",$body="")
971    {
972        if($this->passcookies && $this->_redirectaddr)
973            $this->setcookies();
974
975        $headers = array();     
976                   
977        $URI_PARTS = parse_url($URI);
978        if(empty($url))
979            $url = "/";
980        // GET ... header not needed for curl
981        //$headers[] = $http_method." ".$url." ".$this->_httpversion;       
982        if(!empty($this->agent))
983            $headers[] = "User-Agent: ".$this->agent;
984        if(!empty($this->host))
985            if(!empty($this->host_port))
986                $headers[] = "Host: ".$this->host.":".$this->host_port;
987            else
988                $headers[] = "Host: ".$this->host;
989        if(!empty($this->accept))
990            $headers[] = "Accept: ".$this->accept;
991        if(!empty($this->referer))
992            $headers[] = "Referer: ".$this->referer;
993        if(!empty($this->cookies))
994        {           
995            if(!is_array($this->cookies))
996                $this->cookies = (array)$this->cookies;
997   
998            reset($this->cookies);
999            if ( count($this->cookies) > 0 ) {
1000                $cookie_str = 'Cookie: ';
1001                foreach ( $this->cookies as $cookieKey => $cookieVal ) {
1002                $cookie_str .= $cookieKey."=".urlencode($cookieVal)."; ";
1003                }
1004                $headers[] = substr($cookie_str,0,-2);
1005            }
1006        }
1007        if(!empty($this->rawheaders))
1008        {
1009            if(!is_array($this->rawheaders))
1010                $this->rawheaders = (array)$this->rawheaders;
1011            while(list($headerKey,$headerVal) = each($this->rawheaders))
1012                $headers[] = $headerKey.": ".$headerVal;
1013        }
1014        if(!empty($content_type)) {
1015            if ($content_type == "multipart/form-data")
1016                $headers[] = "Content-type: $content_type; boundary=".$this->_mime_boundary;
1017            else
1018                $headers[] = "Content-type: $content_type";
1019        }
1020        if(!empty($body))   
1021            $headers[] = "Content-length: ".strlen($body);
1022        if(!empty($this->user) || !empty($this->pass)) 
1023            $headers[] = "Authorization: BASIC ".base64_encode($this->user.":".$this->pass);
1024           
1025        for($curr_header = 0; $curr_header < count($headers); $curr_header++) {
1026            $safer_header = strtr( $headers[$curr_header], "\"", " " );
1027            $cmdline_params .= " -H \"".$safer_header."\"";
1028        }
1029       
1030        if(!empty($body))
1031            $cmdline_params .= " -d \"$body\"";
1032       
1033        if($this->read_timeout > 0)
1034            $cmdline_params .= " -m ".$this->read_timeout;
1035       
1036        $headerfile = tempnam($temp_dir, "sno");
1037
1038        $safer_URI = strtr( $URI, "\"", " " ); // strip quotes from the URI to avoid shell access
1039        exec($this->curl_path." -D \"$headerfile\"".$cmdline_params." \"".$safer_URI."\"",$results,$return);
1040       
1041        if($return)
1042        {
1043            $this->error = "Error: cURL could not retrieve the document, error $return.";
1044            return false;
1045        }
1046           
1047           
1048        $results = implode("\r\n",$results);
1049       
1050        $result_headers = file("$headerfile");
1051                       
1052        $this->_redirectaddr = false;
1053        unset($this->headers);
1054                       
1055        for($currentHeader = 0; $currentHeader < count($result_headers); $currentHeader++)
1056        {
1057           
1058            // if a header begins with Location: or URI:, set the redirect
1059            if(preg_match("/^(Location: |URI: )/i",$result_headers[$currentHeader]))
1060            {
1061                // get URL portion of the redirect
1062                preg_match("/^(Location: |URI:)\s+(.*)/",chop($result_headers[$currentHeader]),$matches);
1063                // look for :// in the Location header to see if hostname is included
1064                if(!preg_match("|\:\/\/|",$matches[2]))
1065                {
1066                    // no host in the path, so prepend
1067                    $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host;
1068                    if(!empty($this->host_port))
1069                        $this->_redirectaddr .= ":".$this->host_port;
1070                    // eliminate double slash
1071                    if(!preg_match("|^/|",$matches[2]))
1072                            $this->_redirectaddr .= "/".$matches[2];
1073                    else
1074                            $this->_redirectaddr .= $matches[2];
1075                }
1076                else
1077                    $this->_redirectaddr = $matches[2];
1078            }
1079       
1080            if(preg_match("|^HTTP/|",$result_headers[$currentHeader]))
1081                $this->response_code = $result_headers[$currentHeader];
1082
1083            $this->headers[] = $result_headers[$currentHeader];
1084        }
1085
1086        // check if there is a a redirect meta tag
1087       
1088        if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match))
1089        {
1090            $this->_redirectaddr = $this->_expandlinks($match[1],$URI);
1091        }
1092
1093        // have we hit our frame depth and is there frame src to fetch?
1094        if(($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i",$results,$match))
1095        {
1096            $this->results[] = $results;
1097            for($x=0; $x<count($match[1]); $x++)
1098                $this->_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host);
1099        }
1100        // have we already fetched framed content?
1101        elseif(is_array($this->results))
1102            $this->results[] = $results;
1103        // no framed content
1104        else
1105            $this->results = $results;
1106
1107        unlink("$headerfile");
1108       
1109        return true;
1110    }
1111
1112/*======================================================================*\
1113    Function:   setcookies()
1114    Purpose:    set cookies for a redirection
1115\*======================================================================*/
1116   
1117    function setcookies()
1118    {
1119        for($x=0; $x<count($this->headers); $x++)
1120        {
1121        if(preg_match('/^set-cookie:[\s]+([^=]+)=([^;]+)/i', $this->headers[$x],$match))
1122            $this->cookies[$match[1]] = urldecode($match[2]);
1123        }
1124    }
1125
1126   
1127/*======================================================================*\
1128    Function:   _check_timeout
1129    Purpose:    checks whether timeout has occurred
1130    Input:      $fp file pointer
1131\*======================================================================*/
1132
1133    function _check_timeout($fp)
1134    {
1135        if ($this->read_timeout > 0) {
1136            $fp_status = socket_get_status($fp);
1137            if ($fp_status["timed_out"]) {
1138                $this->timed_out = true;
1139                return true;
1140            }
1141        }
1142        return false;
1143    }
1144
1145/*======================================================================*\
1146    Function:   _connect
1147    Purpose:    make a socket connection
1148    Input:      $fp file pointer
1149\*======================================================================*/
1150   
1151    function _connect(&$fp)
1152    {
1153        if(!empty($this->proxy_host) && !empty($this->proxy_port))
1154            {
1155                $this->_isproxy = true;
1156               
1157                $host = $this->proxy_host;
1158                $port = $this->proxy_port;
1159            }
1160        else
1161        {
1162            $host = $this->host;
1163            $port = $this->port;
1164        }
1165   
1166        $this->status = 0;
1167       
1168        if($fp = fsockopen(
1169                    $host,
1170                    $port,
1171                    $errno,
1172                    $errstr,
1173                    $this->_fp_timeout
1174                    ))
1175        {
1176            // socket connection succeeded
1177
1178            return true;
1179        }
1180        else
1181        {
1182            // socket connection failed
1183            $this->status = $errno;
1184            switch($errno)
1185            {
1186                case -3:
1187                    $this->error="socket creation failed (-3)";
1188                case -4:
1189                    $this->error="dns lookup failure (-4)";
1190                case -5:
1191                    $this->error="connection refused or timed out (-5)";
1192                default:
1193                    $this->error="connection failed (".$errno.")";
1194            }
1195            return false;
1196        }
1197    }
1198/*======================================================================*\
1199    Function:   _disconnect
1200    Purpose:    disconnect a socket connection
1201    Input:      $fp file pointer
1202\*======================================================================*/
1203   
1204    function _disconnect($fp)
1205    {
1206        return(fclose($fp));
1207    }
1208
1209   
1210/*======================================================================*\
1211    Function:   _prepare_post_body
1212    Purpose:    Prepare post body according to encoding type
1213    Input:      $formvars  - form variables
1214                $formfiles - form upload files
1215    Output:     post body
1216\*======================================================================*/
1217   
1218    function _prepare_post_body($formvars, $formfiles)
1219    {
1220        settype($formvars, "array");
1221        settype($formfiles, "array");
1222        $postdata = '';
1223
1224        if (count($formvars) == 0 && count($formfiles) == 0)
1225            return;
1226       
1227        switch ($this->_submit_type) {
1228            case "application/x-www-form-urlencoded":
1229                reset($formvars);
1230                while(list($key,$val) = each($formvars)) {
1231                    if (is_array($val) || is_object($val)) {
1232                        while (list($cur_key, $cur_val) = each($val)) {
1233                            $postdata .= urlencode($key)."[]=".urlencode($cur_val)."&";
1234                        }
1235                    } else
1236                        $postdata .= urlencode($key)."=".urlencode($val)."&";
1237                }
1238                break;
1239
1240            case "multipart/form-data":
1241                $this->_mime_boundary = "Snoopy".md5(uniqid(microtime()));
1242               
1243                reset($formvars);
1244                while(list($key,$val) = each($formvars)) {
1245                    if (is_array($val) || is_object($val)) {
1246                        while (list($cur_key, $cur_val) = each($val)) {
1247                            $postdata .= "--".$this->_mime_boundary."\r\n";
1248                            $postdata .= "Content-Disposition: form-data; name=\"$key\[\]\"\r\n\r\n";
1249                            $postdata .= "$cur_val\r\n";
1250                        }
1251                    } else {
1252                        $postdata .= "--".$this->_mime_boundary."\r\n";
1253                        $postdata .= "Content-Disposition: form-data; name=\"$key\"\r\n\r\n";
1254                        $postdata .= "$val\r\n";
1255                    }
1256                }
1257               
1258                reset($formfiles);
1259                while (list($field_name, $file_names) = each($formfiles)) {
1260                    settype($file_names, "array");
1261                    while (list(, $file_name) = each($file_names)) {
1262                        if (!is_readable($file_name)) continue;
1263
1264                        $fp = fopen($file_name, "r");
1265                        $file_content = fread($fp, filesize($file_name));
1266                        fclose($fp);
1267                        $base_name = basename($file_name);
1268
1269                        $postdata .= "--".$this->_mime_boundary."\r\n";
1270                        $postdata .= "Content-Disposition: form-data; name=\"$field_name\"; filename=\"$base_name\"\r\n\r\n";
1271                        $postdata .= "$file_content\r\n";
1272                    }
1273                }
1274                $postdata .= "--".$this->_mime_boundary."--\r\n";
1275                break;
1276            // XOOPS2 Hack begin
1277            // Added on March 4, 2003 by [email protected]
1278            case "text/xml":
1279            default:
1280                $postdata = $formvars[0];
1281                break;
1282            // XOOPS2 Hack end
1283        }
1284
1285        return $postdata;
1286    }
1287}
1288
1289?>
Note: See TracBrowser for help on using the repository browser.