Issues (1507)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

PHPDaemon/Network/Client.php (14 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace PHPDaemon\Network;
3
4
use PHPDaemon\Network;
5
use PHPDaemon\Request;
6
use PHPDaemon\Structures\ObjectStorage;
7
use PHPDaemon\Structures\PriorityQueueCallbacks;
8
9
/**
10
 * Network client pattern
11
 * @package PHPDaemon\Network
12
 * @author  Vasily Zorin <[email protected]>
13
 */
14
abstract class Client extends Pool
15
{
16
17
    /**
18
     * @var array Array of servers
19
     */
20
    protected $servers = [];
21
22
    /**
23
     * @var array Active connections
24
     */
25
    protected $servConn = [];
26
27
    /**
28
     * @var array
29
     */
30
    protected $servConnFree = [];
31
32
    /**
33
     * @var integer
34
     */
35
    protected $maxConnPerServ = 32;
36
37
    /**
38
     * @var boolean
39
     */
40
    protected $acquireOnGet = false;
41
42
    /**
43
     * @var array
44
     */
45
    protected $pending = [];
46
47
48
    /**
49
     * Setting default config options
50
     * Overriden from ConnectionPool::getConfigDefaults
51
     * @return array
52
     */
53
    protected function getConfigDefaults()
54
    {
55
        return [
56
            /* [boolean] Expose? */
57
            'expose' => 1,
58
59
            /* [string|array] Default servers */
60
            'servers' => '127.0.0.1',
61
62
            /* [string] Default server */
63
            'server' => '127.0.0.1',
64
65
            /* [integer] Maximum connections per server */
66
            'maxconnperserv' => 32
67
        ];
68
    }
69
70
    /**
71
     * Applies config
72
     * @return void
73
     */
74
    protected function applyConfig()
75
    {
76
        parent::applyConfig();
77
        if (isset($this->config->servers)) {
78
            $servers = array_filter(array_map('trim', explode(',', $this->config->servers->value)), 'mb_orig_strlen');
0 ignored issues
show
The property servers does not seem to exist in PHPDaemon\Config\Section.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
79
            $this->servers = [];
80
            foreach ($servers as $s) {
81
                $this->addServer($s);
82
            }
83
        }
84
        if (isset($this->config->maxconnperserv)) {
85
            $this->maxConnPerServ = $this->config->maxconnperserv->value;
0 ignored issues
show
The property maxconnperserv does not seem to exist in PHPDaemon\Config\Section.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
86
        }
87
    }
88
89
    /**
90
     * Adds server
91
     * @param  string $url Server URL
92
     * @param  integer $weight Weight
0 ignored issues
show
Should the type for parameter $weight not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
93
     * @return void
94
     */
95
    public function addServer($url, $weight = null)
96
    {
97
        $this->servers[$url] = $weight;
98
    }
99
    
100
101
    /**
102
     * Returns available connection from the pool
103
     * @param  string $url Address
0 ignored issues
show
Should the type for parameter $url not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
104
     * @param  callback $cb onConnected
0 ignored issues
show
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
105
     * @param  integer $pri Optional. Priority
106
     * @param  \Closure $beforeConnect Called before establishing the connection
0 ignored issues
show
Should the type for parameter $beforeConnect not be null|\Closure?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
107
     * @call   ( callable $cb )
108
     * @call   ( string $url = null, callable $cb = null, integer $pri = 0 )
109
     * @return boolean       Success|Connection
110
     */
111
    public function getConnection($url = null, $cb = null, $pri = 0, \Closure $beforeConnect = null)
112
    {
113
        if (!is_string($url) && $url !== null && $cb === null) { // if called getConnection(function....)
114
            $cb = $url;
115
            $url = null;
116
        }
117
        if ($url === null) {
118
            if (isset($this->config->server->value)) {
119
                $url = $this->config->server->value;
0 ignored issues
show
The property server does not seem to exist in PHPDaemon\Config\Section.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
120
            } elseif (isset($this->servers) && sizeof($this->servers)) {
121
                $url = array_rand($this->servers);
122
            } else {
123
                if ($cb) {
124
                    $cb(false);
125
                }
126
                return false;
127
            }
128
        }
129
130
        start:
131
        $conn = false;
132
        if (isset($this->servConn[$url])) {
133
            $storage = $this->servConn[$url];
134
            $free = $this->servConnFree[$url];
135
            if ($free->count() > 0) {
136
                $conn = $free->getFirst();
137
                if (!$conn->isConnected() || $conn->isFinished()) {
138
                    $free->detach($conn);
139
                    goto start;
140
                }
141
                if ($this->acquireOnGet) {
142
                    $free->detach($conn);
143
                }
144
            } elseif ($storage->count() >= $this->maxConnPerServ) {
145
                if (!isset($this->pending[$url])) {
146
                    $this->pending[$url] = new PriorityQueueCallbacks;
147
                }
148
                $this->pending[$url]->enqueue($cb, $pri);
149
                return true;
150
            }
151
            if ($conn) {
152
                if ($cb !== null) {
153
                    $conn->onConnected($cb);
154
                }
155
                return true;
156
            }
157
        } else {
158
            $this->servConn[$url] = new ObjectStorage;
159
            $this->servConnFree[$url] = new ObjectStorage;
160
        }
161
        //Daemon::log($url . "\n" . Debug::dump($this->finished) . "\n" . Debug::backtrace(true));
162
        $conn = $this->connect($url, $cb, null, $beforeConnect);
0 ignored issues
show
It seems like $cb can also be of type null; however, PHPDaemon\Network\Pool::connect() does only seem to accept callable, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
163
164
        if (!$conn || $conn->isFinished()) {
165
            return false;
166
        }
167
        $this->servConn[$url]->attach($conn);
168
        return true;
169
    }
170
171
    /**
172
     * Detach Connection
173
     * @param  object $conn Connection
174
     * @return void
175
     */
176
    public function detach($conn)
177
    {
178
        parent::detach($conn);
179
        $this->touchPending($conn->getUrl());
180
    }
181
182
    /**
183
     * Mark connection as free
184
     * @param  ClientConnection $conn Connection
185
     * @param  string $url URL
186
     * @return void
187
     */
188
    public function markConnFree(ClientConnection $conn, $url)
189
    {
190
        if (!isset($this->servConnFree[$url])) {
191
            return;
192
        }
193
        $this->servConnFree[$url]->attach($conn);
194
    }
195
196
    /**
197
     * Mark connection as busy
198
     * @param  ClientConnection $conn Connection
199
     * @param  string $url URL
200
     * @return void
201
     */
202
    public function markConnBusy(ClientConnection $conn, $url)
203
    {
204
        if (!isset($this->servConnFree[$url])) {
205
            return;
206
        }
207
        $this->servConnFree[$url]->detach($conn);
208
    }
209
210
    /**
211
     * Detaches connection from URL
212
     * @param  ClientConnection $conn Connection
213
     * @param  string $url URL
214
     * @return void
215
     */
216
    public function detachConnFromUrl(ClientConnection $conn, $url)
217
    {
218
        if (isset($this->servConnFree[$url])) {
219
            $this->servConnFree[$url]->detach($conn);
220
        }
221
        if (isset($this->servConn[$url])) {
222
            $this->servConn[$url]->detach($conn);
223
        }
224
    }
225
226
    /**
227
     * Touch pending "requests for connection"
228
     * @param  string $url URL
229
     * @return void
230
     */
231
    public function touchPending($url)
232
    {
233
        while (isset($this->pending[$url]) && !$this->pending[$url]->isEmpty()) {
234
            if (true === $this->getConnection($url, $this->pending[$url]->dequeue())) {
235
                return;
236
            }
237
        }
238
    }
239
240
    /**
241
     * Returns available connection from the pool by key
242
     * @param  string $key Key
243
     * @param  callable $cb Callback
0 ignored issues
show
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
244
     * @callback $cb ( )
245
     * @return boolean       Success
246
     */
247
    public function getConnectionByKey($key, $cb = null)
248
    {
249
        if (is_object($key)) {
250
            return $key->onConnected($cb);
251
        }
252
        srand(crc32($key));
253
        $addr = array_rand($this->servers);
254
        srand();
255
        return $this->getConnection($addr, $cb);
256
    }
257
258
    /**
259
     * Returns available connection from the pool
260
     * @param  callable $cb Callback
0 ignored issues
show
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
261
     * @callback $cb ( )
262
     * @return boolean      Success
263
     */
264
    public function getConnectionRR($cb = null)
265
    {
266
        return $this->getConnection(null, $cb);
267
    }
268
269
    /**
270
     * Sends a request to arbitrary server
271
     * @param  string $server Server
272
     * @param  string $data Data
273
     * @param  callable $onResponse Called when the request complete
0 ignored issues
show
Should the type for parameter $onResponse not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
274
     * @callback $onResponse ( )
275
     * @return boolean              Success
276
     */
277 View Code Duplication
    public function requestByServer($server, $data, $onResponse = null)
0 ignored issues
show
This method seems to be duplicated in 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...
278
    {
279
        $this->getConnection($server, function ($conn) use ($data, $onResponse) {
280
            if (!$conn->isConnected()) {
281
                return;
282
            }
283
            $conn->onResponse($onResponse);
284
            $conn->write($data);
285
        });
286
        return true;
287
    }
288
289
    /**
290
     * Sends a request to server according to the key
291
     * @param  string $key Key
292
     * @param  string $data Data
293
     * @param  callable $onResponse Callback called when the request complete
0 ignored issues
show
Should the type for parameter $onResponse not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
294
     * @callback $onResponse ( )
295
     * @return boolean              Success
296
     */
297 View Code Duplication
    public function requestByKey($key, $data, $onResponse = null)
0 ignored issues
show
This method seems to be duplicated in 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...
298
    {
299
        $this->getConnectionByKey($key, function ($conn) use ($data, $onResponse) {
300
            if (!$conn->isConnected()) {
301
                return;
302
            }
303
            $conn->onResponse($onResponse);
304
            $conn->write($data);
305
        });
306
        return true;
307
    }
308
309
    /**
310
     * Called when application instance is going to shutdown
311
     * @param  boolean $graceful Graceful?
312
     * @return boolean           Ready to shutdown?
313
     */
314
    public function onShutdown($graceful = false)
315
    {
316
        return $graceful ? true : $this->finish();
317
    }
318
}
319