Completed
Pull Request — master (#329)
by De Cramer
03:46
created

Webaccess::select()   C

Complexity

Conditions 8
Paths 40

Size

Total Lines 46
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 24
nc 40
nop 5
dl 0
loc 46
rs 5.5555
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 120 and the first side effect is on line 63.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
use eXpansion\Framework\Core\Services\Console;
4
5
////////////////////////////////////////////////////////////////
6
//
7
// File:      WEB ACCESS 2.1.3
8
// Date:      13.10.2011
9
// Author:    Gilles Masson
10
// Contributor & fixes: Xymph
11
//
12
// Additional changes for expansion2: Reaby - updated at 27.2.2017
13
//
14
////////////////////////////////////////////////////////////////
15
// This class and functions can be used to make asynchronous xml or http (POST or GET) queries.
16
// this means that you call a function to send the query, and a callback function
17
// will automatically be called when the response has arrived, without having your
18
// program waiting for the response.
19
// You can also use it for synchronous queries (see below).
20
// The class handle (for each url) keepalive and compression (when possible).
21
// It support Cookies, and so can use sessions like php one (anyway the cookie is not stored,
22
// so its maximal life is the life of the program).
23
//
24
//
25
// usage:  $_webaccess = new Webaccess();
26
//         $_webaccess->request($url, array('func_name',xxx), $data, $is_xmlrpc, $keepalive_min_timeout);
27
//    $url: the web script URL.
28
//    $data: string to send in http body (xml, xml_rpc or POST data)
29
//    $is_xmlrpc: true if it's a xml or xml-rpc request, false if it's a standard html GET or POST
30
//    $keepalive_min_timeout: minimal value of server keepalive timeout to send a keepalive request,
31
//                             else make a request with close connection.
32
//    func_name is the callback function name, which will be called this way:
33
34
//       func_name(array('Code'=>code,'Reason'=>reason,'Headers'=>headers,'Message'=>message),xxx), where:
35
//           xxx is the same as given previously in callback description.
36
//           code is the returned http code
37
//             (http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6)
38
//           reason is the returned http reason
39
//             (http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6)
40
//           headers are the http headers of the reply
41
//           message is the returned text body
42
//
43
// IMPORTANT: to have this work, the main part of your program must include a
44
// $webaccess->select() call periodically, which work exactly like stream_select().
45
// This is because the send and receive are asynchronous and will be completed later
46
// in the select() when data are ready to be received and sent.
47
//
48
// This class can be use to make a synchronous query too. For such use null for the callback,
49
// so make the request this way:
50
// $response = $webaccess->request($url, null, $data, $is_xmlrpc, $keepalive_min_timeout);
51
// where $response is an array('Code'=>code,'Reason'=>reason,'Headers'=>headers,'Message'=>message)
52
// like the one passed to the callback function of the asynchronous request.
53
//
54
// If you use only synchronous queries then there is no need to call select() as the function
55
// will return when the reply will be fully returned.
56
//
57
// If the connection itself fail, the array response will include a 'Error' string.
58
// other functions:
59
//   list($host,$port,$path) = getHostPortPath($url);
60
//   gzdecode() workaround
61
62
63
global $_web_access_compress_xmlrpc_request, $_web_access_compress_reply,
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
64
       $_web_access_keepalive, $_web_access_keepalive_timeout,
65
       $_web_access_keepalive_max, $_web_access_retry_timeout,
66
       $_web_access_retry_timeout_max, $_web_access_post_xmlrpc;
67
68
69
// Will compress xmlrpc request ('never','accept','force','force-gzip','force-deflate')
70
// If set to 'accept' the first request will be made without, and the eventual
71
// 'Accept-Encoding' in reply will permit to decide if request compression can
72
// be used (and if gzip or deflate)
73
74
$_web_access_compress_xmlrpc_request = 'accept';
75
76
// will ask server for compressed reply (false, true)
77
// if true then will add a 'Accept-Encoding' header to tell the server to compress
78
// the reply if it support it.
79
80
$_web_access_compress_reply = true;
81
82
83
// keep alive connection ? else close it after the reply.
84
// unless false, first request will be with keepalive, to get server timeout and max values
85
// after timeout will be compared with the request $keepalive_min_timeout value to decide
86
// if keepalive have to be used or not. Note that apache2 timeout is short (about 15s).
87
// The classes will open, re-open or use existing connection as needed.
88
89
$_web_access_keepalive = true;
90
// timeout (s) without request before close, for keep alive
91
92
$_web_access_keepalive_timeout = 600;
93
// max requests before close, for keep alive
94
95
$_web_access_keepalive_max = 2000;
96
97
98
// for asynchronous call, in case of error, timeout before retrying.
99
// it will be x2 for each error (on request or auto retry) until max,
100
// then stop automatic retry, and next request calls will return false.
101
// When stopped, a retry() or synchronous request will force a retry.
102
$_web_access_retry_timeout = 20;
103
$_web_access_retry_timeout_max = 60;
104
105
106
// use text/html with xmlrpc= , instead of of pure text/xml request (false, true)
107
// standard xml-rpc use pure text/xml request, where the xml is simply the body
108
// of the http request (and it's how the xml-rpc reply will be made). As a facility
109
// Dedimania support also to get the xml in a html GET or POST, where xmlrpc= will
110
// contain a urlsafe base64 of the xml. Default to false, so use pure text/xml.
111
$_web_access_post_xmlrpc = false;
112
113
// Note that in each request the text/xml or xmlrpc= will be used only if $is_xmlrpc
114
// is true. If false then the request will be a standard application/x-www-form-urlencoded 
115
// html GET or POST request ; in that case you have to build the url (GET) and/or
116
// body data (POST) yourself.
117
118
// use: list($host,$port,$path) = getHostPortPath($url);
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
119
120
class Webaccess
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
121
{
122
    private $_WebaccessList;
123
    /**
124
     * @var Console
125
     */
126
    private $console;
127
128
    public function __construct(Console $console)
129
    {
130
        $this->_WebaccessList = array();
131
        $this->console = $console;
132
    }
133
134
    public function request(
135
        $url,
136
        $callback,
137
        $datas,
138
        $is_xmlrpc = false,
139
        $keepalive_min_timeout = 300,
140
        $opentimeout = 3,
141
        $waittimeout = 5,
142
        $agent = 'XMLaccess',
143
        $mimeType = "text/html"
144
    ) {
145
        global $_web_access_keepalive, $_web_access_keepalive_timeout, $_web_access_keepalive_max;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
146
        list($host, $port, $path) = getHostPortPath($url);
147
148
        if ($host === false) {
149
            $this->console->writeln('Webaccess request(): Bad url: $ff0'.$url."\n");
150
        } else {
151
            $server = $host.':'.$port;
152
            // create object is needed
153
            if (!isset($this->_WebaccessList[$server]) || $this->_WebaccessList[$server] === null) {
154
                $this->_WebaccessList[$server] = new \WebaccessUrl(
155
                    $this,
156
                    $host,
157
                    $port,
158
                    $_web_access_keepalive,
159
                    $_web_access_keepalive_timeout,
160
                    $_web_access_keepalive_max,
161
                    $agent,
162
                    $mimeType,
163
                    $this->console
164
                );
165
166
            }
167
168
            // increase the default timeout for sync/wait request
169
            if ($callback == null && $waittimeout == 5) {
170
                $waittimeout = 12;
171
            }
172
173
            // call request
174
            if ($this->_WebaccessList[$server] !== null) {
175
                $query = array(
176
                    'Path' => $path,
177
                    'Callback' => $callback,
178
                    'QueryDatas' => $datas,
179
                    'IsXmlrpc' => $is_xmlrpc,
180
                    'KeepaliveMinTimeout' => $keepalive_min_timeout,
181
                    'OpenTimeout' => $opentimeout,
182
                    'WaitTimeout' => $waittimeout,
183
                    'MimeType' => $mimeType,
184
                );
185
186
                return $this->_WebaccessList[$server]->request($query);
187
            }
188
        }
189
190
        return false;
191
    }  // request
192
193
    public function retry($url)
194
    {
195
        list($host, $port, $path) = getHostPortPath($url);
0 ignored issues
show
Unused Code introduced by
The assignment to $path 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...
196
197
        if ($host === false) {
198
            $this->console->writeln('Webaccess retry(): Bad url: $ff0'.$url."\r");
199
        } else {
200
            $server = $host.':'.$port;
201
            if (isset($this->_WebaccessList[$server])) {
202
                $this->_WebaccessList[$server]->retry();
203
            }
204
        }
205
    }  // retry
206
207
    public function select(&$read, &$write, &$except, $tv_sec, $tv_usec = 0)
208
    {
209
        $timeout = (int)($tv_sec * 1000000 + $tv_usec);
210
211
        if ($read == null) {
212
            $read = array();
213
        }
214
        if ($write == null) {
215
            $write = array();
216
        }
217
        if ($except == null) {
218
            $except = array();
219
        }
220
221
        $read = $this->_getWebaccessReadSockets($read);
222
        $write = $this->_getWebaccessWriteSockets($write);
223
        // $except = $this->_getWebaccessReadSockets($except);
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
224
        //print_r($except);
225
226
        if (count($read) + count($write) + count($except) == 0) {
227
            // sleep the asked timeout...
228
            if ($timeout > 1000) {
229
                usleep($timeout);
230
            }
231
232
            return 0;
233
        }
234
235
        $utime = (int)(microtime(true) * 1000000);
236
        $nb = @stream_select($read, $write, $except, $tv_sec, $tv_usec);
237
        if ($nb === false) {
238
            // in case stream_select "forgot" to wait, sleep the remaining asked timeout...
239
            $dtime = (int)(microtime(true) * 1000000) - $utime;
240
            $timeout -= $dtime;
241
            if ($timeout > 1000) {
242
                usleep($timeout);
243
            }
244
245
            return false;
246
        }
247
248
        $this->_manageWebaccessSockets($read, $write, $except);
249
250
        // workaround for stream_select bug with amd64, replace $nb with sum of arrays
251
        return count($read) + count($write) + count($except);
252
    }  // select
253
254
    private function _manageWebaccessSockets(&$receive, &$send, &$except)
0 ignored issues
show
Unused Code introduced by
The parameter $except 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...
255
    {
256
        // send pending datas on all webaccess sockets
257
        if (is_array($send) && count($send) > 0) {
258
            foreach ($send as $key => $socket) {
259
                $i = $this->_findWebaccessSocket($socket);
260
                if ($i !== false) {
261
                    if (isset($this->_WebaccessList[$i]->_spool[0]['State']) &&
262
                        $this->_WebaccessList[$i]->_spool[0]['State'] == 'OPEN') {
263
                        $this->_WebaccessList[$i]->_open();
264
                    } else {
265
                        $this->_WebaccessList[$i]->_send();
266
                    }
267
                    unset($send[$key]);
268
                }
269
            }
270
        }
271
272
        // read datas from all needed webaccess
273
        if (is_array($receive) && count($receive) > 0) {
274
            foreach ($receive as $key => $socket) {
275
                $i = $this->_findWebaccessSocket($socket);
276
                if ($i !== false) {
277
                    $this->_WebaccessList[$i]->_receive();
278
                    unset($receive[$key]);
279
                }
280
            }
281
        }
282
    }  // _manageWebaccessSockets
283
284
    private function _findWebaccessSocket($socket)
285
    {
286
        foreach ($this->_WebaccessList as $key => $wau) {
287
            if ($wau->_socket == $socket) {
288
                return $key;
289
            }
290
        }
291
292
        return false;
293
    }
294
295
    private function _getWebaccessReadSockets($socks)
296
    {
297
        foreach ($this->_WebaccessList as $key => $wau) {
298
            if ($wau->_state == 'OPENED' && $wau->_socket) {
299
                $socks[] = $wau->_socket;
300
            }
301
        }
302
303
        return $socks;
304
    }
305
306
    private function _getWebaccessWriteSockets($socks)
307
    {
308
        foreach ($this->_WebaccessList as $key => $wau) {
309
310
            if (isset($wau->_spool[0]['State']) &&
311
                ($wau->_spool[0]['State'] == 'OPEN' ||
312
                    $wau->_spool[0]['State'] == 'BAD' ||
313
                    $wau->_spool[0]['State'] == 'SEND')
314
            ) {
315
316
                if (($wau->_state == 'CLOSED' || $wau->_state == 'BAD') && !$wau->_socket) {
317
                    $wau->_open();
318
                }
319
320
                if ($wau->_state == 'OPENED' && $wau->_socket) {
321
                    $socks[] = $wau->_socket;
322
                }
323
            }
324
        }
325
326
        return $socks;
327
    }
328
329
    function getAllSpools()
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...
330
    {
331
        $num = 0;
332
        $bad = 0;
333
        foreach ($this->_WebaccessList as $key => $wau) {
334
            if ($wau->_state == 'OPENED' || $wau->_state == 'CLOSED') {
335
                $num += count($wau->_spool);
336
            } elseif ($wau->_state == 'BAD') {
337
                $bad += count($wau->_spool);
338
            }
339
        }
340
341
        return array($num, $bad);
342
    }
343
}
344
345
// useful datas to handle received headers
346
$_wa_header_separator = array('cookie' => ';', 'set-cookie' => ';');
347
$_wa_header_multi = array('set-cookie' => true);
348
349
class WebaccessUrl
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
350
{
351
352
    //-----------------------------
353
    // Fields
354
    //-----------------------------
355
356
    public $wa;
357
358
    public $_host;
359
360
    public $_port;
361
362
    public $_compress_request;
363
364
    public $_socket;
365
366
    public $_state;
367
368
    public $_keepalive;
369
370
    public $_keepalive_timeout;
371
372
    public $_keepalive_max;
373
374
    public $_serv_keepalive_timeout;
375
376
    public $_serv_keepalive_max;
377
378
    public $_spool;
379
380
    public $_wait;
381
382
    public $_response;
383
384
    public $_query_num;
385
386
    public $_request_time;
387
388
    public $_cookies;
389
390
    public $_webaccess_str;
391
392
    public $_bad_time;
393
394
    public $_bad_timeout;
395
396
    public $_read_time;
397
398
    public $_agent;
399
400
    public $_mimeType;
401
402
    public $_query_time;
403
    /**
404
     * @var Console
405
     */
406
    private $console;
407
408
    // $_state values :
409
    //    'OPENED' : socket is opened
410
    //    'CLOSED' : socket is closed (asked, completed, or closed by server)
411
    //    'BAD' :    socket is closed, bad/error or beginning state
412
413
    // $query['State'] values :  (note: $query is added in $_spool, so $this->_spool[0] is the first $query to handle)
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
414
    //    'BAD' :
415
    //    'OPEN' :    should prepare request datas then send them
416
    //    'SEND' :    request datas are prepared, send them
417
    //    'RECEIVE' : request datas are sent, receive reply datas
418
    //    'DONE' :    request completed
419
420
    //-----------------------------
421
    // Methods
422
    //-----------------------------
423
424
    public function __construct(
425
        &$wa,
426
        $host,
427
        $port,
428
        $keepalive = true,
429
        $keepalive_timeout = 600,
430
        $keepalive_max = 300,
431
        $agent = 'XMLaccess',
432
        $mimeType = "text/html",
433
        Console $console
434
    ) {
435
        global $_web_access_compress_xmlrpc_request;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
436
        $this->wa = &$wa;
437
        $this->_host = $host;
438
        $this->_port = $port;
439
        $this->_webaccess_str = 'Webaccess('.$this->_host.':'.$this->_port.'): ';
440
        $this->_agent = $agent;
441
        $this->_mimeType = $mimeType;
442
443
        // request compression setting
444
        if ($_web_access_compress_xmlrpc_request == 'accept') {
445
            $this->_compress_request = 'accept';
446
        } elseif ($_web_access_compress_xmlrpc_request == 'force') {
447
            if (function_exists('gzencode')) {
448
                $this->_compress_request = 'gzip';
449
            } elseif (function_exists('gzdeflate')) {
450
                $this->_compress_request = 'deflate';
451
            } else {
452
                $this->_compress_request = false;
453
            }
454
        } elseif ($_web_access_compress_xmlrpc_request == 'force-gzip' && function_exists('gzencode')) {
455
            $this->_compress_request = 'gzip';
456
        } elseif ($_web_access_compress_xmlrpc_request == 'force-deflate' && function_exists('gzdeflate')) {
457
            $this->_compress_request = 'deflate';
458
        } else {
459
            $this->_compress_request = false;
460
        }
461
462
        $this->_socket = null;
463
        $this->_state = 'CLOSED';
464
        $this->_keepalive = $keepalive;
465
        $this->_keepalive_timeout = $keepalive_timeout;
466
        $this->_keepalive_max = $keepalive_max;
467
        $this->_serv_keepalive_timeout = $keepalive_timeout;
468
        $this->_serv_keepalive_max = $keepalive_max;
469
        $this->_spool = array();
470
        $this->_wait = false;
471
        $this->_response = '';
472
        $this->_query_num = 0;
473
        $this->_query_time = time();
474
        $this->_cookies = array();
475
        $this->_bad_time = time();
476
        $this->_bad_timeout = 0;
477
        $this->_read_time = 0;
478
        $this->console = $console;
479
480
        $this->console->writeln("at request");
481
482
    }
483
484
    // put connection in BAD state
485
    public function _bad($errstr, $isbad = true)
486
    {
487
        global $_web_access_retry_timeout;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
488
        $this->console->writeln($this->_webaccess_str.'$f00'.$errstr);
489
490
        $this->infos();
491
492
        if ($this->_socket) {
493
            @fclose($this->_socket);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
494
        }
495
        $this->_socket = null;
496
497
        if ($isbad) {
498 View Code Duplication
            if (isset($this->_spool[0]['State'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
499
                $this->_spool[0]['State'] = 'BAD';
500
            }
501
            $this->_state = 'BAD';
502
503
            $this->_bad_time = time();
504
            if ($this->_bad_timeout < $_web_access_retry_timeout) {
505
                $this->_bad_timeout = $_web_access_retry_timeout;
506
            } else {
507
                $this->_bad_timeout *= 2;
508
            }
509
        } else {
510 View Code Duplication
            if (isset($this->_spool[0]['State'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
511
                $this->_spool[0]['State'] = 'OPEN';
512
            }
513
            $this->_state = 'CLOSED';
514
        }
515
        $this->_callCallback($this->_webaccess_str.$errstr);
516
    }
517
518
    public function retry()
519
    {
520
        global $_web_access_retry_timeout;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
521
        if ($this->_state == 'BAD') {
522
            $this->_bad_time = time();
523
            $this->_bad_timeout = $_web_access_retry_timeout;
524
        }
525
    }
526
527
    //$query = array('Path'=>$path,'Callback'=>$callback, 'QueryDatas'=>$datas,
0 ignored issues
show
Unused Code Comprehensibility introduced by
79% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
528
    //               'IsXmlrpc'=>$is_xmlrpc, 'KeepaliveMinTimeout'=>$keepalive_min_timeout,
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
529
    //               'OpenTimeout'=>$opentimeout, 'WaitTimeout'=>$waittimeout);
0 ignored issues
show
Unused Code Comprehensibility introduced by
82% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
530
    // will add:     'State','HDatas','Datas','DatasSize',
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
531
    // will add:     'DatasSent','Response','ResponseSize','Headers','Close','Times'
0 ignored issues
show
Unused Code Comprehensibility introduced by
69% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
532
    public function request(&$query)
533
    {
534
        global $_web_access_compress_reply;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
535
        global $_web_access_post_xmlrpc;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
536
        global $_web_access_retry_timeout;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
537
        global $_web_access_retry_timeout_max;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
538
539
        $query['State'] = 'BAD';
540
        $query['HDatas'] = '';
541
        $query['Datas'] = '';
542
        $query['DatasSize'] = 0;
543
        $query['DatasSent'] = 0;
544
        $query['Response'] = '';
545
        $query['ResponseSize'] = 0;
546
        $query['Headers'] = array();
547
        $query['Close'] = false;
548
        $query['Times'] = array(
549
            'open' => array(-1.0, -1.0),
550
            'send' => array(-1.0, -1.0),
551
            'receive' => array(-1.0, -1.0, 0),
552
        );
553
554
555
        // if async, in error, and maximal timeout, then forget the request and return false.
556
        if (($query['Callback'] != null) && ($this->_state == 'BAD')) {
557
            if ($this->_bad_timeout > $_web_access_retry_timeout_max) {
558
                $this->console->writeln($this->_webaccess_str.'$f00Request refused for consecutive errors $555('.$this->_bad_timeout
559
                    ." / ".$_web_access_retry_timeout_max.")");
560
561
                return false;
562
            } else {
563
                // if not max then accept the request
564
                // and try a request (minimum $_web_access_retry_timeout/2 after previous try)
565
                $time = time();
566
                $timeout = ($this->_bad_timeout / 2) - ($time - $this->_bad_time);
567
                if ($timeout < 0) {
568
                    $timeout = 0;
569
                }
570
                $this->_bad_time = $time - $this->_bad_timeout + $timeout;
571
            }
572
        }
573
574
        // build datas to send
575
        if (($query['Callback'] == null) || (is_array($query['Callback']) &&
576
                isset($query['Callback'][0]) &&
577
                is_callable($query['Callback'][0]))
578
        ) {
579
580
            if (is_string($query['QueryDatas']) && strlen($query['QueryDatas']) > 0) {
581
                $msg = "POST ".$query['Path']." HTTP/1.1\r\n";
582
                $msg .= "Host: ".$this->_host."\r\n";
583
                $msg .= "User-Agent: ".$this->_agent."\r\n";
584
                $msg .= "Cache-Control: no-cache\r\n";
585
586 View Code Duplication
                if ($_web_access_compress_reply) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
587
                    // ask compression of response if gzdecode() and/or gzinflate() is available
588
                    if (function_exists('gzdecode') && function_exists('gzinflate')) {
589
                        $msg .= "Accept-Encoding: deflate, gzip\r\n";
590
                    } elseif (function_exists('gzdecode')) {
591
                        $msg .= "Accept-Encoding: gzip\r\n";
592
                    } elseif (function_exists('gzinflate')) {
593
                        $msg .= "Accept-Encoding: deflate\r\n";
594
                    }
595
                }
596
597
                // echo "\nData:\n\n".$query['QueryDatas']."\n";  // for debug purposes, don't remove!
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
598
599
                if ($query['IsXmlrpc'] === true) {
600
                    if ($_web_access_post_xmlrpc) {
601
                        $msg .= "Content-type: application/x-www-form-urlencoded; charset=UTF-8\r\n";
602
603
                        echo "\n=========================== Data =================================\n\n".$query['Datas']."\n";
604
605
                        $query['QueryDatas'] = "xmlrpc=".urlsafe_base64_encode($query['QueryDatas']);
606
                    } else {
607
                        $msg .= "Content-type: text/xml; charset=UTF-8\r\n";
608
                    }
609
610
                    if ($this->_compress_request == 'gzip' && function_exists('gzencode')) {
611
                        $msg .= "Content-Encoding: gzip\r\n";
612
                        $query['QueryDatas'] = gzencode($query['QueryDatas']);
613
                    } elseif ($this->_compress_request == 'deflate' && function_exists('gzdeflate')) {
614
                        $msg .= "Content-Encoding: deflate\r\n";
615
                        $query['QueryDatas'] = gzdeflate($query['QueryDatas']);
616
                    }
617
                } elseif (is_string($query['IsXmlrpc'])) {
618
                    $msg .= "Content-type: ".$query['IsXmlrpc']."\r\n";
619
                    $msg .= "Accept: */*\r\n";
620
                } else {
621
                    $msg .= "Content-type: ".$query['MimeType']."\r\n";
622
                    $msg .= "Accept: */*\r\n";
623
                }
624
625
                $msg .= "Content-length: ".strlen($query['QueryDatas'])."\r\n";
626
627
                $query['HDatas'] = $msg;
628
629
                $query['State'] = 'OPEN';
630
                $query['Retries'] = 0;
631
632
                // print_r($msg); for debugging purposes - don't remove
633
634
                // add the query in spool
635
                $this->_spool[] = &$query;
636
637 View Code Duplication
                if ($query['Callback'] == null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
638
                    $this->_wait = true;
639
                    $this->_open($query['OpenTimeout'], $query['WaitTimeout']); // wait more in not callback mode
640
                    $this->_spool = array();
641
                    $this->_wait = false;
642
643
                    return $query['Response'];
644
                } else {
645
                    $this->_open();
646
                }
647
            } else {
648
                $msg = "GET ".$query['Path']." HTTP/1.1\r\n";
649
                $msg .= "Host: ".$this->_host."\r\n";
650
                $msg .= "User-Agent: ".$this->_agent."\r\n";
651
                $msg .= "Cache-Control: no-cache\r\n";
652 View Code Duplication
                if ($_web_access_compress_reply) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
653
                    // ask compression of response if gzdecode() and/or gzinflate() is available
654
                    if (function_exists('gzdecode') && function_exists('gzinflate')) {
655
                        $msg .= "Accept-Encoding: deflate, gzip\r\n";
656
                    } elseif (function_exists('gzdecode')) {
657
                        $msg .= "Accept-Encoding: gzip\r\n";
658
                    } elseif (function_exists('gzinflate')) {
659
                        $msg .= "Accept-Encoding: deflate\r\n";
660
                    }
661
                }
662
                $msg .= "Content-type: ".$query['MimeType']."; charset=UTF-8\r\n";
663
                $msg .= "Content-length: ".strlen($query['QueryDatas'])."\r\n";
664
                $query['HDatas'] = $msg;
665
666
                $query['State'] = 'OPEN';
667
                $query['Retries'] = 0;
668
669
                // add the query in spool
670
                $this->_spool[] = &$query;
671
672 View Code Duplication
                if ($query['Callback'] == null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
673
                    $this->_wait = true;
674
                    $this->_open($query['OpenTimeout'], $query['WaitTimeout']); // wait more in not callback mode
675
                    $this->_spool = array();
676
                    $this->_wait = false;
677
678
                    return $query['Response'];
679
                } else {
680
                    $this->_open();
681
                }
682
            }
683
684
        } else {
685
686
            $this->console->writeln($this->_webaccess_str.'Bad callback function:$fff '.$query['Callback']);
687
688
            return false;
689
        }
690
691
        return true;
692
    }
693
694
    // open the socket (close it before if needed)
695
    private function _open_socket($opentimeout = 0.0)
696
    {
697
        // if socket not opened, then open it (2 tries)
698
        if (!$this->_socket || $this->_state != 'OPENED') {
699
            $time = microtime(true);
700
            $this->_spool[0]['Times']['open'][0] = $time;
701
702
            $errno = '';
703
            $errstr = '';
704
            $this->_socket = @fsockopen($this->_host, $this->_port, $errno, $errstr, 1.8); // first try
705
            if (!$this->_socket) {
706
707
                if ($opentimeout >= 1.0) {
708
                    $this->_socket = @fsockopen($this->_host, $this->_port, $errno, $errstr, $opentimeout);
709
                }
710
                if (!$this->_socket) {
711
                    $this->_bad('Error('.$errno.')'.$errstr.', connection failed!');
712
713
                    return;
714
                }
715
            }
716
            $this->_state = 'OPENED';
717
            // new socket connection : reset all pending request original values
718
            for ($i = 0; $i < count($this->_spool); $i++) {
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...
719
                $this->_spool[$i]['State'] = 'OPEN';
720
                $this->_spool[$i]['DatasSent'] = 0;
721
                $this->_spool[$i]['Response'] = '';
722
                $this->_spool[$i]['Headers'] = array();
723
            }
724
            $this->_response = '';
725
            $this->_query_num = 0;
726
            $this->_query_time = time();
727
            $time = microtime(true);
728
            $this->_spool[0]['Times']['open'][1] = $time - $this->_spool[0]['Times']['open'][0];
729
        }
730
    }
731
732
    // open the connection (if not already opened) and send
733
    public function _open($opentimeout = 0.0, $waittimeout = 5.0)
734
    {
735
        global $_web_access_retry_timeout_max;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
736
737
        if (!isset($this->_spool[0]['State'])) {
738
            return false;
739
        }
740
        $time = time();
741
742
        // if async, in error, then return false until timeout or if > max)
743
        if (!$this->_wait && $this->_state == 'BAD' &&
744
            (($this->_bad_timeout > $_web_access_retry_timeout_max) ||
745
                (($time - $this->_bad_time) < $this->_bad_timeout))) {
746
            $this->console->writeln($this->_webaccess_str.'wait to retry ('.($time - $this->_bad_time).' / '.$this->_bad_timeout.')');
747
748
            return false;
749
        }
750
751
        // if the socket is probably in timeout, close it
752
        if ($this->_socket && $this->_state == 'OPENED' &&
753
            ($this->_serv_keepalive_timeout <= ($time - $this->_query_time))) {
754
755
            $this->console->writeln($this->_webaccess_str.'timeout, closed it!');
756
            $this->_state = 'CLOSED';
757
            @fclose($this->_socket);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
758
            $this->_socket = null;
759
        }
760
761
        // if socket is not opened, open it
762
        if (!$this->_socket || $this->_state != 'OPENED') {
763
            $this->_open_socket($opentimeout);
764
        }
765
766
        // if socket is open, send data if possible
767
        if ($this->_socket) {
768
            $this->_read_time = microtime(true);
769
770
            // if wait (synchronous query) then go on all pending write/read until the last
771
            if ($this->_wait) {
772
                @stream_set_timeout($this->_socket, 0, 10000);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
773
774
                while (isset($this->_spool[0]['State']) &&
775
                    ($this->_spool[0]['State'] == 'OPEN' ||
776
                        $this->_spool[0]['State'] == 'SEND' ||
777
                        $this->_spool[0]['State'] == 'RECEIVE')) {
778
                    echo 'State='.$this->_spool[0]['State']." (".count($this->_spool).")\n";
779
                    if (!$this->_socket || $this->_state != 'OPENED') {
780
                        $this->_open_socket($opentimeout);
781
                    }
782
783
                    if ($this->_spool[0]['State'] == 'OPEN') {
784
                        $time = microtime(true);
785
                        $this->_spool[0]['Times']['send'][0] = $time;
786
                        $this->_send($waittimeout);
787
                    } elseif ($this->_spool[0]['State'] == 'SEND') {
788
                        $this->_send($waittimeout);
789
                    } elseif ($this->_spool[0]['State'] == 'RECEIVE') {
790
                        $this->_receive($waittimeout * 4);
791
                    }
792
793
                    // if timeout then error
794 View Code Duplication
                    if (($difftime = round(microtime(true) - $this->_read_time)) > $waittimeout) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
795
                        $this->_bad("Request timeout, in _open ({$difftime} > {$waittimeout}s) state=".$this->_spool[0]['State']
796
                        );
797
798
                        return false;
799
                    }
800
                }
801
                if ($this->_socket) {
802
                    @stream_set_timeout($this->_socket, 0, 2000);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
803
                }
804
            } // else just do a send on the current
805
            elseif (isset($this->_spool[0]['State']) && $this->_spool[0]['State'] == 'OPEN') {
806
                @stream_set_timeout($this->_socket, 0, 2000);  // timeout 2 ms
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
807
                $this->_send($waittimeout);
808
            }
809
        }
810
    }  // _open
811
812
    public function _send($waittimeout = 20)
813
    {
814
        if (!isset($this->_spool[0]['State'])) {
815
            return;
816
        }
817
818
        $errno = '';
819
        $errstr = '';
820
821
        // if OPEN then become SEND
822
        if ($this->_spool[0]['State'] == 'OPEN') {
823
824
            $this->_spool[0]['State'] = 'SEND';
825
            $time = microtime(true);
826
            $this->_spool[0]['Times']['send'][0] = $time;
827
            $this->_spool[0]['Response'] = '';
828
            $this->_spool[0]['Headers'] = array();
829
830
            // finish to prepare header and data to send
831
            $msg = $this->_spool[0]['HDatas'];
832
            if (!$this->_keepalive || ($this->_spool[0]['KeepaliveMinTimeout'] < 0) ||
833
                ($this->_serv_keepalive_timeout < $this->_spool[0]['KeepaliveMinTimeout']) ||
834
                ($this->_serv_keepalive_max <= ($this->_query_num + 2)) ||
835
                ($this->_serv_keepalive_timeout <= (time() - $this->_query_time + 2))
836
            ) {
837
                $msg .= "Connection: close\r\n";
838
                $this->_spool[0]['Close'] = true;
839
            } else {
840
                $msg .= "Keep-Alive: timeout=".$this->_keepalive_timeout.', max='.$this->_keepalive_max
841
                    ."\r\nConnection: Keep-Alive\r\n";
842
            }
843
844
            // add cookie header
845
            if (count($this->_cookies) > 0) {
846
                $cookie_msg = '';
847
                $sep = '';
848
                foreach ($this->_cookies as $name => $cookie) {
849
                    if (!isset($cookie['path'])
850
                        || strncmp($this->_spool[0]['Path'], $cookie['path'], strlen($cookie['path'])) == 0
851
                    ) {
852
                        $cookie_msg .= $sep.$name.'='.$cookie['Value'];
853
                        $sep = '; ';
854
                    }
855
                }
856
                if ($cookie_msg != '') {
857
                    $msg .= "Cookie: $cookie_msg\r\n";
858
                }
859
            }
860
861
            $msg .= "\r\n";
862
            $msg .= $this->_spool[0]['QueryDatas'];
863
            $this->_spool[0]['Datas'] = $msg;
864
            $this->_spool[0]['DatasSize'] = strlen($msg);
865
            $this->_spool[0]['DatasSent'] = 0;
866
            //print_r($msg);  // for debug purposes, don't remove
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
867
        }
868
869
        // if not SEND then stop
870
        if ($this->_spool[0]['State'] != 'SEND') {
871
            return;
872
        }
873
874
        do {
875
            $sent = @stream_socket_sendto(
876
                $this->_socket,
877
                substr(
878
                    $this->_spool[0]['Datas'],
879
                    $this->_spool[0]['DatasSent'],
880
                    ($this->_spool[0]['DatasSize'] - $this->_spool[0]['DatasSent'])
881
                )
882
            );
883
884
            if ($sent == false) {
885
886
                $time = microtime(true);
887
                $this->_spool[0]['Times']['send'][1] = $time - $this->_spool[0]['Times']['send'][0];
888
                //var_dump($this->_spool[0]['Datas']);  // for debug purposes, don't remove
0 ignored issues
show
Unused Code Comprehensibility introduced by
79% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
889
                $this->_bad(
890
                    'Error('.$errno.') '.$errstr.', could not send data! ('
891
                    .$sent.' / '.($this->_spool[0]['DatasSize'] - $this->_spool[0]['DatasSent']).', '
892
                    .$this->_spool[0]['DatasSent'].' / '.$this->_spool[0]['DatasSize'].')');
893
                if ($this->_wait) {
894
                    return;
895
                }
896
                break;
897
            } else {
898
                $this->_spool[0]['DatasSent'] += $sent;
899
                if ($this->_spool[0]['DatasSent'] >= $this->_spool[0]['DatasSize']) {
900
                    // All is sent, prepare to receive the reply
901
                    $this->_query_num++;
902
                    $this->_query_time = time();
903
904
                    $time = microtime(true);
905
                    $this->_spool[0]['Times']['send'][1] = $time - $this->_spool[0]['Times']['send'][0];
906
907
                    $this->_spool[0]['State'] = 'RECEIVE';
908
                    $this->_spool[0]['Times']['receive'][0] = $time;
909 View Code Duplication
                } elseif (($difftime = round(microtime(true) - $this->_read_time)) > $waittimeout) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
910
                    // if timeout then error
911
                    $this->_bad(
912
                        "Request timeout, in _send ({$difftime} > {$waittimeout}s) state=".$this->_spool[0]['State']
913
                    );
914
                    break;
915
                }
916
            }
917
918
            // if not async-callback then continue until all is sent
919
        } while ($this->_wait && isset($this->_spool[0]['State']) && ($this->_spool[0]['State'] == 'SEND'));
920
    } // _send
921
922
    public function _receive($waittimeout = 40)
923
    {
924
        global $_Webaccess_last_response;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
925
926
        if (!$this->_socket || $this->_state != 'OPENED') {
927
            return;
928
        }
929
930
        $errno = '';
931
        $errstr = '';
932
        $time0 = microtime(true);
933
        $timeout = ($this->_wait) ? $waittimeout : 0;
934
        do {
935
            $r = array($this->_socket);
936
            $w = null;
937
            $e = null;
938
            $nb = @stream_select($r, $w, $e, $timeout);
939
            if ($nb === 0) {
940
                $nb = count($r);
941
            }
942
943
            while (!@feof($this->_socket) && $nb !== false && $nb > 0) {
944
                $timeout = 0;
945
946
                if (count($r) > 0) {
947
                    $res = @stream_socket_recvfrom($this->_socket, 8192);
948
949
                    if ($res == '') { // should not happen habitually, but...
950
                        break;
951
                    } elseif ($res !== false) {
952
                        $this->_response .= $res;
953
                    } else {
954 View Code Duplication
                        if (isset($this->_spool[0])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
955
                            $time = microtime(true);
956
                            $this->_spool[0]['Times']['receive'][1] = $time - $this->_spool[0]['Times']['receive'][0];
957
                        }
958
                        $this->_bad('Error('.$errno.') '.$errstr.', could not read all data!');
959
960
                        return;
961
                    }
962
                }
963
964
                // if timeout then error
965
                if (($difftime = round(microtime(true) - $this->_read_time)) > $waittimeout) {
966
                    $this->_bad("Request timeout, in _receive ({$difftime} > {$waittimeout}s)");
967
                    break;
968
                }
969
970
                $r = array($this->_socket);
971
                $w = null;
972
                $e = null;
973
                $nb = @stream_select($r, $w, $e, $timeout);
974
                if ($nb === 0) {
975
                    $nb = count($r);
976
                }
977
            }
978
979 View Code Duplication
            if (isset($this->_spool[0]['Times']['receive'][2])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
980
                $time = microtime(true);
981
                $this->_spool[0]['Times']['receive'][2] += ($time - $time0);
982
            }
983
984
            // get headers and full message
985
            $state = $this->_handleHeaders();
986
        } while ($this->_wait && $state === false && $this->_socket && !@feof($this->_socket));
987
988
        if (!isset($this->_spool[0]['State']) || $this->_spool[0]['State'] != 'RECEIVE') {
989
            // in case of (probably keep-alive) connection closed by server
990
            if ($this->_socket && @feof($this->_socket)) {
991
                $this->_state = 'CLOSED';
992
                @fclose($this->_socket);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
993
                $this->_socket = null;
994
            }
995
996
            return;
997
        }
998
999
1000
        // terminated but incomplete! more than probably closed by server...
1001
        if ($state === false && $this->_socket && @feof($this->_socket)) {
1002
            $this->_state = 'CLOSED';
1003
            if (isset($this->_spool[0])) {
1004
                $time = microtime(true);
1005
                $this->_spool[0]['State'] = 'OPEN';
1006
                $this->_spool[0]['Times']['receive'][1] = $time - $this->_spool[0]['Times']['receive'][0];
1007
            }
1008
            // if not 0 sized then show error message
1009
            if (strlen($this->_response) > 0) {
1010
                $this->_bad(
1011
                    'Error: closed with incomplete read: re-open socket and re-send! ('.strlen($this->_response).')'
1012
                );
1013
            } else {
1014
                $this->_bad(
1015
                    'Closed by server when reading: re-open socket and re-send! ('.strlen($this->_response).')',
1016
                    false
1017
                );
1018
            }
1019
1020
            $this->_spool[0]['Retries']++;
1021
1022
            if ($this->_spool[0]['Retries'] > 2) {
1023
                // 3 tries failed, remove entry from spool
1024
                $this->console->writeln($this->_webaccess_str.'$f00 Failed '.$this->_spool[0]['Retries'].' times: skipping current request.');
1025
                array_shift($this->_spool);
1026
            }
1027
1028
            return;
1029
        }
1030
1031
1032
        // reply is complete :)
1033
        if ($state === true) {
1034
            $this->_bad_timeout = 0; // reset error timeout
1035
            $time = microtime(true);  // @todo see if this is needed ?
1036
            $this->_spool[0]['Times']['receive'][1] = $time - $this->_spool[0]['Times']['receive'][0];
1037
            $this->_spool[0]['State'] = 'DONE';
1038
1039
            // store http/xml response in global $_Webaccess_last_response - for debugging use
1040
            $_Webaccess_last_response = $this->_spool[0]['Response'];
1041
            // call callback func
1042
            $this->_callCallback();
1043
1044
1045
            $this->_query_time = time();
1046
1047
            if (!$this->_keepalive || $this->_spool[0]['Close']) {
1048
                $this->console->writeln($this->_webaccess_str.'closed connection (asked in headers).');
1049
                $this->_state = 'CLOSED';
1050
                @fclose($this->_socket);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1051
                $this->_socket = null;
1052
            }
1053
1054
            $this->infos();
1055
1056
            // request completed, remove it from spool!
1057
            array_shift($this->_spool);
1058
        }
1059
    }  // _receive
1060
1061
    private function _callCallback($error = null)
1062
    {
1063
        if ($error !== null) {
1064
            $this->_spool[0]['Response']['Error'] = $error;
1065
        }
1066
        // call callback func
1067
        if (isset($this->_spool[0]['Callback'])) {
1068
            $callbackinfo = $this->_spool[0]['Callback'];
1069
            if (isset($callbackinfo[0]) && is_callable($callbackinfo[0])) {
1070
                $callback_func = $callbackinfo[0];
1071
                $callbackinfo[0] = $this->_spool[0]['Response'];
1072
                call_user_func_array($callback_func, $callbackinfo);
1073
            }
1074
        }
1075
    }
1076
1077
    private function _handleHeaders()
1078
    {
1079
        global $_wa_header_separator, $_wa_header_multi;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1080
1081
        if (!isset($this->_spool[0]['State'])) {
1082
            return false;
1083
        }
1084
1085
        // not enough data, continue read
1086
        if (strlen($this->_response) < 8) {
1087
            return false;
1088
        }
1089
        if (strncmp($this->_response, 'HTTP/', 5) != 0) { // not HTTP!
1090
            $this->_bad(
1091
                "Error, not HTTP response ! **********\n".substr($this->_response, 0, 300)."\n***************\n"
1092
            );
1093
1094
            return null;
1095
        }
1096
1097
        // separate headers and data
1098
        $datas = explode("\r\n\r\n", $this->_response, 2);
1099
        if (count($datas) < 2) {
1100
            $datas = explode("\n\n", $this->_response, 2);
1101
            if (count($datas) < 2) {
1102
                $datas = explode("\r\r", $this->_response, 2);
1103
                if (count($datas) < 2) {
1104
                    return false; // not complete headers, continue read
1105
                }
1106
            }
1107
        }
1108
1109
        // get headers if not done on previous read
1110
        if (!isset($this->_spool[0]['Headers']['Command'][0])) {
1111
            // separate headers
1112
1113
            $headers = array();
1114
            $heads = explode("\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $datas[0])));
1115
            if (count($heads) < 2) {
1116
                $this->_bad("Error, uncomplete headers ! **********\n".$datas[0]."\n***************\n");
1117
1118
                return null;
1119
            }
1120
1121
            $headers['Command'] = explode(' ', $heads[0], 3);
1122
1123 View Code Duplication
            for ($i = 1; $i < count($heads); $i++) {
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...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1124
                $header = explode(':', $heads[$i], 2);
1125
                if (count($header) > 1) {
1126
                    $headername = strtolower(trim($header[0]));
1127
                    if (isset($_wa_header_separator[$headername])) {
1128
                        $sep = $_wa_header_separator[$headername];
1129
                    } else {
1130
                        $sep = ',';
1131
                    }
1132
                    if (isset($_wa_header_multi[$headername]) && $_wa_header_multi[$headername]) {
1133
                        if (!isset($headers[$headername])) {
1134
                            $headers[$headername] = array();
1135
                        }
1136
                        $headers[$headername][] = explode($sep, trim($header[1]));
1137
                    } else {
1138
                        $headers[$headername] = explode($sep, trim($header[1]));
1139
                    }
1140
                }
1141
            }
1142
1143
            if (isset($headers['content-length'][0])) {
1144
                $headers['content-length'][0] += 0; //convert to int
1145
            }
1146
1147
            $this->_spool[0]['Headers'] = $headers;
1148
1149
            // add header specific info in case of Dedimania reply
1150
            if (isset($headers['server'][0])) {
1151
                $this->_webaccess_str = 'Webaccess('.$this->_host.':'.$this->_port.'/'
1152
                    .$headers['server'][0].'): ';
1153
            }
1154
        } else {
1155
            $headers = &$this->_spool[0]['Headers'];
1156
          //  echo "Previous Headers! (".strlen($datas[0]).")\n"; // for debugging purposes, don't remove
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1157
        }
1158
1159
1160
        // get real message
1161
        $datasize = strlen($datas[1]);
1162
        if (isset($headers['content-length'][0]) && $headers['content-length'][0] >= 0) {
1163
            //echo 'mess_size0=' . strlen($datas[1]) . "\n"; // for debugging purposes, don't remove
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1164
1165
            // incomplete message
1166
            if ($headers['content-length'][0] > $datasize) {
1167
                return false;
1168
            } elseif ($headers['content-length'][0] < $datasize) {
1169
                $message = substr($datas[1], 0, $headers['content-length'][0]);
1170
                // remaining buffer for next reply
1171
                $this->_response = substr($datas[1], $headers['content-length'][0]);
1172
            } else {
1173
                $message = $datas[1];
1174
                $this->_response = '';
1175
            }
1176
            $this->_spool[0]['ResponseSize'] = strlen($datas[0]) + 4 + $headers['content-length'][0];
1177
        } // get real message when reply is chunked
1178
        elseif (isset($headers['transfer-encoding'][0])
1179
            && $headers['transfer-encoding'][0] == 'chunked') {
1180
1181
            // get chunk size and make message with chunks data
1182
            $size = -1;
1183
            $chunkPos = 0;
1184
            $message = '';
1185
            if (($datapos = strpos($datas[1], "\r\n", $chunkPos)) !== false) {
1186
1187
                $chunk = explode(';', substr($datas[1], $chunkPos, $datapos - $chunkPos));
1188
                $size = hexdec($chunk[0]);
1189
                while ($size > 0) {
1190
                    // incomplete message
1191
                    if ($datapos + 2 + $size > $datasize) {
1192
                        return false;
1193
                    }
1194
                    $message .= substr($datas[1], $datapos + 2, $size);
1195
                    $chunkPos = $datapos + 2 + $size + 2;
1196
                    if (($datapos = strpos($datas[1], "\r\n", $chunkPos)) !== false) {
1197
                        $chunk = explode(';', substr($datas[1], $chunkPos, $datapos - $chunkPos));
1198
                        $size = hexdec($chunk[0]);
1199
                    } else {
1200
                        $size = -1;
1201
                    }
1202
                }
1203
            }
1204
            // error bad size or incomplete message
1205
            if ($size < 0) {
1206
                return false;
1207
            }
1208
1209
            // incomplete message : end is missing
1210
            if (strpos($datas[1], "\r\n\r\n", $chunkPos) === false) {
1211
                return false;
1212
            }
1213
1214
            // store complete message size
1215
            $msize = strlen($message);
1216
            // add message size after 'chunked' for information
1217
            $headers['transfer-encoding'][1] = 'total_size='.$msize;
1218
            $this->_spool[0]['ResponseSize'] = strlen($datas[0]) + 4 + $msize;
1219
1220
            // after the message itself...
1221
            $message_end = explode("\r\n\r\n", substr($datas[1], $chunkPos), 2);
1222
1223
            // add end headers if any
1224
            $heads = explode("\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $message_end[0])));
1225 View Code Duplication
            for ($i = 1; $i < count($heads); $i++) {
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...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1226
                $header = explode(':', $heads[$i], 2);
1227
                if (count($header) > 1) {
1228
                    $headername = strtolower(trim($header[0]));
1229
                    if (isset($_wa_header_separator[$headername])) {
1230
                        $sep = $_wa_header_separator[$headername];
1231
                    } else {
1232
                        $sep = ',';
1233
                    }
1234
                    if (isset($_wa_header_multi[$headername]) && $_wa_header_multi[$headername]) {
1235
                        if (!isset($headers[$headername])) {
1236
                            $headers[$headername] = array();
1237
                        }
1238
                        $headers[$headername][] = explode($sep, trim($header[1]));
1239
                    } else {
1240
                        $headers[$headername] = explode($sep, trim($header[1]));
1241
                    }
1242
                }
1243
            }
1244
            $this->_spool[0]['Headers'] = $headers;
1245
1246
            // remaining buffer for next reply
1247
            if (isset($message_end[1]) && strlen($message_end[1]) > 0) {
1248
                $this->_response = $message_end[1];
1249
            } else {
1250
                $this->_response = '';
1251
            }
1252
        } else {  // no content-length and not chunked !
1253
            $this->_bad(
1254
                "Error, bad http, no content-length and not chunked ! **********\n".$datas[0]."\n***************\n"
1255
            );
1256
1257
            return null;
1258
        }
1259
1260
        echo 'mess_size1='.strlen($message)."\n";
1261
1262
        // if Content-Encoding: gzip  or  Content-Encoding: deflate
1263
        if (isset($headers['content-encoding'][0])) {
1264
            if ($headers['content-encoding'][0] == 'gzip') {
1265
                $message = @gzdecode($message);
1266
            } elseif ($headers['content-encoding'][0] == 'deflate') {
1267
                $message = @gzinflate($message);
1268
            }
1269
        }
1270
1271
        // if Accept-Encoding: gzip or deflate
1272
        if ($this->_compress_request == 'accept' && isset($headers['accept-encoding'][0])) {
1273
            foreach ($headers['accept-encoding'] as $comp) {
1274
                $comp = trim($comp);
1275
                if ($comp == 'gzip' && function_exists('gzencode')) {
1276
                    $this->_compress_request = 'gzip';
1277
                    break;
1278
                } elseif ($comp == 'deflate' && function_exists('gzdeflate')) {
1279
                    $this->_compress_request = 'deflate';
1280
                    break;
1281
                }
1282
            }
1283
            if ($this->_compress_request == 'accept') {
1284
                $this->_compress_request = false;
1285
            }
1286
            $this->console->writeln($this->_webaccess_str.'send: '.($this->_compress_request === false ? 'no compression' : $this->_compress_request)
1287
                .', receive: '.(isset($headers['content-encoding'][0]) ? $headers['content-encoding'][0] : 'no compression'));
1288
1289
        }
1290
1291
        // get cookies values
1292
        if (isset($headers['set-cookie'])) {
1293
            foreach ($headers['set-cookie'] as $cookie) {
1294
                $cook = explode('=', $cookie[0], 2);
1295
                if (count($cook) > 1) {
1296
                    // set main cookie value
1297
                    $cookname = trim($cook[0]);
1298
                    if (!isset($this->_cookies[$cookname])) {
1299
                        $this->_cookies[$cookname] = array();
1300
                    }
1301
                    $this->_cookies[$cookname]['Value'] = trim($cook[1]);
1302
1303
                    // set cookie options
1304
                    for ($i = 1; $i < count($cookie); $i++) {
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...
1305
                        $cook = explode('=', $cookie[$i], 2);
1306
                        $cookarg = strtolower(trim($cook[0]));
1307
                        if (isset($cook[1])) {
1308
                            $this->_cookies[$cookname][$cookarg] = trim($cook[1]);
1309
                        }
1310
                    }
1311
                }
1312
            }
1313
            //debugPrint('SET-COOKIES: ', $headers['set-cookie']);
0 ignored issues
show
Unused Code Comprehensibility introduced by
82% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1314
            //debugPrint('STORED COOKIES: ', $this->_cookies);
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1315
        }
1316
1317
        // if the server reply ask to close, then close
1318
        if (!isset($headers['connection'][0]) || $headers['connection'][0] == 'close') {
1319
            $this->console->writeln($this->_webaccess_str.'server ask to close connection');
1320
            $this->_spool[0]['Close'] = true;
1321
        }
1322
1323
        // verify server keep-alive value and use them if lower
1324
        if (isset($headers['keep-alive'])) {
1325
            $kasize = count($headers['keep-alive']);
1326
            for ($i = 0; $i < $kasize; $i++) {
1327
                $keep = explode('=', $headers['keep-alive'][$i], 2);
1328
                if (count($keep) > 1) {
1329
                    $headers['keep-alive'][trim(strtolower($keep[0]))] = intval(trim($keep[1]));
1330
                }
1331
            }
1332
            if (isset($headers['keep-alive']['timeout'])) {
1333
                $this->_serv_keepalive_timeout = $headers['keep-alive']['timeout'];
1334
            }
1335
            if (isset($headers['keep-alive']['max'])) {
1336
                $this->_serv_keepalive_max = $headers['keep-alive']['max'];
1337
            }
1338
        }
1339
1340
        // store complete reply message for the request
1341
        $this->_spool[0]['Response'] = array(
1342
            'Code' => intval($headers['Command'][1]),
1343
            'Reason' => $headers['Command'][2],
1344
            'Headers' => $headers,
1345
            'Message' => $message,
1346
        );
1347
1348
        return true;
1349
    }
1350
1351
    public function infos()
1352
    {
1353
        try {
1354
            $size = (isset($this->_spool[0]['Response']['Message'])) ? strlen($this->_spool[0]['Response']['Message']) : 0;
1355
            $msg = $this->_webaccess_str
1356
                .sprintf(
1357
                    "[%s,%s]: %0.3f / %0.3f / %0.3f (%0.3f) / %d [%d,%d,%d]",
1358
                    $this->_state,
1359
                    $this->_spool[0]['State'],
1360
                    $this->_spool[0]['Times']['open'][1],
1361
                    $this->_spool[0]['Times']['send'][1],
1362
                    $this->_spool[0]['Times']['receive'][1],
1363
                    $this->_spool[0]['Times']['receive'][2],
1364
                    $this->_query_num,
1365
                    $this->_spool[0]['DatasSize'],
1366
                    $size,
1367
                    $this->_spool[0]['ResponseSize']
1368
                );
1369
            $this->console->writeln($msg);
1370
        } catch (Exception $e) {
1371
            echo $e->getMessage();
1372
1373
        }
1374
    }
1375
}
1376
1377
1378
/* Additional functions */
1379
1380
/**
1381
 * @param $url
1382
 * @return array
1383
 */
1384
function getHostPortPath($url)
1385
{
1386
    $http_pos = strpos($url, 'http://');
1387
    if ($http_pos !== false) {
1388
        $script = explode('/', substr($url, $http_pos + 7), 2);
1389
        if (isset($script[1])) {
1390
            $path = '/'.$script[1];
1391
        } else {
1392
            $path = '/';
1393
        }
1394
        $serv = explode(':', $script[0], 2);
1395
        $host = $serv[0];
1396
        if (isset($serv[1])) {
1397
            $port = 0 + $serv[1];
1398
        } else {
1399
            $port = 80;
1400
        }
1401
        if (strlen($host) > 2) {
1402
            return array($host, $port, $path);
1403
        }
1404
    }
1405
1406
    return array(false, false, false);
1407
}
1408
1409
function urlsafe_base64_encode($input)
1410
{
1411
    return strtr(\base64_encode($input), '+/=', '-_,');
1412
}
1413
1414
1415
// gzdecode() workaround
1416
if (!function_exists('gzdecode') && function_exists('gzinflate')) {
1417
    function gzdecode($data)
1418
    {
1419
        $len = strlen($data);
1420
        if ($len < 18 || strcmp(substr($data, 0, 2), "\x1f\x8b")) {
1421
            return null; // Not GZIP format (See RFC 1952)
1422
        }
1423
        $method = ord(substr($data, 2, 1)); // Compression method
1424
        $flags = ord(substr($data, 3, 1)); // Flags
1425
        if ($flags & 31 != $flags) {
1426
            // Reserved bits are set -- NOT ALLOWED by RFC 1952
1427
            return null;
1428
        }
1429
        // NOTE: $mtime may be negative (PHP integer limitations)
1430
        $mtime = unpack("V", substr($data, 4, 4));
1431
        $mtime = $mtime[1];
0 ignored issues
show
Unused Code introduced by
$mtime 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...
1432
        $xfl = substr($data, 8, 1);
0 ignored issues
show
Unused Code introduced by
$xfl 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...
1433
        $os = substr($data, 8, 1);
0 ignored issues
show
Unused Code introduced by
$os 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...
1434
        $headerlen = 10;
1435
        $extralen = 0;
1436
        $extra = "";
0 ignored issues
show
Unused Code introduced by
$extra 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...
1437
        if ($flags & 4) {
1438
            // 2-byte length prefixed EXTRA data in header
1439
            if (($len - $headerlen - 2) < 8) {
1440
                return false; // Invalid format
1441
            }
1442
            $extralen = unpack("v", substr($data, 8, 2));
1443
            $extralen = $extralen[1];
1444
            if (($len - $headerlen - 2 - $extralen) < 8) {
1445
                return false; // Invalid format
1446
            }
1447
            $extra = substr($data, 10, $extralen);
0 ignored issues
show
Unused Code introduced by
$extra 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...
1448
            $headerlen += 2 + $extralen;
1449
        }
1450
1451
        $filenamelen = 0;
1452
        $filename = "";
0 ignored issues
show
Unused Code introduced by
$filename 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...
1453 View Code Duplication
        if ($flags & 8) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1454
            // C-style string file NAME data in header
1455
            if (($len - $headerlen - 1) < 8) {
1456
                return false; // Invalid format
1457
            }
1458
            $filenamelen = strpos(substr($data, 8 + $extralen), chr(0));
1459
            if ($filenamelen === false || ($len - $headerlen - $filenamelen - 1) < 8) {
1460
                return false; // Invalid format
1461
            }
1462
            $filename = substr($data, $headerlen, $filenamelen);
0 ignored issues
show
Unused Code introduced by
$filename 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...
1463
            $headerlen += $filenamelen + 1;
1464
        }
1465
1466
        $commentlen = 0;
0 ignored issues
show
Unused Code introduced by
$commentlen 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...
1467
        $comment = "";
0 ignored issues
show
Unused Code introduced by
$comment 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...
1468 View Code Duplication
        if ($flags & 16) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1469
            // C-style string COMMENT data in header
1470
            if (($len - $headerlen - 1) < 8) {
1471
                return false; // Invalid format
1472
            }
1473
            $commentlen = strpos(substr($data, 8 + $extralen + $filenamelen), chr(0));
1474
            if ($commentlen === false || ($len - $headerlen - $commentlen - 1) < 8) {
1475
                return false; // Invalid header format
1476
            }
1477
            $comment = substr($data, $headerlen, $commentlen);
0 ignored issues
show
Unused Code introduced by
$comment 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...
1478
            $headerlen += $commentlen + 1;
1479
        }
1480
1481
        $headercrc = "";
0 ignored issues
show
Unused Code introduced by
$headercrc 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...
1482
        if ($flags & 1) {
1483
            // 2-bytes (lowest order) of CRC32 on header present
1484
            if (($len - $headerlen - 2) < 8) {
1485
                return false; // Invalid format
1486
            }
1487
            $calccrc = crc32(substr($data, 0, $headerlen)) & 0xffff;
1488
            $headercrc = unpack("v", substr($data, $headerlen, 2));
1489
            $headercrc = $headercrc[1];
1490
            if ($headercrc != $calccrc) {
1491
                return false; // Bad header CRC
1492
            }
1493
            $headerlen += 2;
1494
        }
1495
1496
        // GZIP FOOTER - These be negative due to PHP's limitations
1497
        $datacrc = unpack("V", substr($data, -8, 4));
1498
        $datacrc = $datacrc[1];
1499
        $isize = unpack("V", substr($data, -4));
1500
        $isize = $isize[1];
1501
1502
        // Perform the decompression:
1503
        $bodylen = $len - $headerlen - 8;
1504
        if ($bodylen < 1) {
1505
            // This should never happen - IMPLEMENTATION BUG!
1506
            return null;
1507
        }
1508
        $body = substr($data, $headerlen, $bodylen);
1509
        $data = "";
1510
        if ($bodylen > 0) {
1511
            switch ($method) {
1512
                case 8:
1513
                    // Currently the only supported compression method:
1514
                    $data = gzinflate($body);
1515
                    break;
1516
                default:
1517
                    // Unknown compression method
1518
                    return false;
1519
            }
1520
        }
1521
        // Verify decompressed size and CRC32:
1522
        // NOTE: This may fail with large data sizes depending on how
1523
        //      PHP's integer limitations affect strlen() since $isize
1524
        //      may be negative for large sizes.
1525
        if ($isize != strlen($data) || crc32($data) != $datacrc) {
1526
            // Bad format!  Length or CRC doesn't match!
1527
            return false;
1528
        }
1529
1530
        return $data;
1531
    }
1532
}
1533