Completed
Pull Request — master (#133)
by Goffy
16:45
created

Snoopy::fetchtext()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 10

Duplication

Lines 12
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 12
loc 12
rs 9.2
cc 4
eloc 10
nc 3
nop 1
1
<?php
2
3
/*************************************************
4
 *
5
 * Snoopy - the PHP net client
6
 * Author: Monte Ohrt <[email protected]>
7
 * Copyright (c): 1999-2014, all rights reserved
8
 * Version: 1.2.5
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 *
23
 * You may contact the author of Snoopy by e-mail at:
24
 * [email protected]
25
 *
26
 * The latest version of Snoopy can be obtained from:
27
 * http://snoopy.sourceforge.net/
28
 *************************************************/
29
class Snoopy
30
{
31
    /**** Public variables ****/
32
33
    /* user definable vars */
34
35
    var $host = "www.php.net"; // host name we are connecting to
36
    var $port = 80; // port we are connecting to
37
    var $proxy_host = ""; // proxy host to use
38
    var $proxy_port = ""; // proxy port to use
39
    var $proxy_user = ""; // proxy user to use
40
    var $proxy_pass = ""; // proxy password to use
41
42
    var $agent = "Snoopy v1.2.5"; // agent we masquerade as
43
    var $referer = ""; // referer info to pass
44
    var $cookies = array(); // array of cookies to pass
45
    // $cookies["username"]="joe";
46
    var $rawheaders = array(); // array of raw headers to send
47
    // $rawheaders["Content-type"]="text/html";
48
49
    var $maxredirs = 5; // http redirection depth maximum. 0 = disallow
50
    var $lastredirectaddr = ""; // contains address of last redirected address
51
    var $offsiteok = true; // allows redirection off-site
52
    var $maxframes = 0; // frame content depth maximum. 0 = disallow
53
    var $expandlinks = true; // expand links to fully qualified URLs.
54
    // this only applies to fetchlinks()
55
    // submitlinks(), and submittext()
56
    var $passcookies = true; // pass set cookies back through redirects
57
    // NOTE: this currently does not respect
58
    // dates, domains or paths.
59
60
    var $user = ""; // user for http authentication
61
    var $pass = ""; // password for http authentication
62
63
    // http accept types
64
    var $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
65
66
    var $results = ""; // where the content is put
67
68
    var $error = ""; // error messages sent here
69
    var $response_code = ""; // response code returned from server
70
    var $headers = array(); // headers returned from server sent here
71
    var $maxlength = 500000; // max return data length (body)
72
    var $read_timeout = 0; // timeout on read operations, in seconds
73
    // supported only since PHP 4 Beta 4
74
    // set to 0 to disallow timeouts
75
    var $timed_out = false; // if a read operation timed out
76
    var $status = 0; // http request status
77
78
    var $temp_dir = "/tmp"; // temporary directory that the webserver
79
    // has permission to write to.
80
    // under Windows, this should be C:\temp
81
82
    var $curl_path = "/usr/bin/curl";
83
    // Snoopy will use cURL for fetching
84
    // SSL content if a full system path to
85
    // the cURL binary is supplied here.
86
    // set to false if you do not have
87
    // cURL installed. See http://curl.haxx.se
88
    // for details on installing cURL.
89
    // Snoopy does *not* use the cURL
90
    // library functions built into php,
91
    // as these functions are not stable
92
    // as of this Snoopy release.
93
94
    // send Accept-encoding: gzip?
95
    var $use_gzip = true;
96
    /**** Private variables ****/
97
98
    var $_maxlinelen = 4096; // max line length (headers)
99
100
    var $_httpmethod = "GET"; // default http request method
101
    var $_httpversion = "HTTP/1.0"; // default http request version
102
    var $_submit_method = "POST"; // default submit method
103
    var $_submit_type = "application/x-www-form-urlencoded"; // default submit type
104
    var $_mime_boundary = ""; // MIME boundary for multipart/form-data submit type
105
    var $_redirectaddr = false; // will be set if page fetched is a redirect
106
    var $_redirectdepth = 0; // increments on an http redirect
107
    var $_frameurls = array(); // frame src urls
108
    var $_framedepth = 0; // increments on frame depth
109
110
    var $_isproxy = false; // set if using a proxy server
111
    var $_fp_timeout = 30; // timeout for socket connection
112
113
    /*======================================================================*\
114
        Function:	fetch
115
        Purpose:	fetch the contents of a web page
116
                    (and possibly other protocols in the
117
                    future like ftp, nntp, gopher, etc.)
118
        Input:		$URI	the location of the page to fetch
119
        Output:		$this->results	the output text from the fetch
120
    \*======================================================================*/
121
122
    function fetch($URI)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
123
    {
124
125
        //preg_match("|^([^:]+)://([^:/]+)(:[\d]+)*(.*)|",$URI,$URI_PARTS);
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 View Code Duplication
                    if ($this->_isproxy) {
143
                        // using proxy, send entire URI
144
                        $this->_httprequest($URI, $fp, $URI, $this->_httpmethod);
145
                    } else {
146
                        $path = $URI_PARTS["path"] . ($URI_PARTS["query"] ? "?" . $URI_PARTS["query"] : "");
147
                        // no proxy, send only the path
148
                        $this->_httprequest($path, $fp, $URI, $this->_httpmethod);
149
                    }
150
151
                    $this->_disconnect($fp);
152
153 View Code Duplication
                    if ($this->_redirectaddr) {
154
                        /* url was redirected, check if we've hit the max depth */
155
                        if ($this->maxredirs > $this->_redirectdepth) {
156
                            // only follow redirect if it's on this site, or offsiteok is true
157
                            if (preg_match("|^http://" . preg_quote($this->host) . "|i", $this->_redirectaddr) || $this->offsiteok) {
158
                                /* follow the redirect */
159
                                $this->_redirectdepth++;
160
                                $this->lastredirectaddr = $this->_redirectaddr;
0 ignored issues
show
Documentation Bug introduced by
The property $lastredirectaddr was declared of type string, but $this->_redirectaddr is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
161
                                $this->fetch($this->_redirectaddr);
162
                            }
163
                        }
164
                    }
165
166 View Code Duplication
                    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;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
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 View Code Duplication
                if ($this->_isproxy) {
193
                    // using proxy, send entire URI
194
                    $this->_httpsrequest($URI, $URI, $this->_httpmethod);
195
                } else {
196
                    $path = $URI_PARTS["path"] . ($URI_PARTS["query"] ? "?" . $URI_PARTS["query"] : "");
197
                    // no proxy, send only the path
198
                    $this->_httpsrequest($path, $URI, $this->_httpmethod);
199
                }
200
201 View Code Duplication
                if ($this->_redirectaddr) {
202
                    /* url was redirected, check if we've hit the max depth */
203
                    if ($this->maxredirs > $this->_redirectdepth) {
204
                        // only follow redirect if it's on this site, or offsiteok is true
205
                        if (preg_match("|^http://" . preg_quote($this->host) . "|i", $this->_redirectaddr) || $this->offsiteok) {
206
                            /* follow the redirect */
207
                            $this->_redirectdepth++;
208
                            $this->lastredirectaddr = $this->_redirectaddr;
209
                            $this->fetch($this->_redirectaddr);
210
                        }
211
                    }
212
                }
213
214 View Code Duplication
                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;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
228
            default:
229
                // not a valid protocol
230
                $this->error = 'Invalid protocol "' . $URI_PARTS["scheme"] . '"\n';
231
                return false;
232
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
233
        }
234
        return true;
235
    }
236
237
    /*======================================================================*\
238
        Function:	submit
239
        Purpose:	submit an http form
240
        Input:		$URI	the location to post the data
241
                    $formvars	the formvars to use.
242
                        format: $formvars["var"] = "val";
243
                    $formfiles  an array of files to submit
244
                        format: $formfiles["var"] = "/dir/filename.ext";
245
        Output:		$this->results	the text output from the post
246
    \*======================================================================*/
247
248
    function submit($URI, $formvars = "", $formfiles = "")
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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 View Code Duplication
                    if ($this->_isproxy) {
271
                        // using proxy, send entire URI
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
                        // no proxy, send only the path
276
                        $this->_httprequest($path, $fp, $URI, $this->_submit_method, $this->_submit_type, $postdata);
277
                    }
278
279
                    $this->_disconnect($fp);
280
281 View Code Duplication
                    if ($this->_redirectaddr) {
282
                        /* url was redirected, check if we've hit the max depth */
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
                            // only follow redirect if it's on this site, or offsiteok is true
288
                            if (preg_match("|^http://" . preg_quote($this->host) . "|i", $this->_redirectaddr) || $this->offsiteok) {
289
                                /* follow the redirect */
290
                                $this->_redirectdepth++;
291
                                $this->lastredirectaddr = $this->_redirectaddr;
292
                                if (strpos($this->_redirectaddr, "?") > 0)
293
                                    $this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get
294
                                else
295
                                    $this->submit($this->_redirectaddr, $formvars, $formfiles);
296
                            }
297
                        }
298
                    }
299
300 View Code Duplication
                    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;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
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 View Code Duplication
                if ($this->_isproxy) {
328
                    // using proxy, send entire URI
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
                    // no proxy, send only the path
333
                    $this->_httpsrequest($path, $URI, $this->_submit_method, $this->_submit_type, $postdata);
334
                }
335
336 View Code Duplication
                if ($this->_redirectaddr) {
337
                    /* url was redirected, check if we've hit the max depth */
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
                        // only follow redirect if it's on this site, or offsiteok is true
343
                        if (preg_match("|^http://" . preg_quote($this->host) . "|i", $this->_redirectaddr) || $this->offsiteok) {
344
                            /* follow the redirect */
345
                            $this->_redirectdepth++;
346
                            $this->lastredirectaddr = $this->_redirectaddr;
347
                            if (strpos($this->_redirectaddr, "?") > 0)
348
                                $this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get
349
                            else
350
                                $this->submit($this->_redirectaddr, $formvars, $formfiles);
351
                        }
352
                    }
353
                }
354
355 View Code Duplication
                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;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
369
370
            default:
371
                // not a valid protocol
372
                $this->error = 'Invalid protocol "' . $URI_PARTS["scheme"] . '"\n';
373
                return false;
374
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
375
        }
376
        return true;
377
    }
378
379
    /*======================================================================*\
380
        Function:	fetchlinks
381
        Purpose:	fetch the links from a web page
382
        Input:		$URI	where you are fetching from
383
        Output:		$this->results	an array of the URLs
384
    \*======================================================================*/
385
386
    function fetchlinks($URI)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
393
                    $this->results[$x] = $this->_striplinks($this->results[$x]);
394
            } else
395
                $this->results = $this->_striplinks($this->results);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->_striplinks($this->results) of type array<integer,?> is incompatible with the declared type string of property $results.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
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
        Function:	fetchform
406
        Purpose:	fetch the form elements from a web page
407
        Input:		$URI	where you are fetching from
408
        Output:		$this->results	the resulting html form
409
    \*======================================================================*/
410
411 View Code Duplication
    function fetchform($URI)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
412
    {
413
414
        if ($this->fetch($URI)) {
415
416
            if (is_array($this->results)) {
417
                for ($x = 0; $x < count($this->results); $x++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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
        Function:	fetchtext
430
        Purpose:	fetch the text from a web page, stripping the links
431
        Input:		$URI	where you are fetching from
432
        Output:		$this->results	the text from the web page
433
    \*======================================================================*/
434
435 View Code Duplication
    function fetchtext($URI)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
436
    {
437
        if ($this->fetch($URI)) {
438
            if (is_array($this->results)) {
439
                for ($x = 0; $x < count($this->results); $x++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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
        Function:	submitlinks
450
        Purpose:	grab links from a form submission
451
        Input:		$URI	where you are submitting from
452
        Output:		$this->results	an array of the links from the post
453
    \*======================================================================*/
454
455 View Code Duplication
    function submitlinks($URI, $formvars = "", $formfiles = "")
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->_striplinks($this->results) of type array<integer,?> is incompatible with the declared type string of property $results.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
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
        Function:	submittext
478
        Purpose:	grab text from a form submission
479
        Input:		$URI	where you are submitting from
480
        Output:		$this->results	the text from the web page
481
    \*======================================================================*/
482
483 View Code Duplication
    function submittext($URI, $formvars = "", $formfiles = "")
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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
        Function:	set_submit_multipart
507
        Purpose:	Set the form submission content type to
508
                    multipart/form-data
509
    \*======================================================================*/
510
    function set_submit_multipart()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
511
    {
512
        $this->_submit_type = "multipart/form-data";
513
    }
514
515
516
    /*======================================================================*\
517
        Function:	set_submit_normal
518
        Purpose:	Set the form submission content type to
519
                    application/x-www-form-urlencoded
520
    \*======================================================================*/
521
    function set_submit_normal()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
522
    {
523
        $this->_submit_type = "application/x-www-form-urlencoded";
524
    }
525
526
527
528
529
    /*======================================================================*\
530
        Private functions
531
    \*======================================================================*/
532
533
534
    /*======================================================================*\
535
        Function:	_striplinks
536
        Purpose:	strip the hyperlinks from an html document
537
        Input:		$document	document to strip.
538
        Output:		$match		an array of the links
539
    \*======================================================================*/
540
541
    function _striplinks($document)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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
        // catenate the non-empty matches from the conditional subpattern
551
552 View Code Duplication
        while (list($key, $val) = each($links[2])) {
0 ignored issues
show
Unused Code introduced by
The assignment to $key is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
553
            if (!empty($val))
554
                $match[] = $val;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$match was never initialized. Although not strictly required by PHP, it is generally a good practice to add $match = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
555
        }
556
557 View Code Duplication
        while (list($key, $val) = each($links[3])) {
0 ignored issues
show
Unused Code introduced by
The assignment to $key is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
558
            if (!empty($val))
559
                $match[] = $val;
0 ignored issues
show
Bug introduced by
The variable $match does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
560
        }
561
562
        // return the links
563
        return $match;
564
    }
565
566
    /*======================================================================*\
567
        Function:	_stripform
568
        Purpose:	strip the form elements from an html document
569
        Input:		$document	document to strip.
570
        Output:		$match		an array of the links
571
    \*======================================================================*/
572
573
    function _stripform($document)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
574
    {
575
        preg_match_all("'<\/?(FORM|INPUT|SELECT|TEXTAREA|(OPTION))[^<>]*>(?(2)(.*(?=<\/?(option|select)[^<>]*>[\r\n]*)|(?=[\r\n]*))|(?=[\r\n]*))'Usi", $document, $elements);
576
577
        // catenate the matches
578
        $match = implode("\r\n", $elements[0]);
579
580
        // return the links
581
        return $match;
582
    }
583
584
585
    /*======================================================================*\
586
        Function:	_striptext
587
        Purpose:	strip the text from an html document
588
        Input:		$document	document to strip.
589
        Output:		$text		the resulting text
590
    \*======================================================================*/
591
592
    function _striptext($document)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
593
    {
594
595
        // I didn't use preg eval (//e) since that is only available in PHP 4.0.
596
        // so, list your entities one by one here. I included some of the
597
        // more common ones.
598
599
        $search = array("'<script[^>]*?>.*?</script>'si", // strip out javascript
600
            "'<[\/\!]*?[^<>]*?>'si", // strip out html tags
601
            "'([\r\n])[\s]+'", // strip out white space
602
            "'&(quot|#34|#034|#x22);'i", // replace html entities
603
            "'&(amp|#38|#038|#x26);'i", // added hexadecimal values
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", // europe
615
            "'&a(uml|UML);'", // german
616
            "'&o(uml|UML);'",
617
            "'&u(uml|UML);'",
618
            "'&A(uml|UML);'",
619
            "'&O(uml|UML);'",
620
            "'&U(uml|UML);'",
621
            "'&szlig;'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
        Function:	_expandlinks
655
        Purpose:	expand each link into a fully qualified URL
656
        Input:		$links			the links to qualify
657
                    $URI			the full URI to get the base from
658
        Output:		$expandedLinks	the expanded links
659
    \*======================================================================*/
660
661
    function _expandlinks($links, $URI)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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
        Function:	_httprequest
693
        Purpose:	go get the http data from the server
694
        Input:		$url		the url to fetch
695
                    $fp			the current open file pointer
696
                    $URI		the full URI
697
                    $body		body contents to send if any (POST)
698
        Output:
699
    \*======================================================================*/
700
701
    function _httprequest($url, $fp, $URI, $http_method, $content_type = "", $body = "")
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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
            // make sure PHP was built with --with-zlib
723
            // and we can handle gzipp'ed data
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 View Code Duplication
                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 View Code Duplication
        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 View Code Duplication
        if (!empty($this->user) || !empty($this->pass))
763
            $headers .= "Authorization: Basic " . base64_encode($this->user . ":" . $this->pass) . "\r\n";
764
765
        //add proxy auth headers
766 View Code Duplication
        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
        // set the read timeout if needed
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
        // content was returned gzip encoded?
783
        $is_gzipped = false;
784
785
        while ($currentHeader = fgets($fp, $this->_maxlinelen)) {
786 View Code Duplication
            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
            // if a header begins with Location: or URI:, set the redirect
795 View Code Duplication
            if (preg_match("/^(Location:|URI:)/i", $currentHeader)) {
796
                // get URL portion of the redirect
797
                preg_match("/^(Location:|URI:)[ ]+(.*)/i", chop($currentHeader), $matches);
798
                // look for :// in the Location header to see if hostname is included
799
                if (!preg_match("|\:\/\/|", $matches[2])) {
800
                    // no host in the path, so prepend
801
                    $this->_redirectaddr = $URI_PARTS["scheme"] . "://" . $this->host . ":" . $this->port;
0 ignored issues
show
Documentation Bug introduced by
The property $_redirectaddr was declared of type boolean, but $URI_PARTS['scheme'] . '...ost . ':' . $this->port is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
802
                    // eliminate double slash
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];
0 ignored issues
show
Documentation Bug introduced by
The property $_redirectaddr was declared of type boolean, but $matches[2] is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
809
            }
810
811 View Code Duplication
            if (preg_match("|^HTTP/|", $currentHeader)) {
812
                if (preg_match("|^HTTP/[^\s]*\s(.*?)\s|", $currentHeader, $status)) {
813
                    $this->status = $status[1];
0 ignored issues
show
Documentation Bug introduced by
The property $status was declared of type integer, but $status[1] is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
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
        // gunzip
835
        if ($is_gzipped) {
836
            // per http://www.php.net/manual/en/function.gzencode.php
837
            $results = substr($results, 10);
838
            $results = gzinflate($results);
839
        }
840
841 View Code Duplication
        if ($this->read_timeout > 0 && $this->_check_timeout($fp)) {
842
            $this->status = -100;
843
            return false;
844
        }
845
846
        // check if there is a a redirect meta tag
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
        // have we hit our frame depth and is there frame src to fetch?
853 View Code Duplication
        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++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
856
                $this->_frameurls[] = $this->_expandlinks($match[1][$x], $URI_PARTS["scheme"] . "://" . $this->host);
857
        } // have we already fetched framed content?
858
        elseif (is_array($this->results))
859
            $this->results[] = $results;
860
        // no framed content
861
        else
862
            $this->results = $results;
863
864
        return true;
865
    }
866
867
    /*======================================================================*\
868
        Function:	_httpsrequest
869
        Purpose:	go get the https data from the server using curl
870
        Input:		$url		the url to fetch
871
                    $URI		the full URI
872
                    $body		body contents to send if any (POST)
873
        Output:
874
    \*======================================================================*/
875
876
    function _httpsrequest($url, $URI, $http_method, $content_type = "", $body = "")
0 ignored issues
show
Unused Code introduced by
The parameter $http_method is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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 = "/";
0 ignored issues
show
Unused Code introduced by
$url is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
886
        // GET ... header not needed for curl
887
        //$headers[] = $http_method." ".$url." ".$this->_httpversion;
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 View Code Duplication
                foreach ($this->cookies as $cookieKey => $cookieVal) {
907
                    $cookie_str .= $cookieKey . "=" . urlencode($cookieVal) . "; ";
908
                }
909
                $headers[] = substr($cookie_str, 0, -2);
910
            }
911
        }
912 View Code Duplication
        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 View Code Duplication
        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++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
930
            $safer_header = strtr($headers[$curr_header], "\"", " ");
931
            $cmdline_params .= " -H \"" . $safer_header . "\"";
0 ignored issues
show
Bug introduced by
The variable $cmdline_params does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
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");
0 ignored issues
show
Bug introduced by
The variable $temp_dir does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
941
942
        exec($this->curl_path . " -k -D \"$headerfile\"" . $cmdline_params . " " . escapeshellarg($URI), $results, $return);
943
944
        if ($return) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $return of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
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++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
958
959
            // if a header begins with Location: or URI:, set the redirect
960 View Code Duplication
            if (preg_match("/^(Location: |URI: )/i", $result_headers[$currentHeader])) {
961
                // get URL portion of the redirect
962
                preg_match("/^(Location: |URI:)\s+(.*)/", chop($result_headers[$currentHeader]), $matches);
963
                // look for :// in the Location header to see if hostname is included
964
                if (!preg_match("|\:\/\/|", $matches[2])) {
965
                    // no host in the path, so prepend
966
                    $this->_redirectaddr = $URI_PARTS["scheme"] . "://" . $this->host . ":" . $this->port;
0 ignored issues
show
Documentation Bug introduced by
The property $_redirectaddr was declared of type boolean, but $URI_PARTS['scheme'] . '...ost . ':' . $this->port is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
967
                    // eliminate double slash
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];
0 ignored issues
show
Documentation Bug introduced by
The property $_redirectaddr was declared of type boolean, but $matches[2] is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
974
            }
975
976 View Code Duplication
            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];
0 ignored issues
show
Documentation Bug introduced by
The property $status was declared of type integer, but $match[1] is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
980
                }
981
            }
982
983
            $this->headers[] = $result_headers[$currentHeader];
984
        }
985
986
        // check if there is a a redirect meta tag
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
        // have we hit our frame depth and is there frame src to fetch?
993 View Code Duplication
        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++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
996
                $this->_frameurls[] = $this->_expandlinks($match[1][$x], $URI_PARTS["scheme"] . "://" . $this->host);
997
        } // have we already fetched framed content?
998
        elseif (is_array($this->results))
999
            $this->results[] = $results;
1000
        // no framed content
1001
        else
1002
            $this->results = $results;
1003
1004
        unlink("$headerfile");
1005
1006
        return true;
1007
    }
1008
1009
    /*======================================================================*\
1010
        Function:	setcookies()
1011
        Purpose:	set cookies for a redirection
1012
    \*======================================================================*/
1013
1014
    function setcookies()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1015
    {
1016
        for ($x = 0; $x < count($this->headers); $x++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
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
        Function:	_check_timeout
1025
        Purpose:	checks whether timeout has occurred
1026
        Input:		$fp	file pointer
1027
    \*======================================================================*/
1028
1029
    function _check_timeout($fp)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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
        Function:	_connect
1043
        Purpose:	make a socket connection
1044
        Input:		$fp	file pointer
1045
    \*======================================================================*/
1046
1047
    function _connect(&$fp)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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
            // socket connection succeeded
1070
1071
            return true;
1072
        } else {
1073
            // socket connection failed
1074
            $this->status = $errno;
1075
            switch ($errno) {
1076
                case -3:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1077
                    $this->error = "socket creation failed (-3)";
1078
                case -4:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1079
                    $this->error = "dns lookup failure (-4)";
1080
                case -5:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
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
        Function:	_disconnect
1091
        Purpose:	disconnect a socket connection
1092
        Input:		$fp	file pointer
1093
    \*======================================================================*/
1094
1095
    function _disconnect($fp)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1096
    {
1097
        return (fclose($fp));
1098
    }
1099
1100
1101
    /*======================================================================*\
1102
        Function:	_prepare_post_body
1103
        Purpose:	Prepare post body according to encoding type
1104
        Input:		$formvars  - form variables
1105
                    $formfiles - form upload files
1106
        Output:		post body
1107
    \*======================================================================*/
1108
1109
    function _prepare_post_body($formvars, $formfiles)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $cur_key is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
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)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $cur_key is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
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
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
1174