This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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\Servers\WebSocket; |
||
3 | |||
4 | use PHPDaemon\Core\Daemon; |
||
5 | use PHPDaemon\HTTPRequest\Generic; |
||
6 | use PHPDaemon\Request\RequestHeadersAlreadySent; |
||
7 | |||
8 | class Connection extends \PHPDaemon\Network\Connection |
||
9 | { |
||
10 | use \PHPDaemon\Traits\DeferredEventHandlers; |
||
11 | use \PHPDaemon\Traits\Sessions; |
||
12 | |||
13 | /** |
||
14 | * @var integer Timeout |
||
15 | */ |
||
16 | protected $timeout = 120; |
||
17 | |||
18 | protected $handshaked = false; |
||
19 | |||
20 | /** |
||
21 | * @var $route \PHPDaemon\WebSocket\Route |
||
22 | */ |
||
23 | protected $route; |
||
24 | |||
25 | protected $writeReady = true; |
||
26 | protected $extensions = []; |
||
27 | protected $extensionsCleanRegex = '/(?:^|\W)x-webkit-/iS'; |
||
28 | |||
29 | protected $headers = []; |
||
30 | protected $headers_sent = false; |
||
31 | |||
32 | /** |
||
33 | * @var array _SERVER |
||
34 | */ |
||
35 | public $server = []; |
||
36 | |||
37 | /** |
||
38 | * @var array _COOKIE |
||
39 | */ |
||
40 | public $cookie = []; |
||
41 | |||
42 | /** |
||
43 | * @var array _GET |
||
44 | */ |
||
45 | public $get = []; |
||
46 | |||
47 | |||
48 | protected $policyReqNotFound = false; |
||
49 | protected $currentHeader; |
||
50 | protected $EOL = "\r\n"; |
||
51 | |||
52 | /** |
||
53 | * @var boolean Is this connection running right now? |
||
54 | */ |
||
55 | protected $running = false; |
||
56 | |||
57 | /** |
||
58 | * State: first line |
||
59 | */ |
||
60 | const STATE_FIRSTLINE = 1; |
||
61 | |||
62 | /** |
||
63 | * State: headers |
||
64 | */ |
||
65 | const STATE_HEADERS = 2; |
||
66 | |||
67 | /** |
||
68 | * State: content |
||
69 | */ |
||
70 | const STATE_CONTENT = 3; |
||
71 | |||
72 | /** |
||
73 | * State: prehandshake |
||
74 | */ |
||
75 | const STATE_PREHANDSHAKE = 5; |
||
76 | |||
77 | /** |
||
78 | * State: handshaked |
||
79 | */ |
||
80 | const STATE_HANDSHAKED = 6; |
||
81 | |||
82 | const STRING = null; |
||
83 | |||
84 | const BINARY = null; |
||
85 | |||
86 | /** |
||
87 | * @var integer Content length from header() method |
||
88 | */ |
||
89 | protected $contentLength; |
||
90 | |||
91 | /** |
||
92 | * @var integer Number of outgoing cookie-headers |
||
93 | */ |
||
94 | protected $cookieNum = 0; |
||
95 | |||
96 | /** |
||
97 | * @var array Replacement pairs for processing some header values in parse_str() |
||
98 | */ |
||
99 | public static $hvaltr = ['; ' => '&', ';' => '&', ' ' => '%20']; |
||
100 | |||
101 | /** |
||
102 | * Called when the stream is handshaked (at low-level), and peer is ready to recv. data |
||
103 | * @return void |
||
104 | */ |
||
105 | public function onReady() |
||
106 | { |
||
107 | $this->setWatermark(null, $this->pool->maxAllowedPacket + 100); |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * Get real frame type identificator |
||
112 | * @param $type |
||
113 | * @return integer |
||
114 | */ |
||
115 | public function getFrameType($type) |
||
116 | { |
||
117 | if (is_int($type)) { |
||
118 | return $type; |
||
119 | } |
||
120 | if ($type === null) { |
||
121 | $type = 'STRING'; |
||
122 | } |
||
123 | $frametype = @constant(get_class($this) . '::' . $type); |
||
124 | if ($frametype === null) { |
||
125 | Daemon::log(__METHOD__ . ' : Undefined frametype "' . $type . '"'); |
||
126 | } |
||
127 | return $frametype; |
||
128 | } |
||
129 | |||
130 | |||
131 | /** |
||
132 | * Called when connection is inherited from HTTP request |
||
133 | * @param object $req |
||
134 | * @return void |
||
135 | */ |
||
136 | View Code Duplication | public function onInheritanceFromRequest($req) |
|
0 ignored issues
–
show
|
|||
137 | { |
||
138 | $this->state = self::STATE_HEADERS; |
||
139 | $this->addr = $req->attrs->server['REMOTE_ADDR']; |
||
140 | $this->server = $req->attrs->server; |
||
141 | $this->get = $req->attrs->get; |
||
142 | $this->prependInput("\r\n"); |
||
143 | $this->onRead(); |
||
144 | } |
||
145 | |||
146 | /** |
||
147 | * Sends a frame. |
||
148 | * @param string $data Frame's data. |
||
149 | * @param string $type Frame's type. ("STRING" OR "BINARY") |
||
0 ignored issues
–
show
Should the type for parameter
$type not be string|null ?
This check looks for 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. ![]() |
|||
150 | * @param callable $cb Optional. Callback called when the frame is received by client. |
||
0 ignored issues
–
show
Should the type for parameter
$cb not be callable|null ?
This check looks for 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. ![]() |
|||
151 | * @callback $cb ( ) |
||
152 | * @return boolean Success. |
||
153 | */ |
||
154 | public function sendFrame($data, $type = null, $cb = null) |
||
155 | { |
||
156 | return false; |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * Event of Connection. |
||
161 | * @return void |
||
162 | */ |
||
163 | public function onFinish() |
||
164 | { |
||
165 | $this->sendFrame('', 'CONNCLOSE'); |
||
166 | |||
167 | if ($this->route) { |
||
168 | $this->route->onFinish(); |
||
169 | } |
||
170 | $this->route = null; |
||
171 | } |
||
172 | |||
173 | /** |
||
174 | * Uncaught exception handler |
||
175 | * @param \Exception $e |
||
176 | * @return boolean Handled? |
||
177 | */ |
||
178 | public function handleException($e) |
||
179 | { |
||
180 | if (!isset($this->route)) { |
||
181 | return false; |
||
182 | } |
||
183 | return $this->route->handleException($e); |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Called when new frame received. |
||
188 | * @param string $data Frame's data. |
||
189 | * @param string $type Frame's type ("STRING" OR "BINARY"). |
||
190 | * @return boolean Success. |
||
191 | */ |
||
192 | public function onFrame($data, $type) |
||
193 | { |
||
194 | if (!isset($this->route)) { |
||
195 | return false; |
||
196 | } |
||
197 | try { |
||
198 | $this->route->onWakeup(); |
||
199 | $this->route->onFrame($data, $type); |
||
200 | } catch (\Throwable $e) { |
||
0 ignored issues
–
show
The class
Throwable does not exist. Did you forget a USE statement, or did you not list all dependencies?
Scrutinizer analyzes your It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis. ![]() |
|||
201 | Daemon::uncaughtExceptionHandler($e); |
||
202 | } |
||
203 | if ($this->route) { |
||
204 | $this->route->onSleep(); |
||
205 | } |
||
206 | return true; |
||
207 | } |
||
208 | |||
209 | /** |
||
210 | * Called when the worker is going to shutdown. |
||
211 | * @return boolean Ready to shutdown ? |
||
212 | */ |
||
213 | public function gracefulShutdown() |
||
214 | { |
||
215 | if ((!$this->route) || $this->route->gracefulShutdown()) { |
||
216 | $this->finish(); |
||
217 | return true; |
||
218 | } |
||
219 | return false; |
||
220 | } |
||
221 | |||
222 | |||
223 | /** |
||
224 | * Called when we're going to handshake. |
||
225 | * @return boolean Handshake status |
||
226 | */ |
||
227 | public function handshake() |
||
228 | { |
||
229 | $this->route = $this->pool->getRoute($this->server['DOCUMENT_URI'], $this); |
||
230 | View Code Duplication | if (!$this->route) { |
|
0 ignored issues
–
show
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. ![]() |
|||
231 | Daemon::$process->log(get_class($this) . '::' . __METHOD__ . ' : Cannot handshake session for client "' . $this->addr . '"'); |
||
232 | $this->finish(); |
||
233 | return false; |
||
234 | } |
||
235 | |||
236 | if (method_exists($this->route, 'onBeforeHandshake')) { |
||
237 | $this->route->onWakeup(); |
||
238 | $ret = $this->route->onBeforeHandshake(function () { |
||
239 | $this->handshakeAfter(); |
||
240 | }); |
||
241 | if ($this->route) { |
||
242 | $this->route->onSleep(); |
||
243 | } |
||
244 | if ($ret !== false) { |
||
245 | return true; |
||
246 | } |
||
247 | } |
||
248 | |||
249 | return $this->handshakeAfter(); |
||
250 | } |
||
251 | |||
252 | protected function handshakeAfter() |
||
253 | { |
||
254 | $extraHeaders = ''; |
||
255 | foreach ($this->headers as $k => $line) { |
||
256 | if ($k !== 'STATUS') { |
||
257 | $extraHeaders .= $line . "\r\n"; |
||
258 | } |
||
259 | } |
||
260 | |||
261 | View Code Duplication | if (!$this->sendHandshakeReply($extraHeaders)) { |
|
0 ignored issues
–
show
The method
sendHandshakeReply() does not exist on PHPDaemon\Servers\WebSocket\Connection . Did you maybe mean handshake() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() 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. ![]() |
|||
262 | Daemon::$process->log(get_class($this) . '::' . __METHOD__ . ' : Handshake protocol failure for client "' . $this->addr . '"'); |
||
263 | $this->finish(); |
||
264 | return false; |
||
265 | } |
||
266 | |||
267 | $this->handshaked = true; |
||
268 | $this->headers_sent = true; |
||
269 | $this->state = static::STATE_HANDSHAKED; |
||
270 | if (is_callable([$this->route, 'onHandshake'])) { |
||
271 | $this->route->onWakeup(); |
||
0 ignored issues
–
show
|
|||
272 | $this->route->onHandshake(); |
||
0 ignored issues
–
show
|
|||
273 | if ($this->route) { |
||
274 | $this->route->onSleep(); |
||
275 | } |
||
276 | } |
||
277 | return true; |
||
278 | } |
||
279 | |||
280 | /** |
||
281 | * Send Bad request |
||
282 | * @return void |
||
283 | */ |
||
284 | public function badRequest() |
||
285 | { |
||
286 | $this->state = self::STATE_STANDBY; |
||
287 | $this->write("400 Bad Request\r\n\r\n<html><head><title>400 Bad Request</title></head><body bgcolor=\"white\"><center><h1>400 Bad Request</h1></center></body></html>"); |
||
288 | $this->finish(); |
||
289 | } |
||
290 | |||
291 | /** |
||
292 | * Read first line of HTTP request |
||
293 | * @return boolean|null Success |
||
294 | */ |
||
295 | protected function httpReadFirstline() |
||
296 | { |
||
297 | if (($l = $this->readline()) === null) { |
||
298 | return null; |
||
299 | } |
||
300 | $e = explode(' ', $l); |
||
301 | $u = isset($e[1]) ? parse_url($e[1]) : false; |
||
302 | if ($u === false) { |
||
303 | $this->badRequest(); |
||
304 | return false; |
||
305 | } |
||
306 | if (!isset($u['path'])) { |
||
307 | $u['path'] = null; |
||
308 | } |
||
309 | if (isset($u['host'])) { |
||
310 | $this->server['HTTP_HOST'] = $u['host']; |
||
311 | } |
||
312 | $srv = &$this->server; |
||
313 | $srv['REQUEST_METHOD'] = $e[0]; |
||
314 | $srv['REQUEST_TIME'] = time(); |
||
315 | $srv['REQUEST_TIME_FLOAT'] = microtime(true); |
||
316 | $srv['REQUEST_URI'] = $u['path'] . (isset($u['query']) ? '?' . $u['query'] : ''); |
||
317 | $srv['DOCUMENT_URI'] = $u['path']; |
||
318 | $srv['PHP_SELF'] = $u['path']; |
||
319 | $srv['QUERY_STRING'] = isset($u['query']) ? $u['query'] : null; |
||
320 | $srv['SCRIPT_NAME'] = $srv['DOCUMENT_URI'] = isset($u['path']) ? $u['path'] : '/'; |
||
321 | $srv['SERVER_PROTOCOL'] = isset($e[2]) ? $e[2] : 'HTTP/1.1'; |
||
322 | $srv['REMOTE_ADDR'] = $this->addr; |
||
323 | $srv['REMOTE_PORT'] = $this->port; |
||
324 | return true; |
||
325 | } |
||
326 | |||
327 | /** |
||
328 | * Read headers line-by-line |
||
329 | * @return boolean|null Success |
||
330 | */ |
||
331 | protected function httpReadHeaders() |
||
332 | { |
||
333 | while (($l = $this->readLine()) !== null) { |
||
334 | if ($l === '') { |
||
335 | return true; |
||
336 | } |
||
337 | $e = explode(': ', $l); |
||
338 | if (isset($e[1])) { |
||
339 | $this->currentHeader = 'HTTP_' . strtoupper(strtr($e[0], Generic::$htr)); |
||
340 | $this->server[$this->currentHeader] = $e[1]; |
||
341 | View Code Duplication | } elseif (($e[0][0] === "\t" || $e[0][0] === "\x20") && $this->currentHeader) { |
|
0 ignored issues
–
show
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. ![]() |
|||
342 | // multiline header continued |
||
343 | $this->server[$this->currentHeader] .= $e[0]; |
||
344 | } else { |
||
345 | // whatever client speaks is not HTTP anymore |
||
346 | $this->badRequest(); |
||
347 | return false; |
||
348 | } |
||
349 | } |
||
350 | return null; |
||
351 | } |
||
352 | |||
353 | /** |
||
354 | * Called when new data received. |
||
355 | * @return void |
||
356 | */ |
||
357 | protected function onRead() |
||
358 | { |
||
359 | View Code Duplication | if (!$this->policyReqNotFound) { |
|
0 ignored issues
–
show
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. ![]() |
|||
360 | $d = $this->drainIfMatch("<policy-file-request/>\x00"); |
||
361 | if ($d === null) { // partially match |
||
362 | return; |
||
363 | } |
||
364 | if ($d) { |
||
365 | if (($FP = \PHPDaemon\Servers\FlashPolicy\Pool::getInstance($this->pool->config->fpsname->value, |
||
366 | false)) && $FP->policyData |
||
367 | ) { |
||
368 | $this->write($FP->policyData . "\x00"); |
||
369 | } |
||
370 | $this->finish(); |
||
371 | return; |
||
372 | } else { |
||
373 | $this->policyReqNotFound = true; |
||
374 | } |
||
375 | } |
||
376 | start: |
||
377 | if ($this->finished) { |
||
378 | return; |
||
379 | } |
||
380 | if ($this->state === self::STATE_STANDBY) { |
||
381 | $this->state = self::STATE_FIRSTLINE; |
||
382 | } |
||
383 | if ($this->state === self::STATE_FIRSTLINE) { |
||
384 | if (!$this->httpReadFirstline()) { |
||
0 ignored issues
–
show
The expression
$this->httpReadFirstline() of type null|boolean is loosely compared to false ; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.
If an expression can have both $a = canBeFalseAndNull();
// Instead of
if ( ! $a) { }
// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
![]() |
|||
385 | return; |
||
386 | } |
||
387 | $this->state = self::STATE_HEADERS; |
||
388 | } |
||
389 | |||
390 | View Code Duplication | if ($this->state === self::STATE_HEADERS) { |
|
0 ignored issues
–
show
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. ![]() |
|||
391 | if (!$this->httpReadHeaders()) { |
||
0 ignored issues
–
show
The expression
$this->httpReadHeaders() of type boolean|null is loosely compared to false ; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.
If an expression can have both $a = canBeFalseAndNull();
// Instead of
if ( ! $a) { }
// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
![]() |
|||
392 | return; |
||
393 | } |
||
394 | if (!$this->httpProcessHeaders()) { |
||
395 | $this->finish(); |
||
396 | return; |
||
397 | } |
||
398 | $this->state = self::STATE_CONTENT; |
||
399 | } |
||
400 | if ($this->state === self::STATE_CONTENT) { |
||
401 | $this->state = self::STATE_PREHANDSHAKE; |
||
402 | } |
||
403 | } |
||
404 | |||
405 | /** |
||
406 | * Process headers |
||
407 | * @return bool |
||
408 | */ |
||
409 | protected function httpProcessHeaders() |
||
410 | { |
||
411 | $this->state = self::STATE_PREHANDSHAKE; |
||
412 | if (isset($this->server['HTTP_SEC_WEBSOCKET_EXTENSIONS'])) { |
||
413 | $str = strtolower($this->server['HTTP_SEC_WEBSOCKET_EXTENSIONS']); |
||
414 | $str = preg_replace($this->extensionsCleanRegex, '', $str); |
||
415 | $this->extensions = explode(', ', $str); |
||
416 | } |
||
417 | if (!isset($this->server['HTTP_CONNECTION']) |
||
418 | || (!preg_match('~(?:^|\W)Upgrade(?:\W|$)~i', |
||
419 | $this->server['HTTP_CONNECTION'])) // "Upgrade" is not always alone (ie. "Connection: Keep-alive, Upgrade") |
||
420 | || !isset($this->server['HTTP_UPGRADE']) |
||
421 | || (strtolower($this->server['HTTP_UPGRADE']) !== 'websocket') // Lowercase comparison iss important |
||
422 | ) { |
||
423 | $this->finish(); |
||
424 | return false; |
||
425 | } |
||
426 | View Code Duplication | if (isset($this->server['HTTP_COOKIE'])) { |
|
0 ignored issues
–
show
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. ![]() |
|||
427 | Generic::parseStr(strtr($this->server['HTTP_COOKIE'], Generic::$hvaltr), $this->cookie); |
||
428 | } |
||
429 | if (isset($this->server['QUERY_STRING'])) { |
||
430 | Generic::parseStr($this->server['QUERY_STRING'], $this->get); |
||
431 | } |
||
432 | // ---------------------------------------------------------- |
||
433 | // Protocol discovery, based on HTTP headers... |
||
434 | // ---------------------------------------------------------- |
||
435 | if (isset($this->server['HTTP_SEC_WEBSOCKET_VERSION'])) { // HYBI |
||
436 | if ($this->server['HTTP_SEC_WEBSOCKET_VERSION'] === '8') { // Version 8 (FF7, Chrome14) |
||
437 | $this->switchToProtocol('V13'); |
||
438 | } elseif ($this->server['HTTP_SEC_WEBSOCKET_VERSION'] === '13') { // newest protocol |
||
439 | $this->switchToProtocol('V13'); |
||
440 | } else { |
||
441 | Daemon::$process->log(get_class($this) . '::' . __METHOD__ . " : Websocket protocol version " . $this->server['HTTP_SEC_WEBSOCKET_VERSION'] . ' is not yet supported for client "' . $this->addr . '"'); |
||
442 | $this->finish(); |
||
443 | return false; |
||
444 | } |
||
445 | View Code Duplication | } elseif (!isset($this->server['HTTP_SEC_WEBSOCKET_KEY1']) || !isset($this->server['HTTP_SEC_WEBSOCKET_KEY2'])) { |
|
0 ignored issues
–
show
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. ![]() |
|||
446 | $this->switchToProtocol('VE'); |
||
447 | } else { // Defaulting to HIXIE (Safari5 and many non-browser clients...) |
||
448 | $this->switchToProtocol('V0'); |
||
449 | } |
||
450 | // ---------------------------------------------------------- |
||
451 | // End of protocol discovery |
||
452 | // ---------------------------------------------------------- |
||
453 | return true; |
||
454 | } |
||
455 | |||
456 | protected function switchToProtocol($proto) |
||
457 | { |
||
458 | $class = '\\PHPDaemon\\Servers\\WebSocket\\Protocols\\' . $proto; |
||
459 | $conn = new $class(null, $this->pool); |
||
460 | $this->pool->attach($conn); |
||
461 | $conn->setFd($this->getFd(), $this->getBev()); |
||
462 | $this->unsetFd(); |
||
463 | $this->pool->detach($this); |
||
464 | $conn->onInheritance($this); |
||
465 | } |
||
466 | |||
467 | View Code Duplication | public function onInheritance($conn) |
|
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. ![]() |
|||
468 | { |
||
469 | $this->server = $conn->server; |
||
470 | $this->cookie = $conn->cookie; |
||
471 | $this->get = $conn->get; |
||
472 | $this->state = self::STATE_PREHANDSHAKE; |
||
473 | $this->addr = $conn->addr; |
||
474 | $this->onRead(); |
||
475 | } |
||
476 | |||
477 | |||
478 | /** |
||
479 | * Send HTTP-status |
||
480 | * @throws RequestHeadersAlreadySent |
||
481 | * @param integer $code Code |
||
482 | * @return boolean Success |
||
483 | */ |
||
484 | public function status($code = 200) |
||
0 ignored issues
–
show
|
|||
485 | { |
||
486 | return false; |
||
487 | } |
||
488 | |||
489 | /** |
||
490 | * Send the header |
||
491 | * @param string $s Header. Example: 'Location: http://php.net/' |
||
492 | * @param boolean $replace Optional. Replace? |
||
493 | * @param boolean $code Optional. HTTP response code |
||
494 | * @throws \PHPDaemon\Request\RequestHeadersAlreadySent |
||
495 | * @return boolean Success |
||
496 | */ |
||
497 | View Code Duplication | public function header($s, $replace = true, $code = false) |
|
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. ![]() |
|||
498 | { |
||
499 | if ($code) { |
||
500 | $this->status($code); |
||
0 ignored issues
–
show
$code is of type boolean , but the function expects a integer .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() The call to the method
PHPDaemon\Servers\WebSocket\Connection::status() seems un-needed as the method has no side-effects.
PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left. Let’s take a look at an example: class User
{
private $email;
public function getEmail()
{
return $this->email;
}
public function setEmail($email)
{
$this->email = $email;
}
}
If we look at the $user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.
On the hand, if we look at the $user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
// instance variable).
![]() |
|||
501 | } |
||
502 | |||
503 | if ($this->headers_sent) { |
||
504 | throw new RequestHeadersAlreadySent; |
||
505 | } |
||
506 | $s = strtr($s, "\r\n", ' '); |
||
507 | |||
508 | $e = explode(':', $s, 2); |
||
509 | |||
510 | if (!isset($e[1])) { |
||
511 | $e[0] = 'STATUS'; |
||
512 | |||
513 | if (strncmp($s, 'HTTP/', 5) === 0) { |
||
514 | $s = substr($s, 9); |
||
515 | } |
||
516 | } |
||
517 | |||
518 | $k = strtr(strtoupper($e[0]), Generic::$htr); |
||
519 | |||
520 | if ($k === 'CONTENT_TYPE') { |
||
521 | Generic::parseStr(strtolower($e[1]), $ctype, true); |
||
522 | if (!isset($ctype['charset'])) { |
||
523 | $ctype['charset'] = $this->upstream->pool->config->defaultcharset->value; |
||
0 ignored issues
–
show
The property
upstream does not exist on object<PHPDaemon\Servers\WebSocket\Connection> . Since you implemented __get , maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
524 | |||
525 | $s = $e[0] . ': '; |
||
526 | $i = 0; |
||
527 | foreach ($ctype as $k => $v) { |
||
528 | $s .= ($i > 0 ? '; ' : '') . $k . ($v !== '' ? '=' . $v : ''); |
||
529 | ++$i; |
||
530 | } |
||
531 | } |
||
532 | } |
||
533 | if ($k === 'SET_COOKIE') { |
||
534 | $k .= '_' . ++$this->cookieNum; |
||
535 | } elseif (!$replace && isset($this->headers[$k])) { |
||
536 | return false; |
||
537 | } |
||
538 | |||
539 | $this->headers[$k] = $s; |
||
540 | |||
541 | if ($k === 'CONTENT_LENGTH') { |
||
542 | $this->contentLength = (int)$e[1]; |
||
543 | } elseif ($k === 'LOCATION') { |
||
544 | $this->status(301); |
||
0 ignored issues
–
show
The call to the method
PHPDaemon\Servers\WebSocket\Connection::status() seems un-needed as the method has no side-effects.
PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left. Let’s take a look at an example: class User
{
private $email;
public function getEmail()
{
return $this->email;
}
public function setEmail($email)
{
$this->email = $email;
}
}
If we look at the $user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.
On the hand, if we look at the $user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
// instance variable).
![]() |
|||
545 | } |
||
546 | |||
547 | if (Daemon::$compatMode) { |
||
548 | is_callable('header_native') ? header_native($s) : header($s); |
||
549 | } |
||
550 | |||
551 | return true; |
||
552 | } |
||
553 | } |
||
554 |
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.