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\Traits; |
||
3 | |||
4 | use PHPDaemon\Core\CallbackWrapper; |
||
5 | use PHPDaemon\Core\Daemon; |
||
6 | use PHPDaemon\FS\FileSystem; |
||
7 | |||
8 | /** |
||
9 | * Sessions |
||
10 | * @package PHPDaemon\Traits |
||
11 | * @author Vasily Zorin <[email protected]> |
||
12 | */ |
||
13 | trait Sessions |
||
14 | { |
||
15 | /** |
||
16 | * @var string Session ID |
||
17 | */ |
||
18 | protected $sessionId; |
||
19 | |||
20 | /** |
||
21 | * @var integer |
||
22 | */ |
||
23 | protected $sessionStartTimeout = 10; |
||
24 | |||
25 | /** |
||
26 | * @var boolean |
||
27 | */ |
||
28 | protected $sessionStarted = false; |
||
29 | |||
30 | /** |
||
31 | * @var boolean |
||
32 | */ |
||
33 | protected $sessionFlushing = false; |
||
34 | |||
35 | /** |
||
36 | * @var resource |
||
37 | */ |
||
38 | protected $sessionFp; |
||
39 | |||
40 | /** |
||
41 | * @var string |
||
42 | */ |
||
43 | protected $sessionPrefix = 'sess_'; |
||
44 | |||
45 | /** |
||
46 | * Is session started? |
||
47 | * @return boolean |
||
48 | */ |
||
49 | public function sessionStarted() |
||
50 | { |
||
51 | return $this->sessionStarted; |
||
52 | } |
||
53 | |||
54 | /** |
||
55 | * Deferred event 'onSessionStart' |
||
56 | * @return callable |
||
57 | */ |
||
58 | public function onSessionStartEvent() |
||
59 | { |
||
60 | return function ($sessionStartEvent) { |
||
61 | /** @var \PHPDaemon\Core\DeferredEvent $sessionStartEvent */ |
||
62 | $name = ini_get('session.name'); |
||
63 | $sid = $this->getCookieStr($name); |
||
0 ignored issues
–
show
|
|||
64 | if ($sid === '') { |
||
65 | $this->sessionStartNew(function ($success) use ($sessionStartEvent) { |
||
66 | $sessionStartEvent->setResult($success); |
||
67 | }); |
||
68 | return; |
||
69 | } |
||
70 | $this->onSessionRead(function ($session) use ($sessionStartEvent) { |
||
0 ignored issues
–
show
The method
onSessionRead() does not exist on PHPDaemon\Traits\Sessions . Did you maybe mean onSessionReadEvent() ?
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. ![]() |
|||
71 | if ($this->getSessionState() === null) { |
||
72 | $this->sessionStartNew(function ($success) use ($sessionStartEvent) { |
||
73 | $sessionStartEvent->setResult($success); |
||
74 | }); |
||
75 | return; |
||
76 | } |
||
77 | $sessionStartEvent->setResult(true); |
||
78 | }); |
||
79 | }; |
||
80 | } |
||
81 | |||
82 | /** |
||
83 | * Deferred event 'onSessionRead' |
||
84 | * @return callable |
||
85 | */ |
||
86 | public function onSessionReadEvent() |
||
87 | { |
||
88 | return function ($sessionEvent) { |
||
89 | /** @var \PHPDaemon\Core\DeferredEvent $sessionEvent */ |
||
90 | $name = ini_get('session.name'); |
||
91 | $sid = $this->getCookieStr($name); |
||
0 ignored issues
–
show
It seems like
getCookieStr() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
92 | if ($sid === '') { |
||
93 | $sessionEvent->setResult(false); |
||
94 | return; |
||
95 | } |
||
96 | if ($this->getSessionState() !== null) { |
||
97 | $sessionEvent->setResult(true); |
||
98 | return; |
||
99 | } |
||
100 | $this->sessionRead($sid, function ($data) use ($sessionEvent, $sid) { |
||
101 | $canDecode = $data !== false && $this->sessionDecode($data); |
||
102 | $sessionEvent->setResult($canDecode); |
||
103 | }); |
||
104 | }; |
||
105 | } |
||
106 | |||
107 | /** |
||
108 | * Reads session data |
||
109 | * @param string $sid Session ID |
||
110 | * @param callable $cb Callback |
||
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. ![]() |
|||
111 | * @return void |
||
112 | */ |
||
113 | public function sessionRead($sid, $cb = null) |
||
114 | { |
||
115 | FileSystem::open(FileSystem::genRndTempnamPrefix(session_save_path(), $this->sessionPrefix) . basename($sid), |
||
116 | 'r+!', function ($fp) use ($cb) { |
||
117 | if (!$fp) { |
||
118 | $cb(false); |
||
119 | return; |
||
120 | } |
||
121 | $fp->readAll(function ($fp, $data) use ($cb) { |
||
122 | $this->sessionFp = $fp; |
||
123 | $cb($data); |
||
124 | }); |
||
125 | }); |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * Commmit session data |
||
130 | * @param callable $cb Callback |
||
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. ![]() |
|||
131 | * @return void |
||
132 | */ |
||
133 | public function sessionCommit($cb = null) |
||
134 | { |
||
135 | if (!$this->sessionFp || $this->sessionFlushing) { |
||
136 | if ($cb) { |
||
137 | $cb(false); |
||
138 | } |
||
139 | return; |
||
140 | } |
||
141 | $this->sessionFlushing = true; |
||
142 | $data = $this->sessionEncode(); |
||
143 | $l = mb_orig_strlen($data); |
||
0 ignored issues
–
show
It seems like
$data defined by $this->sessionEncode() on line 142 can also be of type false ; however, mb_orig_strlen() does only seem to accept string , did you maybe forget to handle an error condition?
This check looks for type mismatches where the missing type is Consider the follow example <?php
function getDate($date)
{
if ($date !== null) {
return new DateTime($date);
}
return false;
}
This function either returns a new ![]() |
|||
144 | $cb = CallbackWrapper::wrap($cb); |
||
0 ignored issues
–
show
It seems like
$cb defined by \PHPDaemon\Core\CallbackWrapper::wrap($cb) on line 144 can also be of type null ; however, PHPDaemon\Core\CallbackWrapper::wrap() 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. ![]() |
|||
145 | $this->sessionFp->write($data, function ($file, $result) use ($l, $cb) { |
||
0 ignored issues
–
show
|
|||
146 | $file->truncate($l, function ($file, $result) use ($cb) { |
||
0 ignored issues
–
show
|
|||
147 | $this->sessionFlushing = false; |
||
148 | if ($cb) { |
||
149 | $cb(true); |
||
150 | } |
||
151 | }); |
||
152 | }); |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * Session start |
||
157 | * @param boolean $force_start |
||
158 | * @return void |
||
159 | */ |
||
160 | protected function sessionStart($force_start = true) |
||
0 ignored issues
–
show
|
|||
161 | { |
||
162 | if ($this->sessionStarted) { |
||
163 | return; |
||
164 | } |
||
165 | $this->sessionStarted = true; |
||
166 | if (!$this instanceof \PHPDaemon\HTTPRequest\Generic) { |
||
167 | Daemon::log('Called ' . get_class($this) . '(trait \PHPDaemon\Traits\Sessions)->sessionStart() outside of Request. You should use onSessionStart.'); |
||
168 | return; |
||
169 | } |
||
170 | $f = true; // hack to avoid a sort of "race condition" |
||
171 | $this->onSessionStart(function ($event) use (&$f) { |
||
0 ignored issues
–
show
The method
onSessionStart() does not exist on PHPDaemon\HTTPRequest\Generic . Did you maybe mean onSessionStartEvent() ?
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. ![]() |
|||
172 | $f = false; |
||
173 | $this->wakeup(); |
||
0 ignored issues
–
show
It seems like
wakeup() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
174 | }); |
||
175 | if ($f) { |
||
176 | $this->sleep($this->sessionStartTimeout); |
||
0 ignored issues
–
show
The property
$sessionStartTimeout is declared protected in PHPDaemon\Traits\Sessions . Since you implemented __get() , maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.
Since your code implements the magic setter <?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.");
}
}
}
Since the property has write access only, you can use the @property-write 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. ![]() |
|||
177 | } |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * Start new session |
||
182 | * @param callable $cb Callback |
||
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. ![]() |
|||
183 | * @return void |
||
184 | */ |
||
185 | protected function sessionStartNew($cb = null) |
||
186 | { |
||
187 | FileSystem::tempnam(session_save_path(), $this->sessionPrefix, function ($fp) use ($cb) { |
||
188 | if (!$fp) { |
||
189 | $cb(false); |
||
190 | return; |
||
191 | } |
||
192 | |||
193 | $this->sessionFp = $fp; |
||
194 | $this->sessionId = substr(basename($fp->path), mb_orig_strlen($this->sessionPrefix)); |
||
195 | $this->setcookie( |
||
0 ignored issues
–
show
It seems like
setcookie() must be provided by classes using this trait. How about adding it as abstract method to this trait?
This check looks for methods that are used by a trait but not required by it. To illustrate, let’s look at the following code example trait Idable {
public function equalIds(Idable $other) {
return $this->getId() === $other->getId();
}
}
The trait Adding the ![]() |
|||
196 | ini_get('session.name'), |
||
197 | $this->sessionId, |
||
198 | ini_get('session.cookie_lifetime'), |
||
199 | ini_get('session.cookie_path'), |
||
200 | ini_get('session.cookie_domain'), |
||
201 | ini_get('session.cookie_secure'), |
||
202 | ini_get('session.cookie_httponly') |
||
203 | ); |
||
204 | |||
205 | $cb(true); |
||
206 | }); |
||
207 | } |
||
208 | |||
209 | /** |
||
210 | * Encodes session data |
||
211 | * @return string|false |
||
212 | */ |
||
213 | protected function sessionEncode() |
||
214 | { |
||
215 | $type = ini_get('session.serialize_handler'); |
||
216 | if ($type === 'php') { |
||
217 | return $this->serializePHP($this->getSessionState()); |
||
218 | } |
||
219 | if ($type === 'php_binary') { |
||
220 | return igbinary_serialize($this->getSessionState()); |
||
221 | } |
||
222 | return false; |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * Set session state |
||
227 | * @param mixed $var |
||
228 | * @return void |
||
229 | */ |
||
230 | protected function setSessionState($var) |
||
231 | { |
||
232 | $this->attrs->session = $var; |
||
0 ignored issues
–
show
The property
attrs does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
233 | } |
||
234 | |||
235 | /** |
||
236 | * Get session state |
||
237 | * @return mixed |
||
238 | */ |
||
239 | protected function getSessionState() |
||
240 | { |
||
241 | return $this->attrs->session; |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * Decodes session data |
||
246 | * @param string $str Data |
||
247 | * @return boolean |
||
248 | */ |
||
249 | protected function sessionDecode($str) |
||
250 | { |
||
251 | $type = ini_get('session.serialize_handler'); |
||
252 | if ($type === 'php') { |
||
253 | $this->setSessionState($this->unserializePHP($str)); |
||
254 | return true; |
||
255 | } |
||
256 | if ($type === 'php_binary') { |
||
257 | $this->setSessionState(igbinary_unserialize($str)); |
||
258 | return true; |
||
259 | } |
||
260 | return false; |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * session_encode() - clone, which not require session_start() |
||
265 | * @see http://www.php.net/manual/en/function.session-encode.php |
||
266 | * @param array $array |
||
267 | * @return string |
||
268 | */ |
||
269 | public function serializePHP($array) |
||
270 | { |
||
271 | $raw = ''; |
||
272 | $line = 0; |
||
273 | $keys = array_keys($array); |
||
274 | |||
275 | foreach ($keys as $key) { |
||
276 | $value = $array[$key]; |
||
277 | $line++; |
||
278 | $raw .= $key . '|'; |
||
279 | if (is_array($value) && isset($value['huge_recursion_blocker_we_hope'])) { |
||
280 | $raw .= 'R:' . $value['huge_recursion_blocker_we_hope'] . ';'; |
||
281 | } else { |
||
282 | $raw .= serialize($value); |
||
283 | } |
||
284 | $array[$key] = array('huge_recursion_blocker_we_hope' => $line); |
||
285 | } |
||
286 | |||
287 | return $raw; |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * session_decode() - clone, which not require session_start() |
||
292 | * @see http://www.php.net/manual/en/function.session-decode.php#108037 |
||
293 | * @param string $session_data |
||
294 | * @return array |
||
295 | */ |
||
296 | protected function unserializePHP($session_data) |
||
297 | { |
||
298 | $return_data = array(); |
||
299 | $offset = 0; |
||
300 | |||
301 | while ($offset < mb_orig_strlen($session_data)) { |
||
302 | if (!strstr(substr($session_data, $offset), "|")) { |
||
303 | return $return_data; |
||
304 | //throw new \Exception("invalid session data, remaining: " . substr($session_data, $offset)); |
||
305 | } |
||
306 | $pos = mb_orig_strpos($session_data, "|", $offset); |
||
307 | $num = $pos - $offset; |
||
308 | $varname = substr($session_data, $offset, $num); |
||
309 | $offset += $num + 1; |
||
310 | $data = unserialize(substr($session_data, $offset)); |
||
311 | $return_data[$varname] = $data; |
||
312 | $offset += mb_orig_strlen(serialize($data)); |
||
313 | } |
||
314 | |||
315 | return $return_data; |
||
316 | } |
||
317 | } |
||
318 |
This check looks for methods that are used by a trait but not required by it.
To illustrate, let’s look at the following code example
The trait
Idable
provides a methodequalsId
that in turn relies on the methodgetId()
. If this method does not exist on a class mixing in this trait, the method will fail.Adding the
getId()
as an abstract method to the trait will make sure it is available.