Issues (6)

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/Route.php (1 issue)

Labels
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
/**
4
 * Codeburner Framework.
5
 *
6
 * @author Alex Rohleder <[email protected]>
7
 * @copyright 2016 Alex Rohleder
8
 * @license http://opensource.org/licenses/MIT
9
 */
10
11
namespace Codeburner\Router;
12
13
use Codeburner\Router\Exceptions\BadRouteException;
14
use Codeburner\Router\Strategies\MatcherAwareInterface;
15
use Codeburner\Router\Strategies\StrategyInterface;
16
17
/**
18
 * Route representation, a route must be able to chang and execute itself.
19
 *
20
 * @author Alex Rohleder <[email protected]>
21
 */
22
23
class Route
24
{
25
26
    /**
27
     * @var Collector
28
     */
29
30
    protected $collector;
31
32
    /**
33
     * @var string
34
     */
35
36
    protected $method;
37
38
    /**
39
     * @var string
40
     */
41
42
    protected $pattern;
43
44
    /**
45
     * @var callable
46
     */
47
48
    protected $action;
49
50
    /**
51
     * @var string
52
     */
53
54
    protected $namespace = "";
55
56
    /**
57
     * @var string[]
58
     */
59
60
    protected $params = [];
61
62
    /**
63
     * Defaults are parameters set by the user, and don't
64
     * appear on the pattern.
65
     *
66
     * @var array
67
     */
68
69
    protected $defaults = [];
70
71
    /**
72
     * Metadata can be set to be used on filters, dispatch strategies
73
     * or anywhere the route object is used.
74
     *
75
     * @var array
76
     */
77
78
    protected $metadata = [];
79
80
    /**
81
     * @var string|StrategyInterface
82
     */
83
84
    protected $strategy;
85
86
    /**
87
     * Blocked routes are dynamic routes selected to pass by the matcher.
88
     *
89
     * @var boolean
90
     */
91
92
    protected $blocked = false;
93
94
    /**
95
     * The matcher that dispatched this route.
96
     *
97
     * @var Matcher $matcher
98
     */
99
100
    protected $matcher;
101
102
    /**
103
     * The function used to create controllers from name.
104
     *
105
     * @var callable
106
     */
107
108
    protected $controllerCreationFunction;
109
110
    /**
111
     * @param Collector $collector
112
     * @param string $method
113
     * @param string $pattern
114
     * @param callable $action
115
     */
116
117 53
    public function __construct(Collector $collector, $method, $pattern, $action)
118
    {
119 53
        $this->collector = $collector;
120 53
        $this->method    = $method;
121 53
        $this->pattern   = $pattern;
122 53
        $this->action    = $action;
123 53
    }
124
125
    /**
126
     * Clone this route and set it into the collector.
127
     *
128
     * @return Route
129
     */
130
131 4
    public function reset()
132
    {
133 4
        return $this->collector->set($this->method, $this->pattern, $this->action)->nth(0)
134 4
                               ->setStrategy($this->strategy)->setParams($this->params)
135 4
                               ->setDefaults($this->defaults)->setMetadataArray($this->metadata);
136
    }
137
138
    /**
139
     * Remove this route from the collector.
140
     *
141
     * @return self
142
     */
143
144 6
    public function forget()
145
    {
146 6
        $this->collector->forget($this->method, $this->pattern);
147 6
        return $this;
148
    }
149
150
    /**
151
     * Execute the route action, if no strategy was provided the action
152
     * will be executed by the call_user_func PHP function.
153
     *
154
     * @param callable $container
155
     * @throws BadRouteException
156
     * @return mixed
157
     */
158
159 19
    public function call(callable $container = null)
160
    {
161 19
        $this->action = $this->buildCallable($this->action, $container);
162
163 19
        if ($this->strategy === null) {
164 10
            return call_user_func_array($this->action, array_merge($this->defaults, $this->params));
165
        }
166
167 9
        if (!is_object($this->strategy)) {
168 2
            if ($container === null) {
169 2
                   $this->strategy = new $this->strategy;
170 2
            } else $this->strategy = $container($this->strategy);
171 2
        }
172
173 9
        return $this->callWithStrategy();
174
    }
175
176
    /**
177
     * Seek for dynamic content in one callable. This allow to use parameters defined on pattern on callable
178
     * definition, eg. "get" "/{resource:string+}/{slug:slug+}" "{resource}::find".
179
     *
180
     * This will snakecase the resource parameter and deal with as a controller, then call the find method.
181
     * A request for "/articles/my-first-article" will execute find method of Articles controller with only
182
     * "my-first-article" as parameter.
183
     *
184
     * @param callable $callable
185
     * @param callable $container
186
     *
187
     * @return callable
188
     */
189
190 19
    private function buildCallable($callable, $container = null)
191
    {
192 19
        if (is_string($callable) && strpos($callable, "::")) {
193 13
            $callable = explode("::", $callable);
194 13
        }
195
196 19
        if (is_array($callable)) {
197 13
            if (is_string($callable[0])) {
198 13
                   $callable[0] = $this->parseCallableController($callable[0], $container);
0 ignored issues
show
It seems like $container defined by parameter $container on line 190 can also be of type null; however, Codeburner\Router\Route::parseCallableController() does only seem to accept callable, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
199 13
            }
200
201 13
            $callable[1] = $this->parseCallablePlaceholders($callable[1]);
202 13
        }
203
204 19
        return $callable;
205
    }
206
207
    /**
208
     * Get the controller object.
209
     *
210
     * @param string $controller
211
     * @param callable $container
212
     *
213
     * @return Object
214
     */
215
216 13
    private function parseCallableController($controller, $container)
217
    {
218 13
        $controller  = rtrim($this->namespace, "\\") . "\\" . $this->parseCallablePlaceholders($controller);
219
220 13
        if ($container === null) {
221 12
               return new $controller;
222 1
        } else return $container($controller);
223
    }
224
225
    /**
226
     * Parse and replace dynamic content on route action.
227
     *
228
     * @param string $fragment Part of callable
229
     * @return string
230
     */
231
232 13
    private function parseCallablePlaceholders($fragment)
233
    {
234 13
        if (strpos($fragment, "{") !== false) {
235 1
            foreach ($this->params as $placeholder => $value) {
236 1
                if (strpos($fragment, "{" . $placeholder . "}") !== false) {
237 1
                    $fragment = str_replace("{" . $placeholder . "}", ucwords(str_replace("-", " ", $value)), $fragment);
238 1
                }
239 1
            }
240 1
        }
241
242 13
        return $fragment;
243
    }
244
245
    /**
246
     * Execute the route action with the given strategy.
247
     *
248
     * @throws BadRouteException
249
     * @return mixed
250
     */
251
252 9
    private function callWithStrategy()
253
    {
254 9
        if ($this->strategy instanceof StrategyInterface) {
255 8
            if ($this->strategy instanceof MatcherAwareInterface) {
256 2
                $this->strategy->setMatcher($this->matcher);
257 2
            }
258
259 8
            return $this->strategy->call($this);
260
        }
261
262 1
        throw new BadRouteException(str_replace("%s", get_class($this->strategy), BadRouteException::BAD_STRATEGY));
263
    }
264
265
    /**
266
     * @return Collector
267
     */
268
269 1
    public function getCollector()
270
    {
271 1
        return $this->collector;
272
    }
273
274
    /**
275
     * @return string
276
     */
277
278
    public function getMethod()
279
    {
280
        return $this->method;
281
    }
282
283
    /**
284
     * @return string
285
     */
286
287 32
    public function getPattern()
288
    {
289 32
        return $this->pattern;
290
    }
291
292
    /**
293
     * @return string[]
294
     */
295
296
    public function getSegments()
297
    {
298
        return explode("/", $this->pattern);
299
    }
300
301
    /**
302
     * @return callable
303
     */
304
305 13
    public function getAction()
306
    {
307 13
        return $this->action;
308
    }
309
310
    /**
311
     * @return string
312
     */
313
314
    public function getNamespace()
315
    {
316
        return $this->namespace;
317
    }
318
319
    /**
320
     * @return string[]
321
     */
322
323 32
    public function getParams()
324
    {
325 32
        return $this->params;
326
    }
327
328
    /**
329
     * @param string $key
330
     * @return string
331
     */
332
333
    public function getParam($key)
334
    {
335
        return $this->params[$key];
336
    }
337
338
    /**
339
     * Return defaults and params merged in one array.
340
     *
341
     * @return array
342
     */
343
344 6
    public function getMergedParams()
345
    {
346 6
        return array_merge($this->defaults, $this->params);
347
    }
348
349
    /**
350
     * @return array
351
     */
352
353 1
    public function getDefaults()
354
    {
355 1
        return $this->defaults;
356
    }
357
358
    /**
359
     * @param string $key
360
     * @return mixed
361
     */
362
363 1
    public function getDefault($key)
364
    {
365 1
        return $this->defaults[$key];
366
    }
367
368
    /**
369
     * @return array
370
     */
371
372 1
    public function getMetadataArray()
373
    {
374 1
        return $this->metadata;
375
    }
376
377
    /**
378
     * @param string $key
379
     * @return mixed
380
     */
381
382 1
    public function getMetadata($key)
383
    {
384 1
        return $this->metadata[$key];
385
    }
386
387
    /**
388
     * @return string|null
389
     */
390
391 2
    public function getStrategy()
392
    {
393 2
        if ($this->strategy instanceof StrategyInterface) {
394
            return get_class($this->strategy);
395
        }
396
397 2
        return $this->strategy;
398
    }
399
400
    /**
401
     * @return StrategyInterface|string
402
     */
403
404 1
    public function getRawStrategy()
405
    {
406 1
        return $this->strategy;
407
    }
408
409
    /**
410
     * @return Matcher
411
     */
412
413 1
    public function getMatcher()
414
    {
415 1
        return $this->matcher;
416
    }
417
418
    /**
419
     * Verify if a Route have already been blocked.
420
     *
421
     * @return boolean
422
     */
423
424 32
    public function getBlock()
425
    {
426 32
        return $this->blocked;
427
    }
428
429
    /**
430
     * Blocking a route indicate that that route have been selected and
431
     * parsed, now it will be given to the matcher.
432
     *
433
     * @param bool $blocked
434
     * @return self
435
     */
436
437 32
    public function setBlock($blocked)
438
    {
439 32
        $this->blocked = $blocked;
440 32
        return $this;
441
    }
442
443
    /**
444
     * @param string $method
445
     * @return Route
446
     */
447
448 1
    public function setMethod($method)
449
    {
450 1
        $this->forget();
451 1
        $this->method = $method;
452 1
        return $this->reset();
453
    }
454
455
    /**
456
     * @param string $pattern
457
     * @return Route
458
     */
459
460 3
    public function setPattern($pattern)
461
    {
462 3
        $this->forget();
463 3
        $this->pattern = $pattern;
464 3
        return $this->reset();
465
    }
466
467
    /**
468
     * @param string $pattern
469
     * @return self
470
     */
471
472 32
    public function setPatternWithoutReset($pattern)
473
    {
474 32
        $this->pattern = $pattern;
475 32
        return $this;
476
    }
477
478
    /**
479
     * @param string $action
480
     * @return self
481
     */
482
483 3
    public function setAction($action)
484
    {
485 3
        $this->action = $action;
486 3
        return $this;
487
    }
488
489
    /**
490
     * @param string $namespace
491
     * @return self
492
     */
493
494 1
    public function setNamespace($namespace)
495
    {
496 1
        $this->namespace = $namespace;
497 1
        return $this;
498
    }
499
500
    /**
501
     * @param string[] $params
502
     * @return self
503
     */
504
505 33
    public function setParams(array $params)
506
    {
507 33
        $this->params = $params;
508 33
        return $this;
509
    }
510
511
    /**
512
     * @param string $key
513
     * @param string $value
514
     *
515
     * @return self
516
     */
517
518
    public function setParam($key, $value)
519
    {
520
        $this->params[$key] = $value;
521
        return $this;
522
    }
523
524
    /**
525
     * @param mixed[] $defaults
526
     * @return self
527
     */
528
529 5
    public function setDefaults(array $defaults)
530
    {
531 5
        $this->defaults = $defaults;
532 5
        return $this;
533
    }
534
535
    /**
536
     * @param string $key
537
     * @param mixed $value
538
     *
539
     * @return self
540
     */
541
542 1
    public function setDefault($key, $value)
543
    {
544 1
        $this->defaults[$key] = $value;
545 1
        return $this;
546
    }
547
548
    /**
549
     * @param mixed[] $metadata
550
     * @return self
551
     */
552
553 5
    public function setMetadataArray(array $metadata)
554
    {
555 5
        $this->metadata = $metadata;
556 5
        return $this;
557
    }
558
559
    /**
560
     * @param string $key
561
     * @param mixed $value
562
     *
563
     * @return $this
564
     */
565
566 1
    public function setMetadata($key, $value)
567
    {
568 1
        $this->metadata[$key] = $value;
569 1
        return $this;
570
    }
571
572
    /**
573
     * @param null|string|StrategyInterface $strategy
574
     * @return self
575
     */
576
577 20
    public function setStrategy($strategy)
578
    {
579 20
        $this->strategy = $strategy;
580 20
        return $this;
581
    }
582
583
    /**
584
     * @param Matcher $matcher
585
     * @return self
586
     */
587
588 45
    public function setMatcher(Matcher $matcher)
589
    {
590 45
        $this->matcher = $matcher;
591 45
        return $this;
592
    }
593
594
    /**
595
     * Set a constraint to a token in the route pattern.
596
     *
597
     * @param string $token
598
     * @param string $regex
599
     *
600
     * @return self
601
     */
602
603 1
    public function setConstraint($token, $regex)
604
    {
605 1
        $initPos = strpos($this->pattern, "{" . $token);
606
607 1
        if ($initPos !== false) {
608 1
            $endPos = strpos($this->pattern, "}", $initPos);
609 1
            $newPattern = substr_replace($this->pattern, "{" . "$token:$regex" . "}", $initPos, $endPos - $initPos + 1);
610 1
            $wildcards = $this->collector->getParser()->getWildcardTokens();
611 1
            $newPattern = str_replace(array_keys($wildcards), $wildcards, $newPattern);
612 1
            $this->setPatternWithoutReset($newPattern);
613 1
        }
614
615 1
        return $this;
616
    }
617
618
    /**
619
     * @param string $key
620
     * @return bool
621
     */
622
623
    public function hasParam($key)
624
    {
625
        return isset($this->params[$key]);
626
    }
627
628
    /**
629
     * @param string $key
630
     * @return bool
631
     */
632
633
    public function hasDefault($key)
634
    {
635
        return isset($this->defaults[$key]);
636
    }
637
638
    /**
639
     * @param string $key
640
     * @return bool
641
     */
642
643
    public function hasMetadata($key)
644
    {
645
        return isset($this->metadata[$key]);
646
    }
647
648
}
649