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 /** MicroRouter */ |
||
2 | |||
3 | namespace Micro\Web; |
||
4 | |||
5 | /** |
||
6 | * Router class file. |
||
7 | * |
||
8 | * Routing user requests |
||
9 | * |
||
10 | * @author Oleg Lunegov <[email protected]> |
||
11 | * @link https://github.com/linpax/microphp-framework |
||
12 | * @copyright Copyright (c) 2013 Oleg Lunegov |
||
13 | * @license https://github.com/linpax/microphp-framework/blob/master/LICENSE |
||
14 | * @package Micro |
||
15 | * @subpackage Web |
||
16 | * @version 1.0 |
||
17 | * @since 1.0 |
||
18 | */ |
||
19 | class Router implements IRouter |
||
20 | { |
||
21 | /** @var array $routes routes for routing */ |
||
22 | public $routes = []; |
||
23 | |||
24 | |||
25 | /** |
||
26 | * Construct for route scanner |
||
27 | * |
||
28 | * @access public |
||
29 | * |
||
30 | * @param array $routes |
||
31 | * |
||
32 | * @result void |
||
33 | */ |
||
34 | public function __construct(array $routes = []) |
||
35 | { |
||
36 | $this->routes = $routes; |
||
37 | } |
||
38 | |||
39 | /** |
||
40 | * @inheritdoc |
||
41 | */ |
||
42 | public function parse($uri, $method = 'GET') |
||
43 | { |
||
44 | // default path |
||
45 | if ($uri === '/' || $uri === '' || $uri === '/default') { |
||
46 | return '/default'; |
||
47 | } |
||
48 | |||
49 | // scan routes |
||
50 | foreach ($this->routes as $condition => $config) { |
||
51 | if (is_array($config) && !empty($config['route'])) { |
||
52 | if (!empty($config['verb']) && ($config['verb'] !== $method)) { |
||
53 | continue; |
||
54 | } |
||
55 | |||
56 | $replacement = $config['route']; |
||
57 | } elseif (is_string($config)) { |
||
58 | $replacement = $config; |
||
59 | } else { |
||
60 | continue; |
||
61 | } |
||
62 | // slice path |
||
63 | if ($uri === $condition) { |
||
64 | return $replacement; |
||
65 | } |
||
66 | // pattern path |
||
67 | if ($validated = $this->validatedRule($uri, $condition, $replacement)) { |
||
68 | return $validated; |
||
69 | } |
||
70 | } |
||
71 | |||
72 | // return raw uri |
||
73 | return $uri; |
||
74 | } |
||
75 | |||
76 | /** |
||
77 | * Validated router rule |
||
78 | * |
||
79 | * @access private |
||
80 | * |
||
81 | * @param string $uri uri to validation |
||
82 | * @param string $pattern checking pattern |
||
83 | * @param string $replacement replacement for pattern |
||
84 | * |
||
85 | * @return string |
||
86 | */ |
||
87 | private function validatedRule($uri, $pattern, $replacement) |
||
88 | { |
||
89 | $uriBlocks = explode('/', trim($uri, '/')); |
||
90 | $patBlocks = explode('/', trim($pattern, '/')); |
||
91 | $repBlocks = explode('/', trim($replacement, '/')); |
||
92 | |||
93 | if (count($uriBlocks) !== count($patBlocks)) { |
||
94 | return false; |
||
95 | } |
||
96 | |||
97 | |||
98 | $attributes = $this->parseUri($uriBlocks, $patBlocks); |
||
99 | if (!$attributes) { |
||
100 | return false; |
||
101 | } |
||
102 | |||
103 | $result = $this->buildResult($attributes, $repBlocks); |
||
104 | if ($result === null || $result === false) { |
||
105 | return false; |
||
106 | } |
||
107 | |||
108 | if (!$attributes) { |
||
0 ignored issues
–
show
|
|||
109 | return $result; |
||
110 | } |
||
111 | |||
112 | $result .= '?'; |
||
113 | foreach ($attributes AS $key => $val) { |
||
114 | if ($key !== $val) { |
||
115 | $result .= '&'.$key.'='.$val; |
||
116 | } |
||
117 | } |
||
118 | |||
119 | return $result; |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Match patBlocks in uriBlocks |
||
124 | * |
||
125 | * @access private |
||
126 | * |
||
127 | * @param array $uriBlocks uri blocks from URL |
||
128 | * @param array $patBlocks pattern blocks from valid URL |
||
129 | * |
||
130 | * @return array |
||
131 | */ |
||
132 | private function parseUri(array $uriBlocks = [], array $patBlocks = []) |
||
133 | { |
||
134 | $attr = []; |
||
135 | |||
136 | foreach (range(0, count($uriBlocks) - 1) AS $i) { |
||
137 | if (0 === strpos($patBlocks[$i], '<')) { |
||
138 | $cut = strpos($patBlocks[$i], ':'); |
||
139 | |||
140 | if (preg_match('/'.substr($patBlocks[$i], $cut + 1, -1).'/', $uriBlocks[$i])) { |
||
141 | $attr[substr($patBlocks[$i], 1, $cut - 1)] = $uriBlocks[$i]; |
||
142 | } else { |
||
143 | return null; |
||
144 | } |
||
145 | |||
146 | } elseif ($uriBlocks[$i] !== $patBlocks[$i]) { |
||
147 | return null; |
||
148 | } else { |
||
149 | $attr[$uriBlocks[$i]] = $patBlocks[$i]; |
||
150 | } |
||
151 | } |
||
152 | |||
153 | return $attr; |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * Replacement $result with repBlocks |
||
158 | * |
||
159 | * @access private |
||
160 | * |
||
161 | * @param array $attr elements of valid URL |
||
162 | * @param array $repBlocks replacement blocks from valid URL |
||
163 | * |
||
164 | * @return bool|null|string |
||
165 | */ |
||
166 | private function buildResult(&$attr, $repBlocks) |
||
167 | { |
||
168 | $result = null; |
||
169 | |||
170 | foreach ($repBlocks AS $value) { |
||
171 | if (0 !== strpos($value, '<')) { |
||
172 | $result .= '/'.$value; |
||
173 | |||
174 | unset($attr[$value]); |
||
175 | } else { |
||
176 | $element = substr($value, 1, -1); |
||
177 | |||
178 | if (!empty($attr[$element])) { |
||
179 | $result .= '/'.$attr[$element]; |
||
180 | |||
181 | unset($attr[$element]); |
||
182 | } else { |
||
183 | return false; |
||
184 | } |
||
185 | } |
||
186 | } |
||
187 | |||
188 | return $result; |
||
189 | } |
||
190 | } |
||
191 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.