note 48241 deleted from function.realpath by danbrown
| From: | danbrown@php.net | Date: | Mon, 01 Jun 2009 13:03:50 +0000 |
| Subject: | note 48241 deleted from function.realpath by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-156243@lists.php.net to get a copy of this message | ||
Note Submitter: carlosreche at yahoo dot com
----
In my last function, it will always discard "../" if there are no more parent dirs to go
back. But it's a mistake! For example, relative paths like "../../downloads" returns
"downloads/", and it should return exactly the same entry (because parent directories for
"downloads" may exist in this case). Well, I've corrected this bug. Now:
"C:/downloads/../../../" returns "C:/"
"downloads/../../../" returns "../../"
<?php
function real_path($path)
{
if ($path == "")
{
return false;
}
$path = trim(preg_replace("/\\\\/", "/", (string)$path));
if (!preg_match("/(\.\w{1,4})$/", $path) &&
!preg_match("/\?[^\\/]+$/", $path) &&
!preg_match("/\\/$/", $path))
{
$path .= '/';
}
$pattern = "/^(\\/|\w:\\/|https?:\\/\\/[^\\/]+\\/)?(.*)$/i";
preg_match_all($pattern, $path, $matches, PREG_SET_ORDER);
$path_tok_1 = $matches[0][1];
$path_tok_2 = $matches[0][2];
$path_tok_2 = preg_replace(
array("/^\\/+/", "/\\/+/"),
array("", "/"),
$path_tok_2);
$path_parts = explode("/", $path_tok_2);
$real_path_parts = array();
for ($i = 0, $real_path_parts = array(); $i < count($path_parts); $i++)
{
if ($path_parts[$i] == '.')
{
continue;
}
else if ($path_parts[$i] == '..')
{
if ( (isset($real_path_parts[0]) && $real_path_parts[0] != '..')
|| ($path_tok_1 != "") )
{
array_pop($real_path_parts);
continue;
}
}
array_push($real_path_parts, $path_parts[$i]);
}
return $path_tok_1 . implode('/', $real_path_parts);
}
?>