Issues (1)

Security Analysis    no request data  

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.

src/Weew/Router/Router.php (1 issue)

Severity

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
3
namespace Weew\Router;
4
5
use Exception;
6
use Weew\Http\HttpRequestMethod;
7
use Weew\Router\Exceptions\FilterException;
8
use Weew\Url\IUrl;
9
10
class Router implements IRouter {
11
    /**
12
     * @var Router[]
13
     */
14
    protected $nestedRouters = [];
15
16
    /**
17
     * @var IRoute[]
18
     */
19
    protected $routes = [];
20
21
    /**
22
     * @var IRoutesMatcher
23
     */
24
    protected $matcher;
25
26
    /**
27
     * @var string
28
     */
29
    protected $prefix;
30
31
    /**
32
     * @var string
33
     */
34
    protected $controller;
35
36
    /**
37
     * @var ICallableInvoker
38
     */
39
    protected $callableInvoker;
40
41
    /**
42
     * @param IRoutesMatcher $matcher
43
     * @param ICallableInvoker $callableInvoker
44
     */
45
    public function __construct(
46
        IRoutesMatcher $matcher = null,
47
        ICallableInvoker $callableInvoker = null
48
    ) {
49
        if ( ! $matcher instanceof IRoutesMatcher) {
50
            $matcher = $this->createRoutesMatcher();
51
        }
52
53
        if ( ! $callableInvoker instanceof ICallableInvoker) {
54
            $callableInvoker = $this->createCallableInvoker();
55
        }
56
57
        $this->setRoutesMatcher($matcher);
58
        $this->setCallableInvoker($callableInvoker);
59
    }
60
61
    /**
62
     * @param $method
63
     * @param IUrl $url
64
     *
65
     * @return null|IRoute
66
     */
67
    public function match($method, IUrl $url) {
68
        $exceptions = [];
69
        $route = $this->matchRouter($method, $url, $exceptions);
70
71
        if ($route === null && count($exceptions) > 0) {
72
            $exception = array_pop($exceptions);
73
            throw $exception->getOriginalException();
74
        }
75
76
        return $route;
77
    }
78
79
    /**
80
     * @return string
81
     */
82
    public function getController() {
83
        return $this->controller;
84
    }
85
86
    /**
87
     * @param $class
88
     * @param bool $nest
89
     *
90
     * @return IRouter
91
     */
92
    public function setController($class, $nest = true) {
93
        if ($nest) {
94
            $router = $this->createNestedRouter();
95
            $router->setController($class, false);
96
97
            return $router;
98
        }
99
100
        $this->controller = $class;
101
102
        return $this;
103
    }
104
105
    /**
106
     * @return IRouter
107
     */
108
    public function removeController() {
109
        $this->controller = null;
110
111
        return $this;
112
    }
113
114
    /**
115
     * @param $path
116
     * @param $abstract
117
     *
118
     * @return $this
119
     * @throws Exception
120
     */
121
    public function get($path, $abstract) {
122
        return $this->route(HttpRequestMethod::GET, $path, $abstract);
123
    }
124
125
    /**
126
     * @param $path
127
     * @param $abstract
128
     *
129
     * @return $this
130
     * @throws Exception
131
     */
132
    public function post($path, $abstract) {
133
        return $this->route(HttpRequestMethod::POST, $path, $abstract);
134
    }
135
136
    /**
137
     * @param $path
138
     * @param $abstract
139
     *
140
     * @return $this
141
     * @throws Exception
142
     */
143
    public function put($path, $abstract) {
144
        return $this->route(HttpRequestMethod::PUT, $path, $abstract);
145
    }
146
147
    /**
148
     * @param $path
149
     * @param $abstract
150
     *
151
     * @return $this
152
     * @throws Exception
153
     */
154
    public function update($path, $abstract) {
155
        return $this->route(HttpRequestMethod::UPDATE, $path, $abstract);
156
    }
157
158
    /**
159
     * @param $path
160
     * @param $abstract
161
     *
162
     * @return $this
163
     * @throws Exception
164
     */
165
    public function patch($path, $abstract) {
166
        return $this->route(HttpRequestMethod::PATCH, $path, $abstract);
167
    }
168
169
    /**
170
     * @param $path
171
     * @param $abstract
172
     *
173
     * @return $this
174
     * @throws Exception
175
     */
176
    public function delete($path, $abstract) {
177
        return $this->route(HttpRequestMethod::DELETE, $path, $abstract);
178
    }
179
180
    /**
181
     * @param $path
182
     * @param $abstract
183
     *
184
     * @return $this
185
     * @throws Exception
186
     */
187
    public function options($path, $abstract) {
188
        return $this->route(HttpRequestMethod::OPTIONS, $path, $abstract);
189
    }
190
191
    /**
192
     * @param $path
193
     * @param $abstract
194
     *
195
     * @return Router
196
     */
197
    public function head($path, $abstract) {
198
        return $this->route(HttpRequestMethod::HEAD, $path, $abstract);
199
    }
200
201
    /**
202
     * @param $path
203
     * @param $abstract
204
     *
205
     * @return Router
206
     */
207
    public function any($path, $abstract) {
208
        return $this->createRoute([
209
            HttpRequestMethod::GET,
210
            HttpRequestMethod::POST,
211
            HttpRequestMethod::PUT,
212
            HttpRequestMethod::PATCH,
213
            HttpRequestMethod::UPDATE,
214
            HttpRequestMethod::DELETE,
215
        ], $path, $abstract);
216
    }
217
218
    /**
219
     * @param $method
220
     * @param $path
221
     * @param $abstract
222
     *
223
     * @return Router
224
     */
225
    public function route($method, $path, $abstract) {
226
        return $this->createRoute($method, $path, $abstract);
227
    }
228
229
230
    /**
231
     * @param callable $callable
232
     *
233
     * @return IRouter
234
     */
235
    public function group(callable $callable = null) {
236
        $router = $this->createNestedRouter();
237
238
        if ($callable !== null) {
239
            $this->invokeCallable($callable, $router);
240
        }
241
242
        return $router;
243
    }
244
245
    /**
246
     * @param $name
247
     * @param $pattern
248
     *
249
     * @return $this
250
     */
251
    public function addPattern($name, $pattern) {
252
        $this->getRoutesMatcher()->addPattern($name, $pattern);
253
254
        return $this;
255
    }
256
257
    /**
258
     * @param $name
259
     * @param $callable
260
     *
261
     * @return $this
262
     */
263
    public function addFilter($name, $callable) {
264
        $filter = new RouteFilter($name, $callable);
265
        $this->getRoutesMatcher()->getFiltersMatcher()
266
            ->addFilter($filter);
267
268
        return $this;
269
    }
270
271
    /**
272
     * @param $name
273
     *
274
     * @return $this
275
     */
276
    public function enableFilter($name) {
277
        if ( ! is_array($name)) {
278
            $name = [$name];
279
        }
280
281
        $this->getRoutesMatcher()->getFiltersMatcher()
282
            ->enableFilters($name);
283
284
        return $this;
285
    }
286
287
    /**
288
     * @param $name
289
     * @param callable $callable
290
     *
291
     * @return $this
292
     */
293
    public function addResolver($name, $callable) {
294
        $resolver = new RouteResolver($name, $callable);
295
        $this->getRoutesMatcher()->getParameterResolver()
296
            ->addResolver($resolver);
297
298
        return $this;
299
    }
300
301
    /**
302
     * @return string
303
     */
304
    public function getPrefix() {
305
        return $this->prefix;
306
    }
307
308
    /**
309
     * @param $prefix
310
     *
311
     * @return $this
312
     */
313
    public function setPrefix($prefix) {
314
        $this->prefix = $prefix;
315
316
        return $this;
317
    }
318
319
    /**
320
     * @param $prefix
321
     *
322
     * @return $this
323
     */
324
    public function addPrefix($prefix) {
325
        if ($this->getPrefix() !== null) {
326
            $this->setPrefix(url($this->getPrefix(), $prefix));
327
        } else {
328
            $this->setPrefix($prefix);
329
        }
330
331
        return $this;
332
    }
333
334
    /**
335
     * @param $protocol
336
     *
337
     * @return $this
338
     */
339
    public function restrictProtocol($protocol) {
340
        if ( ! is_array($protocol)) {
341
            $protocol = [$protocol];
342
        }
343
344
        $this->getRoutesMatcher()->getRestrictionsMatcher()
345
            ->setProtocols($protocol);
346
347
        return $this;
348
    }
349
350
    /**
351
     * @param $tld
352
     *
353
     * @return $this
354
     */
355
    public function restrictTLD($tld) {
356
        if ( ! is_array($tld)) {
357
            $tld = [$tld];
358
        }
359
360
        $this->getRoutesMatcher()->getRestrictionsMatcher()
361
            ->setTLDs($tld);
362
363
        return $this;
364
    }
365
366
    /**
367
     * @param $domain
368
     *
369
     * @return $this
370
     */
371
    public function restrictDomain($domain) {
372
        if ( ! is_array($domain)) {
373
            $domain = [$domain];
374
        }
375
376
        $this->getRoutesMatcher()->getRestrictionsMatcher()
377
            ->setDomains($domain);
378
379
        return $this;
380
    }
381
382
    /**
383
     * @param $subdomain
384
     *
385
     * @return $this
386
     */
387
    public function restrictSubdomain($subdomain) {
388
        if ( ! is_array($subdomain)) {
389
            $subdomain = [$subdomain];
390
        }
391
392
        $this->getRoutesMatcher()->getRestrictionsMatcher()
393
            ->setSubdomains($subdomain);
394
395
        return $this;
396
    }
397
398
    /**
399
     * @param $host
400
     *
401
     * @return $this
402
     */
403
    public function restrictHost($host) {
404
        if ( ! is_array($host)) {
405
            $host = [$host];
406
        }
407
408
        $this->getRoutesMatcher()->getRestrictionsMatcher()
409
            ->setHosts($host);
410
411
        return $this;
412
    }
413
414
    /**
415
     * @return IRoute[]
416
     */
417
    public function getRoutes() {
418
        return $this->routes;
419
    }
420
421
    /**
422
     * @param IRoute[] $routes
423
     */
424
    public function setRoutes(array $routes) {
425
        $this->routes = $routes;
426
    }
427
428
    /**
429
     * @return IRoutesMatcher
430
     */
431
    public function getRoutesMatcher() {
432
        return $this->matcher;
433
    }
434
435
    /**
436
     * @param IRoutesMatcher $matcher
437
     */
438
    public function setRoutesMatcher(IRoutesMatcher $matcher) {
439
        $this->matcher = $matcher;
440
    }
441
442
    /**
443
     * @return Router
444
     */
445
    public function createNestedRouter() {
446
        $router = $this->createRouter();
447
        $router->setPrefix($this->getPrefix());
448
        $router->setController($this->controller, false);
449
        $router->setRoutesMatcher(clone $router->getRoutesMatcher());
450
        $this->addNestedRouter($router);
451
452
        return $router;
453
    }
454
455
    /**
456
     * @return IRouter[]
457
     */
458
    public function getNestedRouters() {
459
        return $this->nestedRouters;
460
    }
461
462
    /**
463
     * @return ICallableInvoker
464
     */
465
    public function getCallableInvoker() {
466
        return $this->callableInvoker;
467
    }
468
469
    /**
470
     * @param ICallableInvoker $callableInvoker
471
     */
472
    public function setCallableInvoker(ICallableInvoker $callableInvoker) {
473
        $this->callableInvoker = $callableInvoker;
474
    }
475
476
    /**
477
     * @param $method
478
     * @param IUrl $url
479
     * @param array $exceptions
480
     * @param IRoute|null $route
481
     *
482
     * @return null|IRoute
483
     */
484
    public function matchRouter(
485
        $method,
486
        IUrl $url,
487
        array &$exceptions,
488
        IRoute $route = null
0 ignored issues
show
The parameter $route 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...
489
    ) {
490
        try {
491
            $route = $this->getRoutesMatcher()
492
                ->match($this->getRoutes(), $method, $url);
493
        } catch (FilterException $ex) {
494
            $exceptions[] = $ex;
495
        }
496
497
        if ($route === null) {
498
            $route = $this->matchNestedRouters(
499
                $method, $url, $exceptions, $route
500
            );
501
        }
502
503
        return $route;
504
    }
505
506
    /**
507
     * @param $method
508
     * @param IUrl $url
509
     * @param array $exceptions
510
     * @param IRoute|null $route
511
     *
512
     * @return null|IRoute
513
     */
514
    protected function matchNestedRouters(
515
        $method,
516
        IUrl $url,
517
        array &$exceptions,
518
        IRoute $route = null
519
    ) {
520
        foreach ($this->getNestedRouters() as $router) {
521
            $match = $router->matchRouter($method, $url, $exceptions, $route);
522
523
            if ($match !== null) {
524
                $route = $match;
525
                break;
526
            }
527
        }
528
529
        return $route;
530
    }
531
532
    /**
533
     * @return RoutesMatcher
534
     */
535
    protected function createRoutesMatcher() {
536
        return new RoutesMatcher();
537
    }
538
539
    /**
540
     * @param $method
541
     * @param $path
542
     * @param $abstract
543
     *
544
     * @return $this
545
     * @throws Exception
546
     */
547
    protected function createRoute($method, $path, $abstract) {
548
        if ($this->getPrefix() !== null) {
549
            $path = url($this->getPrefix(), $path);
550
        }
551
552
        if ( ! is_array($method)) {
553
            $method = [$method];
554
        }
555
556
        $handler = $this->createHandler($abstract);
557
        $route = new Route($method, $path, $handler);
558
        $this->routes[] = $route;
559
560
        return $this;
561
    }
562
563
    /**
564
     * @param $abstract
565
     *
566
     * @return array
567
     */
568
    protected function createHandler($abstract) {
569
        $controller = $this->getController();
570
571
        if ($controller !== null &&
572
            is_string($abstract)) {
573
            $abstract = [$controller, $abstract];
574
        }
575
576
        return $abstract;
577
    }
578
579
    /**
580
     * @return Router
581
     */
582
    protected function createRouter() {
583
        return new Router($this->getRoutesMatcher());
584
    }
585
586
    /**
587
     * @param IRouter $router
588
     */
589
    protected function addNestedRouter(IRouter $router) {
590
        $this->nestedRouters[] = $router;
591
    }
592
593
    /**
594
     * @param callable $callable
595
     * @param IRouter $router
596
     */
597
    protected function invokeCallable(callable $callable, IRouter $router) {
598
        $this->getCallableInvoker()->invoke($callable, $router);
599
    }
600
601
    /**
602
     * @return CallableInvoker
603
     */
604
    protected function createCallableInvoker() {
605
        return new CallableInvoker();
606
    }
607
}
608