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 | |||
3 | /** |
||
4 | * |
||
5 | * This file is part of the Apix Project. |
||
6 | * |
||
7 | * (c) Franck Cassedanne <franck at ouarz.net> |
||
8 | * |
||
9 | * @license http://opensource.org/licenses/BSD-3-Clause New BSD License |
||
10 | * |
||
11 | */ |
||
12 | |||
13 | namespace Apix; |
||
14 | |||
15 | class Request |
||
16 | { |
||
17 | const METHOD_OVERRIDE = '_method'; |
||
18 | |||
19 | /** |
||
20 | * Holds the URI string |
||
21 | * @var string |
||
22 | */ |
||
23 | protected $uri = null; |
||
24 | |||
25 | /** |
||
26 | * The HTTP response headers array |
||
27 | * @var array |
||
28 | */ |
||
29 | protected $headers = array(); |
||
30 | |||
31 | /** |
||
32 | * Hold the request body (raw) data |
||
33 | * @var string |
||
34 | */ |
||
35 | protected $body = null; |
||
36 | |||
37 | /** |
||
38 | * Holds the HTTP method |
||
39 | * @var string |
||
40 | */ |
||
41 | protected $method = null; |
||
42 | |||
43 | /** |
||
44 | * Body stream scheme |
||
45 | * @var string |
||
46 | */ |
||
47 | protected $bodyStream = 'php://input'; |
||
48 | |||
49 | /** |
||
50 | * Constructor, at instanciation sets the minimum request properties |
||
51 | */ |
||
52 | public function __construct() |
||
53 | { |
||
54 | $this->setHeaders(); |
||
55 | $this->setParams(); |
||
56 | $this->setBody(); |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * Sets and parse the provided URI, or if missing guess from the enviroment |
||
61 | * |
||
62 | * @param string|false $uri If false, extract one from $_SERVER variables |
||
63 | */ |
||
64 | public function setUri($uri=false) |
||
65 | { |
||
66 | $uri = false === $uri ? $this->getRequestedUri() : $uri; |
||
67 | $uri = parse_url($uri, PHP_URL_PATH); |
||
68 | |||
69 | // remove a trailing slash |
||
70 | if ( $uri != '/' && substr($uri, -1) == '/' ) { |
||
71 | $uri = substr($uri, 0, -1); |
||
72 | } |
||
73 | |||
74 | $this->uri = $uri; |
||
0 ignored issues
–
show
|
|||
75 | } |
||
76 | |||
77 | /** |
||
78 | * Gets the current URI, if undefined guess and set one up. |
||
79 | * |
||
80 | * @return string |
||
81 | */ |
||
82 | public function getUri() |
||
83 | { |
||
84 | if (null === $this->uri) { |
||
85 | $this->setUri(); |
||
86 | } |
||
87 | |||
88 | return $this->uri; |
||
89 | } |
||
90 | |||
91 | /** |
||
92 | * Gets the requested URI (from client, spoofable). |
||
93 | * |
||
94 | * @return string |
||
95 | */ |
||
96 | public function getRequestedUri() |
||
0 ignored issues
–
show
getRequestedUri uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
97 | { |
||
98 | if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { |
||
99 | $uri = $_SERVER['HTTP_X_REWRITE_URL']; |
||
100 | } elseif (isset($_SERVER['IIS_WasUrlRewritten']) |
||
101 | && $_SERVER['IIS_WasUrlRewritten'] == '1' |
||
102 | && isset($_SERVER['UNENCODED_URL']) |
||
103 | && $_SERVER['UNENCODED_URL'] != '' |
||
104 | ) { |
||
105 | $uri = $_SERVER['UNENCODED_URL']; |
||
106 | } elseif (isset($_SERVER['REQUEST_URI'])) { |
||
107 | $uri = $_SERVER['REQUEST_URI']; |
||
108 | } elseif (isset($_SERVER['PATH_INFO'])) { |
||
109 | $uri = $_SERVER['PATH_INFO']; |
||
110 | } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { |
||
111 | $uri = $_SERVER['ORIG_PATH_INFO']; |
||
112 | } |
||
113 | |||
114 | return isset($uri) ? $uri : '/'; |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * Gets the requested Scheme (from server). |
||
119 | * |
||
120 | * @return string |
||
121 | */ |
||
122 | public function getRequestedScheme() |
||
0 ignored issues
–
show
getRequestedScheme uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
123 | { |
||
124 | return isset($_SERVER['HTTPS']) ? 'https' : 'http'; |
||
125 | } |
||
126 | |||
127 | /** |
||
128 | * Gets the requested host (from client, spoofable). |
||
129 | * |
||
130 | * @return string |
||
131 | */ |
||
132 | public function getRequestedHost() |
||
0 ignored issues
–
show
getRequestedHost uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
133 | { |
||
134 | $s = $_SERVER; |
||
135 | $host = ''; |
||
136 | if ( !empty($s['HTTP_X_FORWARDED_HOST']) ) { |
||
137 | $host = $s['HTTP_X_FORWARDED_HOST']; |
||
138 | // handles multiple forwarders. |
||
139 | if (strpos($host, ',') !== false) { |
||
140 | $host = trim(array_pop( explode(',', $host) )); |
||
0 ignored issues
–
show
|
|||
141 | } |
||
142 | } elseif ( !empty($s['HTTP_HOST']) ) { |
||
143 | $host = $s['HTTP_HOST']; |
||
144 | } elseif ( !empty($s['SERVER_NAME']) ) { |
||
145 | $host = $s['SERVER_NAME']; |
||
146 | $host .= !empty($s['SERVER_PORT']) |
||
147 | ? ':' . $s['SERVER_PORT'] |
||
148 | : ''; |
||
149 | } |
||
150 | |||
151 | return rtrim($host, '/'); |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * Gets the request Url. |
||
156 | * |
||
157 | * @return string |
||
158 | */ |
||
159 | public function getRequestedUrl() |
||
160 | { |
||
161 | // TODO here |
||
162 | echo $this->getRequestedHost(); |
||
163 | if($host = $this->getRequestedHost() ) { |
||
164 | $host = $this->getRequestedScheme() . '://' . $host; |
||
165 | } |
||
166 | return $host . $this->getRequestedUri(); |
||
167 | |||
168 | // return 'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
58% 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. ![]() |
|||
169 | // . $this->getRequestedHost() |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
50% 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. ![]() |
|||
170 | // . $this->getRequestedUri(); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
56% 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. ![]() |
|||
171 | } |
||
172 | |||
173 | /** |
||
174 | * Sets a parameter by name |
||
175 | * |
||
176 | * @param string $key The key |
||
177 | * @param mixed $value The value |
||
178 | */ |
||
179 | public function setParam($key, $value) |
||
180 | { |
||
181 | $this->params[$key] = $value; |
||
0 ignored issues
–
show
The property
params 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;
![]() |
|||
182 | } |
||
183 | |||
184 | /** |
||
185 | * Gets a specified param |
||
186 | * |
||
187 | * @param string $key |
||
188 | * @param boolean $raw Set to true to get the raw URL encoded value |
||
189 | * @param string $filter POSIX character classes e.g. alnum, alpha |
||
190 | * @return mixed |
||
191 | */ |
||
192 | public function getParam($key, $raw=false, $filter=null) |
||
193 | { |
||
194 | if (isset($this->params[$key])) { |
||
195 | |||
196 | $param = $raw===false ? rawurldecode($this->params[$key]) |
||
197 | : $this->params[$key]; |
||
198 | |||
199 | if (null !== $filter) { |
||
200 | return preg_replace('/[^[:' . $filter . ':]]/', '', $param); |
||
201 | } |
||
202 | |||
203 | return $param; |
||
204 | } |
||
205 | } |
||
206 | |||
207 | /** |
||
208 | * Sets all parameters |
||
209 | * |
||
210 | * @param array|null $params |
||
211 | */ |
||
212 | public function setParams(array $params = null) |
||
0 ignored issues
–
show
setParams uses the super-global variable $_REQUEST which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
213 | { |
||
214 | $this->params = null === $params ? $_REQUEST : $params; |
||
215 | } |
||
216 | |||
217 | /** |
||
218 | * Returns all the request parameters |
||
219 | * |
||
220 | * @return array |
||
221 | */ |
||
222 | public function getParams() |
||
223 | { |
||
224 | return $this->params; |
||
225 | } |
||
226 | |||
227 | /** |
||
228 | * Sets the request method either using: |
||
229 | * - the passed method value, |
||
230 | * - or from an override value: |
||
231 | * - X-HTTP-Method-Override, |
||
232 | * - a GET param override, |
||
233 | * - server env or use the default value. |
||
234 | * |
||
235 | * @param string $method |
||
236 | * @param string $default |
||
237 | */ |
||
238 | public function setMethod($method = null, $default = 'GET') |
||
0 ignored issues
–
show
setMethod uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
239 | { |
||
240 | if (null === $method) { |
||
241 | if ($this->hasHeader('X-HTTP-Method-Override')) { |
||
242 | $method = $this->getHeader('X-HTTP-Method-Override'); |
||
243 | } elseif ($this->getParam(self::METHOD_OVERRIDE)) { |
||
244 | $method = $this->getParam(self::METHOD_OVERRIDE); |
||
245 | } else { |
||
246 | $method = isset($_SERVER['REQUEST_METHOD']) |
||
247 | ? $_SERVER['REQUEST_METHOD'] |
||
248 | : $default; |
||
249 | } |
||
250 | } |
||
251 | $this->method = strtoupper($method); |
||
252 | } |
||
253 | |||
254 | /** |
||
255 | * Returns the current requet method |
||
256 | * |
||
257 | * @param string |
||
258 | */ |
||
259 | public function getMethod() |
||
260 | { |
||
261 | if (null === $this->method) { |
||
262 | $this->setMethod(); |
||
263 | } |
||
264 | |||
265 | return $this->method; |
||
266 | } |
||
267 | |||
268 | /** |
||
269 | * Sets a request header by name |
||
270 | * |
||
271 | * @param string $name |
||
272 | * @param string $value |
||
273 | */ |
||
274 | public function setHeader($name, $value) |
||
275 | { |
||
276 | $this->headers[strtoupper($name)] = $value; |
||
277 | } |
||
278 | |||
279 | /** |
||
280 | * Checks if specified header exists |
||
281 | * |
||
282 | * @param string $name |
||
283 | * @return boolean |
||
284 | */ |
||
285 | public function hasHeader($name) |
||
286 | { |
||
287 | return isset($this->headers[strtoupper($name)]); |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * Returns the specified header |
||
292 | * |
||
293 | * @param string $name |
||
294 | * @return string |
||
295 | */ |
||
296 | public function getHeader($name) |
||
297 | { |
||
298 | $name = strtoupper($name); |
||
299 | if (isset($this->headers[$name])) { |
||
300 | return $this->headers[$name]; |
||
301 | } |
||
302 | } |
||
303 | |||
304 | /** |
||
305 | * Populates the headers properties |
||
306 | * Will use the provided associative array or extract things from $_SERVER |
||
307 | * |
||
308 | * @param array $headers The value |
||
309 | */ |
||
310 | public function setHeaders(array $headers = null) |
||
0 ignored issues
–
show
setHeaders uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
311 | { |
||
312 | if (null === $headers) { |
||
313 | #$headers = http_get_request_headers(); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
50% 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. ![]() |
|||
314 | $headers = $_SERVER; |
||
315 | } |
||
316 | $this->headers = $headers; |
||
317 | // $this->headers = array_change_key_case($headers); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
50% 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. ![]() |
|||
318 | } |
||
319 | |||
320 | /** |
||
321 | * Returns all the headers |
||
322 | * |
||
323 | * @return array |
||
324 | */ |
||
325 | public function getHeaders() |
||
326 | { |
||
327 | return $this->headers; |
||
328 | } |
||
329 | |||
330 | /** |
||
331 | * Returns the client's IP address |
||
332 | * |
||
333 | * @return string |
||
334 | */ |
||
335 | public function getIp() |
||
336 | { |
||
337 | $ip = $this->getHeader('HTTP_CLIENT_IP'); |
||
338 | if (empty($ip)) { |
||
339 | $ip = $this->getHeader('HTTP_X_FORWARDED_FOR'); |
||
340 | } |
||
341 | |||
342 | return empty($ip) ? $this->getHeader('REMOTE_ADDR') : $ip; |
||
343 | } |
||
344 | |||
345 | /** |
||
346 | * Sets the body stream property |
||
347 | * |
||
348 | * @param string $string |
||
349 | */ |
||
350 | public function setBodyStream($string) |
||
351 | { |
||
352 | $this->bodyStream = $string; |
||
353 | } |
||
354 | |||
355 | /** |
||
356 | * Sets the body using the provided string or retrieve it from a PHP stream |
||
357 | * |
||
358 | * @param string $body |
||
359 | */ |
||
360 | public function setBody($body = null) |
||
361 | { |
||
362 | $this->body = null === $body |
||
363 | ? file_get_contents($this->bodyStream) |
||
364 | : $body; |
||
365 | } |
||
366 | |||
367 | /** |
||
368 | * Checks wether the body contains data |
||
369 | * |
||
370 | * @return boolean |
||
371 | */ |
||
372 | public function hasBody() |
||
373 | { |
||
374 | return !empty($this->body); |
||
375 | } |
||
376 | |||
377 | /** |
||
378 | * Returns the raw (undecoded) body data |
||
379 | * |
||
380 | * @return string |
||
381 | */ |
||
382 | public function getRawBody() |
||
383 | { |
||
384 | return $this->body; |
||
385 | #return = http_get_request_body(); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
50% 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. ![]() |
|||
386 | #return file_get_contents($this->bodyStream); |
||
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. ![]() |
|||
387 | } |
||
388 | |||
389 | /** |
||
390 | * Returns the (decoded) body data of a request |
||
391 | * |
||
392 | * @param boolean $cache Wether to cache the body after decoding. |
||
393 | * @return string |
||
394 | * @throws \BadFunctionCallException |
||
395 | */ |
||
396 | public function getBody($cache=true) |
||
397 | { |
||
398 | static $body = null; |
||
399 | if ($cache && null !== $body) { |
||
400 | return $body; |
||
401 | } |
||
402 | |||
403 | // Decode any content-encoding (gzip or deflate) if needed |
||
404 | switch (strtolower($this->getHeader('content-encoding'))) { |
||
405 | // Handle gzip encoding |
||
406 | case 'gzip': |
||
407 | $body = $this->gzDecode($this->body); |
||
408 | break; |
||
409 | |||
410 | // Handle deflate encoding |
||
411 | case 'deflate': |
||
412 | $body = $this->gzInflate($this->body); |
||
413 | break; |
||
414 | |||
415 | default: |
||
416 | return $this->body; |
||
417 | } |
||
418 | |||
419 | return $body; |
||
420 | } |
||
421 | |||
422 | /** |
||
423 | * Handles gzip decoding |
||
424 | * |
||
425 | * @param boolean $cache Wether to cache the body after decoding. |
||
0 ignored issues
–
show
There is no parameter named
$cache . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
426 | * @return string |
||
427 | * @throws \BadFunctionCallException |
||
428 | * @codeCoverageIgnore |
||
429 | */ |
||
430 | public function gzDecode($data) |
||
431 | { |
||
432 | return function_exists('gzdecode') |
||
433 | ? gzdecode($data) |
||
434 | : file_get_contents( |
||
435 | 'compress.zlib://data:;base64,' |
||
436 | . base64_encode($data) |
||
437 | ); |
||
438 | } |
||
439 | |||
440 | /** |
||
441 | * Handles inflating a deflated string |
||
442 | * |
||
443 | * @param string $data |
||
444 | * @return string |
||
445 | * @throws \BadFunctionCallException |
||
446 | * @codeCoverageIgnore |
||
447 | */ |
||
448 | public function gzInflate($data) |
||
449 | { |
||
450 | |||
451 | if (! function_exists('gzinflate')) { |
||
452 | throw new \BadFunctionCallException( |
||
453 | 'zlib extension is required to deflate this' |
||
454 | ); |
||
455 | } |
||
456 | |||
457 | return gzinflate($data); |
||
458 | } |
||
459 | |||
460 | } |
||
461 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.