Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
filesystem.php
001 <?php
002 /**
003 *
004 * This file is part of the phpBB Forum Software package.
005 *
006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
007 * @license GNU General Public License, version 2 (GPL-2.0)
008 *
009 * For full copyright and license information, please see
010 * the docs/CREDITS.txt file.
011 *
012 */
013
014 namespace phpbb\filesystem;
015
016 use phpbb\filesystem\exception\filesystem_exception;
017
018 /**
019 * A class with various functions that are related to paths, files and the filesystem
020 */
021 class filesystem implements filesystem_interface
022 {
023 /**
024 * Store some information about file ownership for phpBB's chmod function
025 *
026 * @var array
027 */
028 protected $chmod_info;
029
030 /**
031 * Stores current working directory
032 *
033 * @var string|bool current working directory or false if it cannot be recovered
034 */
035 protected $working_directory;
036
037 /**
038 * Symfony's Filesystem component
039 *
040 * @var \Symfony\Component\Filesystem\Filesystem
041 */
042 protected $symfony_filesystem;
043
044 /**
045 * Constructor
046 */
047 public function __construct()
048 {
049 $this->chmod_info = array();
050 $this->symfony_filesystem = new \Symfony\Component\Filesystem\Filesystem();
051 $this->working_directory = null;
052 }
053
054 /**
055 * {@inheritdoc}
056 */
057 public function chgrp($files, $group, $recursive = false)
058 {
059 try
060 {
061 $this->symfony_filesystem->chgrp($files, $group, $recursive);
062 }
063 catch (\Symfony\Component\Filesystem\Exception\IOException $e)
064 {
065 // Try to recover filename
066 // By the time this is written that is at the end of the message
067 $error = trim($e->getMessage());
068 $file = substr($error, strrpos($error, ' '));
069
070 throw new filesystem_exception('FILESYSTEM_CANNOT_CHANGE_FILE_GROUP', $file, array(), $e);
071 }
072 }
073
074 /**
075 * {@inheritdoc}
076 */
077 public function chmod($files, $perms = null, $recursive = false, $force_chmod_link = false)
078 {
079 if (is_null($perms))
080 {
081 // Default to read permission for compatibility reasons
082 $perms = self::CHMOD_READ;
083 }
084
085 // Check if we got a permission flag
086 if ($perms > self::CHMOD_ALL)
087 {
088 $file_perm = $perms;
089
090 // Extract permissions
091 //$owner = ($file_perm >> 6) & 7; // This will be ignored
092 $group = ($file_perm >> 3) & 7;
093 $other = ($file_perm >> 0) & 7;
094
095 // Does any permissions provided? if so we add execute bit for directories
096 $group = ($group !== 0) ? ($group | self::CHMOD_EXECUTE) : $group;
097 $other = ($other !== 0) ? ($other | self::CHMOD_EXECUTE) : $other;
098
099 // Compute directory permissions
100 $dir_perm = (self::CHMOD_ALL << 6) + ($group << 3) + ($other << 3);
101 }
102 else
103 {
104 // Add execute bit to owner if execute bit is among perms
105 $owner_perm = (self::CHMOD_READ | self::CHMOD_WRITE) | ($perms & self::CHMOD_EXECUTE);
106 $file_perm = ($owner_perm << 6) + ($perms << 3) + ($perms << 0);
107
108 // Compute directory permissions
109 $perm = ($perms !== 0) ? ($perms | self::CHMOD_EXECUTE) : $perms;
110 $dir_perm = (($owner_perm | self::CHMOD_EXECUTE) << 6) + ($perm << 3) + ($perm << 0);
111 }
112
113 // Symfony's filesystem component does not support extra execution flags on directories
114 // so we need to implement it again
115 foreach ($this->to_iterator($files) as $file)
116 {
117 if ($recursive && is_dir($file) && !is_link($file))
118 {
119 $this->chmod(new \FilesystemIterator($file), $perms, true);
120 }
121
122 // Don't chmod links as mostly those require 0777 and that cannot be changed
123 if (is_dir($file) || (is_link($file) && $force_chmod_link))
124 {
125 if (true !== @chmod($file, $dir_perm))
126 {
127 throw new filesystem_exception('FILESYSTEM_CANNOT_CHANGE_FILE_PERMISSIONS', $file, array());
128 }
129 }
130 else if (is_file($file))
131 {
132 if (true !== @chmod($file, $file_perm))
133 {
134 throw new filesystem_exception('FILESYSTEM_CANNOT_CHANGE_FILE_PERMISSIONS', $file, array());
135 }
136 }
137 }
138 }
139
140 /**
141 * {@inheritdoc}
142 */
143 public function chown($files, $user, $recursive = false)
144 {
145 try
146 {
147 $this->symfony_filesystem->chown($files, $user, $recursive);
148 }
149 catch (\Symfony\Component\Filesystem\Exception\IOException $e)
150 {
151 // Try to recover filename
152 // By the time this is written that is at the end of the message
153 $error = trim($e->getMessage());
154 $file = substr($error, strrpos($error, ' '));
155
156 throw new filesystem_exception('FILESYSTEM_CANNOT_CHANGE_FILE_GROUP', $file, array(), $e);
157 }
158 }
159
160 /**
161 * {@inheritdoc}
162 */
163 public function clean_path($path)
164 {
165 $exploded = explode('/', $path);
166 $filtered = array();
167 foreach ($exploded as $part)
168 {
169 if ($part === '.' && !empty($filtered))
170 {
171 continue;
172 }
173
174 if ($part === '..' && !empty($filtered) && $filtered[count($filtered) - 1] !== '.' && $filtered[count($filtered) - 1] !== '..')
175 {
176 array_pop($filtered);
177 }
178 else
179 {
180 $filtered[] = $part;
181 }
182 }
183 $path = implode('/', $filtered);
184 return $path;
185 }
186
187 /**
188 * {@inheritdoc}
189 */
190 public function copy($origin_file, $target_file, $override = false)
191 {
192 try
193 {
194 $this->symfony_filesystem->copy($origin_file, $target_file, $override);
195 }
196 catch (\Symfony\Component\Filesystem\Exception\IOException $e)
197 {
198 throw new filesystem_exception('FILESYSTEM_CANNOT_COPY_FILES', '', array(), $e);
199 }
200 }
201
202 /**
203 * {@inheritdoc}
204 */
205 public function dump_file($filename, $content)
206 {
207 try
208 {
209 $this->symfony_filesystem->dumpFile($filename, $content);
210 }
211 catch (\Symfony\Component\Filesystem\Exception\IOException $e)
212 {
213 throw new filesystem_exception('FILESYSTEM_CANNOT_DUMP_FILE', $filename, array(), $e);
214 }
215 }
216
217 /**
218 * {@inheritdoc}
219 */
220 public function exists($files)
221 {
222 return $this->symfony_filesystem->exists($files);
223 }
224
225 /**
226 * {@inheritdoc}
227 */
228 public function is_absolute_path($path)
229 {
230 return (isset($path[0]) && $path[0] === '/' || preg_match('#^[a-z]:[/\\\]#i', $path)) ? true : false;
231 }
232
233 /**
234 * {@inheritdoc}
235 */
236 public function is_readable($files, $recursive = false)
237 {
238 foreach ($this->to_iterator($files) as $file)
239 {
240 if ($recursive && is_dir($file) && !is_link($file))
241 {
242 if (!$this->is_readable(new \FilesystemIterator($file), true))
243 {
244 return false;
245 }
246 }
247
248 if (!is_readable($file))
249 {
250 return false;
251 }
252 }
253
254 return true;
255 }
256
257 /**
258 * {@inheritdoc}
259 */
260 public function is_writable($files, $recursive = false)
261 {
262 if (defined('PHP_WINDOWS_VERSION_MAJOR') || !function_exists('is_writable'))
263 {
264 foreach ($this->to_iterator($files) as $file)
265 {
266 if ($recursive && is_dir($file) && !is_link($file))
267 {
268 if (!$this->is_writable(new \FilesystemIterator($file), true))
269 {
270 return false;
271 }
272 }
273
274 if (!$this->phpbb_is_writable($file))
275 {
276 return false;
277 }
278 }
279 }
280 else
281 {
282 // use built in is_writable
283 foreach ($this->to_iterator($files) as $file)
284 {
285 if ($recursive && is_dir($file) && !is_link($file))
286 {
287 if (!$this->is_writable(new \FilesystemIterator($file), true))
288 {
289 return false;
290 }
291 }
292
293 if (!is_writable($file))
294 {
295 return false;
296 }
297 }
298 }
299
300 return true;
301 }
302
303 /**
304 * {@inheritdoc}
305 */
306 public function make_path_relative($end_path, $start_path)
307 {
308 return $this->symfony_filesystem->makePathRelative($end_path, $start_path);
309 }
310
311 /**
312 * {@inheritdoc}
313 */
314 public function mirror($origin_dir, $target_dir, \Traversable $iterator = null, $options = array())
315 {
316 try
317 {
318 $this->symfony_filesystem->mirror($origin_dir, $target_dir, $iterator, $options);
319 }
320 catch (\Symfony\Component\Filesystem\Exception\IOException $e)
321 {
322 $msg = $e->getMessage();
323 $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"'));
324
325 throw new filesystem_exception('FILESYSTEM_CANNOT_MIRROR_DIRECTORY', $filename, array(), $e);
326 }
327 }
328
329 /**
330 * {@inheritdoc}
331 */
332 public function mkdir($dirs, $mode = 0777)
333 {
334 try
335 {
336 $this->symfony_filesystem->mkdir($dirs, $mode);
337 }
338 catch (\Symfony\Component\Filesystem\Exception\IOException $e)
339 {
340 $msg = $e->getMessage();
341 $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"'));
342
343 throw new filesystem_exception('FILESYSTEM_CANNOT_CREATE_DIRECTORY', $filename, array(), $e);
344 }
345 }
346
347 /**
348 * {@inheritdoc}
349 */
350 public function phpbb_chmod($files, $perms = null, $recursive = false, $force_chmod_link = false)
351 {
352 if (is_null($perms))
353 {
354 // Default to read permission for compatibility reasons
355 $perms = self::CHMOD_READ;
356 }
357
358 if (empty($this->chmod_info))
359 {
360 if (!function_exists('fileowner') || !function_exists('filegroup'))
361 {
362 $this->chmod_info['process'] = false;
363 }
364 else
365 {
366 $common_php_owner = @fileowner(__FILE__);
367 $common_php_group = @filegroup(__FILE__);
368
369 // And the owner and the groups PHP is running under.
370 $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false;
371 $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false;
372
373 // If we are unable to get owner/group, then do not try to set them by guessing
374 if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group)
375 {
376 $this->chmod_info['process'] = false;
377 }
378 else
379 {
380 $this->chmod_info = array(
381 'process' => true,
382 'common_owner' => $common_php_owner,
383 'common_group' => $common_php_group,
384 'php_uid' => $php_uid,
385 'php_gids' => $php_gids,
386 );
387 }
388 }
389 }
390
391 if ($this->chmod_info['process'])
392 {
393 try
394 {
395 foreach ($this->to_iterator($files) as $file)
396 {
397 $file_uid = @fileowner($file);
398 $file_gid = @filegroup($file);
399
400 // Change owner
401 if (is_writable($file) && $file_uid !== $this->chmod_info['common_owner'])
402 {
403 $this->chown($file, $this->chmod_info['common_owner'], $recursive);
404 }
405
406 // Change group
407 if (is_writable($file) && $file_gid !== $this->chmod_info['common_group'])
408 {
409 $this->chgrp($file, $this->chmod_info['common_group'], $recursive);
410 }
411
412 clearstatcache();
413 $file_uid = @fileowner($file);
414 $file_gid = @filegroup($file);
415 }
416 }
417 catch (filesystem_exception $e)
418 {
419 $this->chmod_info['process'] = false;
420 }
421 }
422
423 // Still able to process?
424 if ($this->chmod_info['process'])
425 {
426 if ($file_uid === $this->chmod_info['php_uid'])
427 {
428 $php = 'owner';
429 }
430 else if (in_array($file_gid, $this->chmod_info['php_gids']))
431 {
432 $php = 'group';
433 }
434 else
435 {
436 // Since we are setting the everyone bit anyway, no need to do expensive operations
437 $this->chmod_info['process'] = false;
438 }
439 }
440
441 // We are not able to determine or change something
442 if (!$this->chmod_info['process'])
443 {
444 $php = 'other';
445 }
446
447 switch ($php)
448 {
449 case 'owner':
450 try
451 {
452 $this->chmod($files, $perms, $recursive, $force_chmod_link);
453 clearstatcache();
454 if ($this->is_readable($files) && $this->is_writable($files))
455 {
456 break;
457 }
458 }
459 catch (filesystem_exception $e)
460 {
461 // Do nothing
462 }
463 case 'group':
464 try
465 {
466 $this->chmod($files, $perms, $recursive, $force_chmod_link);
467 clearstatcache();
468 if ((!($perms & self::CHMOD_READ) || $this->is_readable($files, $recursive)) && (!($perms & self::CHMOD_WRITE) || $this->is_writable($files, $recursive)))
469 {
470 break;
471 }
472 }
473 catch (filesystem_exception $e)
474 {
475 // Do nothing
476 }
477 case 'other':
478 default:
479 $this->chmod($files, $perms, $recursive, $force_chmod_link);
480 break;
481 }
482 }
483
484 /**
485 * {@inheritdoc}
486 */
487 public function realpath($path)
488 {
489 if (!function_exists('realpath'))
490 {
491 return $this->phpbb_own_realpath($path);
492 }
493
494 $realpath = realpath($path);
495
496 // Strangely there are provider not disabling realpath but returning strange values. :o
497 // We at least try to cope with them.
498 if ((!$this->is_absolute_path($path) && $realpath === $path) || $realpath === false)
499 {
500 return $this->phpbb_own_realpath($path);
501 }
502
503 // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
504 if (substr($realpath, -1) === DIRECTORY_SEPARATOR)
505 {
506 $realpath = substr($realpath, 0, -1);
507 }
508
509 return $realpath;
510 }
511
512 /**
513 * {@inheritdoc}
514 */
515 public function remove($files)
516 {
517 try
518 {
519 $this->symfony_filesystem->remove($files);
520 }
521 catch (\Symfony\Component\Filesystem\Exception\IOException $e)
522 {
523 // Try to recover filename
524 // By the time this is written that is at the end of the message
525 $error = trim($e->getMessage());
526 $file = substr($error, strrpos($error, ' '));
527
528 throw new filesystem_exception('FILESYSTEM_CANNOT_DELETE_FILES', $file, array(), $e);
529 }
530 }
531
532 /**
533 * {@inheritdoc}
534 */
535 public function rename($origin, $target, $overwrite = false)
536 {
537 try
538 {
539 $this->symfony_filesystem->rename($origin, $target, $overwrite);
540 }
541 catch (\Symfony\Component\Filesystem\Exception\IOException $e)
542 {
543 $msg = $e->getMessage();
544 $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"'));
545
546 throw new filesystem_exception('FILESYSTEM_CANNOT_RENAME_FILE', $filename, array(), $e);
547 }
548 }
549
550 /**
551 * {@inheritdoc}
552 */
553 public function symlink($origin_dir, $target_dir, $copy_on_windows = false)
554 {
555 try
556 {
557 $this->symfony_filesystem->symlink($origin_dir, $target_dir, $copy_on_windows);
558 }
559 catch (\Symfony\Component\Filesystem\Exception\IOException $e)
560 {
561 throw new filesystem_exception('FILESYSTEM_CANNOT_CREATE_SYMLINK', $origin_dir, array(), $e);
562 }
563 }
564
565 /**
566 * {@inheritdoc}
567 */
568 public function touch($files, $time = null, $access_time = null)
569 {
570 try
571 {
572 $this->symfony_filesystem->touch($files, $time, $access_time);
573 }
574 catch (\Symfony\Component\Filesystem\Exception\IOException $e)
575 {
576 // Try to recover filename
577 // By the time this is written that is at the end of the message
578 $error = trim($e->getMessage());
579 $file = substr($error, strrpos($error, ' '));
580
581 throw new filesystem_exception('FILESYSTEM_CANNOT_TOUCH_FILES', $file, array(), $e);
582 }
583 }
584
585 /**
586 * phpBB's implementation of is_writable
587 *
588 * @todo Investigate if is_writable is still buggy
589 *
590 * @param string $file file/directory to check if writable
591 *
592 * @return bool true if the given path is writable
593 */
594 protected function phpbb_is_writable($file)
595 {
596 if (file_exists($file))
597 {
598 // Canonicalise path to absolute path
599 $file = $this->realpath($file);
600
601 if (is_dir($file))
602 {
603 // Test directory by creating a file inside the directory
604 $result = @tempnam($file, 'i_w');
605
606 if (is_string($result) && file_exists($result))
607 {
608 unlink($result);
609
610 // Ensure the file is actually in the directory (returned realpathed)
611 return (strpos($result, $file) === 0) ? true : false;
612 }
613 }
614 else
615 {
616 $handle = new \SplFileInfo($file);
617
618 // Returns TRUE if writable, FALSE otherwise
619 return $handle->isWritable();
620 }
621 }
622 else
623 {
624 // file does not exist test if we can write to the directory
625 $dir = dirname($file);
626
627 if (file_exists($dir) && is_dir($dir) && $this->phpbb_is_writable($dir))
628 {
629 return true;
630 }
631 }
632
633 return false;
634 }
635
636 /**
637 * Try to resolve real path when PHP's realpath fails to do so
638 *
639 * @param string $path
640 * @return bool|string
641 */
642 protected function phpbb_own_realpath($path)
643 {
644 // Replace all directory separators with '/'
645 $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
646
647 $is_absolute_path = false;
648 $path_prefix = '';
649
650 if ($this->is_absolute_path($path))
651 {
652 $is_absolute_path = true;
653 }
654 else
655 {
656 // Resolve working directory and store it
657 if (is_null($this->working_directory))
658 {
659 if (function_exists('getcwd'))
660 {
661 $this->working_directory = str_replace(DIRECTORY_SEPARATOR, '/', getcwd());
662 }
663
664 //
665 // From this point on we really just guessing
666 // If chdir were called we screwed
667 //
668 else if (function_exists('debug_backtrace'))
669 {
670 $call_stack = debug_backtrace(0);
671 $this->working_directory = str_replace(DIRECTORY_SEPARATOR, '/', dirname($call_stack[count($call_stack) - 1]['file']));
672 }
673 else
674 {
675 //
676 // Assuming that the working directory is phpBB root
677 // we could use this as a fallback, when phpBB will use controllers
678 // everywhere this will be a safe assumption
679 //
680 //$dir_parts = explode(DIRECTORY_SEPARATOR, __DIR__);
681 //$namespace_parts = explode('\\', trim(__NAMESPACE__, '\\'));
682
683 //$namespace_part_count = count($namespace_parts);
684
685 // Check if we still loading from root
686 //if (array_slice($dir_parts, -$namespace_part_count) === $namespace_parts)
687 //{
688 // $this->working_directory = implode('/', array_slice($dir_parts, 0, -$namespace_part_count));
689 //}
690 //else
691 //{
692 // $this->working_directory = false;
693 //}
694
695 $this->working_directory = false;
696 }
697 }
698
699 if ($this->working_directory !== false)
700 {
701 $is_absolute_path = true;
702 $path = $this->working_directory . '/' . $path;
703 }
704 }
705
706 if ($is_absolute_path)
707 {
708 if (defined('PHP_WINDOWS_VERSION_MAJOR'))
709 {
710 $path_prefix = $path[0] . ':';
711 $path = substr($path, 2);
712 }
713 else
714 {
715 $path_prefix = '';
716 }
717 }
718
719 $resolved_path = $this->resolve_path($path, $path_prefix, $is_absolute_path);
720 if ($resolved_path === false)
721 {
722 return false;
723 }
724
725 if (!@file_exists($resolved_path) || (!@is_dir($resolved_path . '/') && !is_file($resolved_path)))
726 {
727 return false;
728 }
729
730 // Return OS specific directory separators
731 $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved_path);
732
733 // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
734 if (substr($resolved, -1) === DIRECTORY_SEPARATOR)
735 {
736 return substr($resolved, 0, -1);
737 }
738
739 return $resolved;
740 }
741
742 /**
743 * Convert file(s) to \Traversable object
744 *
745 * This is the same function as Symfony's toIterator, but that is private
746 * so we cannot use it.
747 *
748 * @param string|array|\Traversable $files filename/list of filenames
749 * @return \Traversable
750 */
751 protected function to_iterator($files)
752 {
753 if (!$files instanceof \Traversable)
754 {
755 $files = new \ArrayObject(is_array($files) ? $files : array($files));
756 }
757
758 return $files;
759 }
760
761 /**
762 * Try to resolve symlinks in path
763 *
764 * @param string $path The path to resolve
765 * @param string $prefix The path prefix (on windows the drive letter)
766 * @param bool $absolute Whether or not the path is absolute
767 * @param bool $return_array Whether or not to return path parts
768 *
769 * @return string|array|bool returns the resolved path or an array of parts of the path if $return_array is true
770 * or false if path cannot be resolved
771 */
772 protected function resolve_path($path, $prefix = '', $absolute = false, $return_array = false)
773 {
774 if ($return_array)
775 {
776 $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
777 }
778
779 trim ($path, '/');
780 $path_parts = explode('/', $path);
781 $resolved = array();
782 $resolved_path = $prefix;
783 $file_found = false;
784
785 foreach ($path_parts as $path_part)
786 {
787 if ($file_found)
788 {
789 return false;
790 }
791
792 if (empty($path_part) || ($path_part === '.' && ($absolute || !empty($resolved))))
793 {
794 continue;
795 }
796 else if ($absolute && $path_part === '..')
797 {
798 if (empty($resolved))
799 {
800 // No directories above root
801 return false;
802 }
803
804 array_pop($resolved);
805 $resolved_path = false;
806 }
807 else if ($path_part === '..' && !empty($resolved) && !in_array($resolved[count($resolved) - 1], array('.', '..')))
808 {
809 array_pop($resolved);
810 $resolved_path = false;
811 }
812 else
813 {
814 if ($resolved_path === false)
815 {
816 if (empty($resolved))
817 {
818 $resolved_path = ($absolute) ? $prefix . '/' . $path_part : $path_part;
819 }
820 else
821 {
822 $tmp_array = $resolved;
823 if ($absolute)
824 {
825 array_unshift($tmp_array, $prefix);
826 }
827
828 $resolved_path = implode('/', $tmp_array);
829 }
830 }
831
832 $current_path = $resolved_path . '/' . $path_part;
833
834 // Resolve symlinks
835 if (@is_link($current_path))
836 {
837 if (!function_exists('readlink'))
838 {
839 return false;
840 }
841
842 $link = readlink($current_path);
843
844 // Is link has an absolute path in it?
845 if ($this->is_absolute_path($link))
846 {
847 if (defined('PHP_WINDOWS_VERSION_MAJOR'))
848 {
849 $prefix = $link[0] . ':';
850 $link = substr($link, 2);
851 }
852 else
853 {
854 $prefix = '';
855 }
856
857 $resolved = $this->resolve_path($link, $prefix, true, true);
858 $absolute = true;
859 }
860 else
861 {
862 $resolved = $this->resolve_path($resolved_path . '/' . $link, $prefix, $absolute, true);
863 }
864
865 if (!$resolved)
866 {
867 return false;
868 }
869
870 $resolved_path = false;
871 }
872 else if (@is_dir($current_path . '/'))
873 {
874 $resolved[] = $path_part;
875 $resolved_path = $current_path;
876 }
877 else if (@is_file($current_path))
878 {
879 $resolved[] = $path_part;
880 $resolved_path = $current_path;
881 $file_found = true;
882 }
883 else
884 {
885 return false;
886 }
887 }
888 }
889
890 // If at the end of the path there were a .. or .
891 // we need to build the path again.
892 // Only doing this when a string is expected in return
893 if ($resolved_path === false && $return_array === false)
894 {
895 if (empty($resolved))
896 {
897 $resolved_path = ($absolute) ? $prefix . '/' : './';
898 }
899 else
900 {
901 $tmp_array = $resolved;
902 if ($absolute)
903 {
904 array_unshift($tmp_array, $prefix);
905 }
906
907 $resolved_path = implode('/', $tmp_array);
908 }
909 }
910
911 return ($return_array) ? $resolved : $resolved_path;
912 }
913 }
914