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 | * @package Fuel\FileSystem |
||
4 | * @version 2.0 |
||
5 | * @author Fuel Development Team |
||
6 | * @license MIT License |
||
7 | * @copyright 2010 - 2015 Fuel Development Team |
||
8 | * @link http://fuelphp.com |
||
9 | */ |
||
10 | |||
11 | namespace Fuel\FileSystem; |
||
12 | |||
13 | use Closure; |
||
14 | |||
15 | class Finder |
||
16 | { |
||
17 | /** |
||
18 | * @var string |
||
19 | */ |
||
20 | protected $defaultExtension = 'php'; |
||
21 | |||
22 | /** |
||
23 | * @var array |
||
24 | */ |
||
25 | protected $paths = []; |
||
26 | |||
27 | /** |
||
28 | * @var string |
||
29 | */ |
||
30 | protected $root; |
||
31 | |||
32 | /** |
||
33 | * @var boolean |
||
34 | */ |
||
35 | protected $returnHandlers = false; |
||
36 | |||
37 | /** |
||
38 | * @var null|boolean |
||
39 | */ |
||
40 | protected $nextAsHandlers = null; |
||
41 | |||
42 | /** |
||
43 | * @param array $path |
||
44 | * @param string $defaultExtension |
||
45 | * @param string $root |
||
46 | */ |
||
47 | 5 | public function __construct(array $paths = null, $defaultExtension = null, $root = null) |
|
48 | { |
||
49 | 5 | if ($paths) |
|
50 | { |
||
51 | 1 | $this->addPaths((array) $paths, false); |
|
52 | } |
||
53 | |||
54 | 5 | if ($defaultExtension) |
|
0 ignored issues
–
show
|
|||
55 | { |
||
56 | 1 | $this->setDefaultExtension($defaultExtension); |
|
57 | } |
||
58 | |||
59 | 5 | $this->root = $root; |
|
60 | 5 | } |
|
61 | |||
62 | /** |
||
63 | * Wether to return handlers |
||
64 | * |
||
65 | * @param boolean $returnHandlers |
||
66 | */ |
||
67 | 1 | public function returnHandlers($returnHandlers = true) |
|
68 | { |
||
69 | 1 | $this->returnHandlers = $returnHandlers; |
|
70 | 1 | } |
|
71 | |||
72 | /** |
||
73 | * Wether to let the next find result return handlers |
||
74 | * |
||
75 | * @param boolean $returnHandlers |
||
76 | */ |
||
77 | 2 | public function asHandlers($returnHandlers = true) |
|
78 | { |
||
79 | 2 | $this->nextAsHandlers = $returnHandlers; |
|
80 | 2 | } |
|
81 | |||
82 | /** |
||
83 | * Wether to let the next find result return a handler |
||
84 | * |
||
85 | * @param boolean $returnHandler |
||
86 | */ |
||
87 | 1 | public function asHandler($returnHandler = true) |
|
88 | { |
||
89 | 1 | $this->nextAsHandlers = $returnHandler; |
|
90 | 1 | } |
|
91 | |||
92 | /** |
||
93 | * Returns the root |
||
94 | * |
||
95 | * @return string |
||
96 | */ |
||
97 | 1 | public function getRoot() |
|
98 | { |
||
99 | 1 | return $this->root; |
|
100 | } |
||
101 | |||
102 | /** |
||
103 | * Sets a root restriction |
||
104 | * |
||
105 | * @param string $root |
||
106 | */ |
||
107 | 2 | public function setRoot($root) |
|
108 | { |
||
109 | 2 | if ( ! $path = realpath($root)) |
|
110 | { |
||
111 | 1 | throw new \Exception('Location does not exist: '.$root); |
|
112 | } |
||
113 | |||
114 | 1 | $this->root = $path; |
|
115 | 1 | } |
|
116 | |||
117 | /** |
||
118 | * Adds paths to look in |
||
119 | * |
||
120 | * @param array $paths |
||
121 | * @param boolean $clearCache |
||
122 | */ |
||
123 | 2 | public function addPaths(array $paths, $clearCache = true, $group = '__DEFAULT__') |
|
124 | { |
||
125 | 2 | array_map([$this, 'addPath'], $paths, [[$clearCache, $group]]); |
|
126 | 2 | } |
|
127 | |||
128 | /** |
||
129 | * Adds a path |
||
130 | * |
||
131 | * @param string $path |
||
132 | * @param boolean $clearCache |
||
133 | */ |
||
134 | 4 | View Code Duplication | public function addPath($path, $clearCache = true, $group = '__DEFAULT__') |
135 | { |
||
136 | //var_dump(func_get_args()); |
||
137 | 4 | $path = $this->normalizePath($path); |
|
138 | |||
139 | // This is done for easy reference and |
||
140 | // eliminates the need to check for doubles |
||
141 | 3 | $this->paths[$group][$path] = $path; |
|
142 | |||
143 | 3 | if ($clearCache) |
|
144 | { |
||
145 | 3 | $this->cache = []; |
|
146 | } |
||
147 | 3 | } |
|
148 | |||
149 | /** |
||
150 | * Removes paths to look in |
||
151 | * |
||
152 | * @param array $paths |
||
153 | */ |
||
154 | 1 | public function removePaths(array $paths, $clearCache = true, $group = '__DEFAULT__') |
|
155 | { |
||
156 | 1 | array_map([$this, 'removePath'], $paths, [[$clearCache, $group]]); |
|
157 | 1 | } |
|
158 | |||
159 | /** |
||
160 | * Removes a path |
||
161 | * |
||
162 | * @param string $path |
||
163 | */ |
||
164 | 1 | public function removePath($path, $clearCache = true, $group = '__DEFAULT__') |
|
165 | { |
||
166 | 1 | $path = $this->normalizePath($path); |
|
167 | |||
168 | 1 | if ($path and isset($this->paths[$group][$path])) |
|
169 | { |
||
170 | 1 | unset($this->paths[$group][$path]); |
|
171 | |||
172 | 1 | if ($clearCache) $this->removePathCache($path); |
|
173 | } |
||
174 | 1 | } |
|
175 | |||
176 | /** |
||
177 | * Removes path cache |
||
178 | * |
||
179 | * @param string $path |
||
180 | */ |
||
181 | 1 | public function removePathCache($path) |
|
182 | { |
||
183 | 1 | foreach ($this->cache as $key => $cache) |
|
184 | { |
||
185 | 1 | if (in_array($path, $cache['used'])) |
|
186 | { |
||
187 | 1 | unset($this->cache[$key]); |
|
188 | } |
||
189 | } |
||
190 | 1 | } |
|
191 | |||
192 | /** |
||
193 | * Normalizes a path |
||
194 | * |
||
195 | * @param string $path |
||
196 | * |
||
197 | * @return string |
||
198 | * |
||
199 | * @throws \Exception |
||
200 | */ |
||
201 | 4 | public function normalizePath($path) |
|
202 | { |
||
203 | 4 | $path = rtrim($path, '/\\').DIRECTORY_SEPARATOR; |
|
204 | 4 | $path = realpath($path).DIRECTORY_SEPARATOR; |
|
205 | |||
206 | 4 | if ($this->root and strpos($path, $this->root) !== 0) |
|
207 | { |
||
208 | 1 | throw new \Exception('Cannot access path outside: '.$this->root.'. Trying to access: '.$path); |
|
209 | } |
||
210 | |||
211 | 3 | return $path; |
|
212 | } |
||
213 | |||
214 | /** |
||
215 | * Returns the paths set up to look in |
||
216 | * |
||
217 | * @return array |
||
218 | */ |
||
219 | 1 | public function getPaths($group = '__DEFAULT__') |
|
220 | { |
||
221 | 1 | if ( ! isset($this->paths[$group])) |
|
222 | { |
||
223 | 1 | return []; |
|
224 | } |
||
225 | |||
226 | 1 | return array_values($this->paths[$group]); |
|
227 | } |
||
228 | |||
229 | /** |
||
230 | * Retrieves the path groups |
||
231 | * |
||
232 | * @return array |
||
233 | */ |
||
234 | 1 | public function getGroups() |
|
235 | { |
||
236 | 1 | return array_keys($this->paths); |
|
237 | } |
||
238 | |||
239 | /** |
||
240 | * Replaces all the paths |
||
241 | * |
||
242 | * @param array $paths |
||
243 | */ |
||
244 | 1 | View Code Duplication | public function setPaths(array $paths, $clearCache = true, $group = '__DEFAULT__') |
245 | { |
||
246 | 1 | $this->paths[$group] = []; |
|
247 | 1 | $this->addPaths($paths, false, $group); |
|
248 | |||
249 | 1 | if ($clearCache) |
|
250 | { |
||
251 | 1 | $this->cache = []; |
|
252 | } |
||
253 | 1 | } |
|
254 | |||
255 | /** |
||
256 | * Finds all files with a given name/subpath. |
||
257 | * |
||
258 | * @param string $name |
||
259 | * @param boolean $reload |
||
260 | * @param boolean $reversed |
||
261 | * @param string $type |
||
262 | */ |
||
263 | 2 | public function findAll($name, $reload = false, $reversed = false, $type = 'all') |
|
264 | { |
||
265 | 2 | $name = trim($name, '\\/'); |
|
266 | 2 | $scope = 'all::'.$type; |
|
267 | 2 | $asHandlers = $this->returnHandlers; |
|
268 | 2 | $group = '__DEFAULT__'; |
|
269 | 2 | $query = $name; |
|
270 | |||
271 | 2 | if ($this->nextAsHandlers !== null) |
|
272 | { |
||
273 | 1 | $asHandlers = $this->nextAsHandlers; |
|
274 | 1 | $this->nextAsHandlers = null; |
|
275 | } |
||
276 | |||
277 | 2 | View Code Duplication | if (strpos($query, '::') !== false) |
278 | { |
||
279 | 1 | list($group, $query) = explode('::', $query); |
|
280 | } |
||
281 | |||
282 | 2 | if ( ! isset($this->paths[$group])) |
|
283 | { |
||
284 | 1 | return []; |
|
285 | } |
||
286 | |||
287 | 2 | if ($type !== 'dir') |
|
288 | { |
||
289 | 2 | $query = $this->normalizeFileName($query); |
|
290 | } |
||
291 | |||
292 | 2 | if ( ! $reload and $cached = $this->findCached($scope, $name, $reversed)) |
|
293 | { |
||
294 | 1 | return $cached; |
|
295 | } |
||
296 | |||
297 | 2 | $used = []; |
|
298 | 2 | $found = []; |
|
299 | 2 | $paths = $reversed ? array_reverse($this->paths[$group]) : $this->paths[$group]; |
|
300 | |||
301 | 2 | foreach ($paths as $path) |
|
302 | { |
||
303 | 2 | if ($type !== 'dir' and is_file($path.$query)) |
|
304 | { |
||
305 | 2 | $found[] = $asHandlers ? new File($path.$query) : $path.$query; |
|
306 | 2 | $used[] = $path; |
|
307 | } |
||
308 | 2 | elseif ($type !== 'file' and is_dir($path.$query)) |
|
309 | { |
||
310 | 2 | $found[] = $asHandlers ? new Directory($path.$query, $this->returnHandlers) : $path.$query; |
|
311 | 2 | $used[] = $path; |
|
312 | } |
||
313 | } |
||
314 | |||
315 | // Store the paths in cache |
||
316 | 2 | $this->cache($scope, $name, $reversed, $found, $used); |
|
317 | |||
318 | 2 | return $found; |
|
319 | } |
||
320 | |||
321 | /** |
||
322 | * Finds all files with a given name/subpath |
||
323 | * |
||
324 | * @param string $name |
||
325 | * @param boolean $reload |
||
326 | * @param boolean $reversed |
||
327 | */ |
||
328 | 2 | public function findAllFiles($name, $reload = false, $reversed = false) |
|
329 | { |
||
330 | 2 | return $this->findAll($name, $reload, $reversed, 'file'); |
|
331 | } |
||
332 | |||
333 | /** |
||
334 | * Finds all directories with a given name/subpath |
||
335 | * |
||
336 | * @param string $name |
||
337 | * @param boolean $reload |
||
338 | * @param boolean $reversed |
||
339 | */ |
||
340 | 2 | public function findAllDirs($name, $reload = false, $reversed = false) |
|
341 | { |
||
342 | 2 | return $this->findAll($name, $reload, $reversed, 'dir'); |
|
343 | } |
||
344 | |||
345 | /** |
||
346 | * Reverse-finds all files and directories with a given name/subpath |
||
347 | * |
||
348 | * @param string $name |
||
349 | * @param boolean $reload |
||
350 | * @param string $type |
||
351 | */ |
||
352 | 1 | public function findAllReversed($name, $reload = false, $type = 'all') |
|
353 | { |
||
354 | 1 | return $this->findAll($name, $reload, true, $type); |
|
355 | } |
||
356 | |||
357 | /** |
||
358 | * Reverse-finds all directories with a given name/subpath |
||
359 | * |
||
360 | * @param string $name |
||
361 | * @param boolean $reload |
||
362 | */ |
||
363 | 1 | public function findAllDirsReversed($name, $reload = false) |
|
364 | { |
||
365 | 1 | return $this->findAll($name, $reload, true, 'dir'); |
|
366 | } |
||
367 | |||
368 | /** |
||
369 | * Reverse-finds all files with a given name/subpath |
||
370 | * |
||
371 | * @param string $name |
||
372 | * @param boolean $reload |
||
373 | */ |
||
374 | 1 | public function findAllFilesReversed($name, $reload = false) |
|
375 | { |
||
376 | 1 | return $this->findAll($name, $reload, true, 'file'); |
|
377 | } |
||
378 | |||
379 | /** |
||
380 | * Finds one file or directories with a given name/subpath |
||
381 | * |
||
382 | * @param string $name |
||
383 | * @param boolean $reload |
||
384 | * @param boolean $reversed |
||
385 | * @param string $type |
||
386 | */ |
||
387 | 3 | public function find($name, $reload = false, $reversed = false, $type = 'all') |
|
388 | { |
||
389 | 3 | $name = trim($name, '\\/'); |
|
390 | 3 | $scope = 'one::'.$type; |
|
391 | 3 | $asHandlers = $this->returnHandlers; |
|
392 | 3 | $query = $name; |
|
393 | 3 | $group = '__DEFAULT__'; |
|
394 | |||
395 | 3 | if ($this->nextAsHandlers !== null) |
|
396 | { |
||
397 | 1 | $asHandlers = $this->nextAsHandlers; |
|
398 | 1 | $this->nextAsHandlers = null; |
|
399 | } |
||
400 | |||
401 | 3 | View Code Duplication | if (strpos($query, '::') !== false) |
402 | { |
||
403 | 1 | list($group, $query) = explode('::', $query); |
|
404 | } |
||
405 | |||
406 | 3 | if ( ! isset($this->paths[$group])) |
|
407 | { |
||
408 | 1 | return; |
|
409 | } |
||
410 | |||
411 | 3 | if ($type !== 'dir') |
|
412 | { |
||
413 | 3 | $query = $this->normalizeFileName($query); |
|
414 | } |
||
415 | |||
416 | 3 | if ( ! $reload and $cached = $this->findCached($scope, $name, $reversed)) |
|
417 | { |
||
418 | 1 | return $cached; |
|
419 | } |
||
420 | |||
421 | 3 | $paths = $this->paths[$group]; |
|
422 | |||
423 | 3 | if ($reversed) |
|
424 | { |
||
425 | 1 | $paths = array_reverse($paths); |
|
426 | } |
||
427 | |||
428 | 3 | foreach ($paths as $path) |
|
429 | { |
||
430 | 3 | if ($type !== 'dir' and is_file($path.$query)) |
|
431 | { |
||
432 | 3 | $found = $path.$query; |
|
433 | |||
434 | 3 | if ($asHandlers) |
|
435 | { |
||
436 | 1 | $found = new File($found); |
|
437 | } |
||
438 | |||
439 | 3 | break; |
|
440 | } |
||
441 | 2 | elseif ($type !== 'file' and is_dir($path.$query)) |
|
442 | { |
||
443 | 2 | $found = $path.$query; |
|
444 | |||
445 | 2 | if ($asHandlers) |
|
446 | { |
||
447 | 1 | $found = new Directory($found); |
|
448 | } |
||
449 | |||
450 | 2 | break; |
|
451 | } |
||
452 | } |
||
453 | |||
454 | 3 | if (isset($found)) |
|
455 | { |
||
456 | // Store the paths in cache |
||
457 | 3 | $this->cache($scope, $name, $reversed, $found, [$path]); |
|
458 | |||
459 | 3 | return $found; |
|
460 | } |
||
461 | 1 | } |
|
462 | |||
463 | /** |
||
464 | * Finds one file with a given name/subpath |
||
465 | * |
||
466 | * @param string $name |
||
467 | * @param boolean $reload |
||
468 | * @param boolean $reversed |
||
469 | */ |
||
470 | 3 | public function findFile($name, $reload = false, $reversed = false) |
|
471 | { |
||
472 | 3 | return $this->find($name, $reload, $reversed, 'file'); |
|
473 | } |
||
474 | |||
475 | /** |
||
476 | * Finds one directories with a given name/subpath |
||
477 | * |
||
478 | * @param string $name |
||
479 | * @param boolean $reload |
||
480 | * @param boolean $reversed |
||
481 | */ |
||
482 | 2 | public function findDir($name, $reload = false, $reversed = false) |
|
483 | { |
||
484 | 2 | return $this->find($name, $reload, $reversed, 'dir'); |
|
485 | } |
||
486 | |||
487 | /** |
||
488 | * Reverse-finds one file or directory with a given name/subpath |
||
489 | * |
||
490 | * @param string $name |
||
491 | * @param boolean $reload |
||
492 | * @param boolean $reversed |
||
493 | * @param string $type |
||
494 | */ |
||
495 | 1 | public function findReversed($name, $reload = false, $type = 'all') |
|
496 | { |
||
497 | 1 | return $this->find($name, $reload, true, $type); |
|
498 | } |
||
499 | |||
500 | /** |
||
501 | * Reverse-finds one file with a given name/subpath |
||
502 | * |
||
503 | * @param string $name |
||
504 | * @param boolean $reload |
||
505 | * @param boolean $reversed |
||
506 | */ |
||
507 | 1 | public function findFileReversed($name, $reload = false) |
|
508 | { |
||
509 | 1 | return $this->findReversed($name, $reload, 'file'); |
|
510 | } |
||
511 | |||
512 | /** |
||
513 | * Reverse-finds one directory with a given name/subpath |
||
514 | * |
||
515 | * @param string $name |
||
516 | * @param boolean $reload |
||
517 | * @param boolean $reversed |
||
518 | */ |
||
519 | 1 | public function findDirReversed($name, $reload = false) |
|
520 | { |
||
521 | 1 | return $this->findReversed($name, $reload, 'dir'); |
|
522 | } |
||
523 | |||
524 | /** |
||
525 | * Retrieves a location from cache |
||
526 | * |
||
527 | * @param string $scope |
||
528 | * @param string $name |
||
529 | * @param boolean $reversed |
||
530 | * |
||
531 | * @return string|array |
||
532 | */ |
||
533 | 3 | public function findCached($scope, $name, $reversed) |
|
534 | { |
||
535 | 3 | $cacheKey = $this->makeCacheKey($scope, $name, $reversed); |
|
536 | |||
537 | 3 | if (isset($this->cache[$cacheKey])) |
|
538 | { |
||
539 | 1 | return $this->cache[$cacheKey]['result']; |
|
540 | } |
||
541 | 3 | } |
|
542 | |||
543 | /** |
||
544 | * Clears the location cache |
||
545 | */ |
||
546 | 1 | public function clearCache() |
|
547 | { |
||
548 | 1 | $this->cached = []; |
|
549 | 1 | } |
|
550 | |||
551 | /** |
||
552 | * Caches a find result |
||
553 | * |
||
554 | * @param string $scope |
||
555 | * @param string $name |
||
556 | * @param boolean $reversed |
||
557 | * @param array $pathsUsed |
||
558 | */ |
||
559 | 3 | public function cache($scope, $name, $reversed, $result, $pathsUsed = []) |
|
560 | { |
||
561 | 3 | $cacheKey = $this->makeCacheKey($scope, $name, $reversed); |
|
562 | 3 | $this->cache[$cacheKey] = [ |
|
563 | 3 | 'result' => $result, |
|
564 | 3 | 'used' => $pathsUsed, |
|
565 | ]; |
||
566 | 3 | } |
|
567 | |||
568 | /** |
||
569 | * Generates a cache key |
||
570 | * |
||
571 | * @param string $scope |
||
572 | * @param string $name |
||
573 | * @param boolean $reversed |
||
574 | * |
||
575 | * @return string |
||
576 | */ |
||
577 | 3 | public function makeCacheKey($scope, $name, $reversed) |
|
578 | { |
||
579 | 3 | $cacheKey = $scope.'::'.$name; |
|
580 | |||
581 | 3 | if ($reversed) |
|
582 | { |
||
583 | 1 | $cacheKey .= '::reversed'; |
|
584 | } |
||
585 | |||
586 | 3 | return $cacheKey; |
|
587 | } |
||
588 | |||
589 | /** |
||
590 | * Normalizes a file name |
||
591 | * |
||
592 | * @param string $name |
||
593 | * |
||
594 | * @return string |
||
595 | */ |
||
596 | 3 | public function normalizeFileName($name) |
|
597 | { |
||
598 | 3 | if ( ! pathinfo($name, PATHINFO_EXTENSION)) |
|
599 | { |
||
600 | 3 | $name .= '.'.$this->defaultExtension; |
|
601 | } |
||
602 | |||
603 | 3 | return $name; |
|
604 | } |
||
605 | |||
606 | /** |
||
607 | * Sets the default extension |
||
608 | * |
||
609 | * @param string $extension |
||
610 | */ |
||
611 | 2 | public function setDefaultExtension($extension) |
|
612 | { |
||
613 | 2 | $this->defaultExtension = ltrim($extension, '.'); |
|
614 | 2 | } |
|
615 | } |
||
616 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
string
values, the empty string''
is a special case, in particular the following results might be unexpected: