From 4761d30ceb295143e72c59f91d19015d6b656ad5 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 14 Sep 2008 15:47:44 +0200 Subject: [PATCH] rewrote the fullpath function FS#1462 The fullpath function now correctly handles windows drive letter paths and UNC paths making sure that those are not destroyed with upper dir .. notation. Unit tests where added. darcs-hash:20080914134744-7ad00-9abf5931d910a0b12979b1f69b090e8ecd568c71.gz --- _test/cases/inc/init_fullpath.test.php | 75 ++++++++++++++++++++++++++ _test/runtests.php | 1 + inc/init.php | 62 ++++++++++++--------- 3 files changed, 114 insertions(+), 24 deletions(-) create mode 100644 _test/cases/inc/init_fullpath.test.php diff --git a/_test/cases/inc/init_fullpath.test.php b/_test/cases/inc/init_fullpath.test.php new file mode 100644 index 000000000..e2acc35a5 --- /dev/null +++ b/_test/cases/inc/init_fullpath.test.php @@ -0,0 +1,75 @@ + '/foo/bar/baz', + '/foo//bar/baz' => '/foo/bar/baz', + '/foo/../bar/baz' => '/bar/baz', + '/foo/./bar/baz' => '/foo/bar/baz', + '/foo/bar/..' => '/foo', + '/foo/bar/../../../baz' => '/baz', + + 'foo/bar/baz' => '/absolute/path/foo/bar/baz', + 'foo//bar/baz' => '/absolute/path/foo/bar/baz', + 'foo/../bar/baz' => '/absolute/path/bar/baz', + 'foo/./bar/baz' => '/absolute/path/foo/bar/baz', + 'foo/bar/..' => '/absolute/path/foo', + 'foo/bar/../../../baz' => '/absolute/baz', + ); + + foreach($tests as $from => $to){ + $info = "Testing '$from' resulted in '".fullpath($from)."'"; + $this->signal('failinfo',$info); + + $this->assertEqual(fullpath($from),$to); + } + + + $_SERVER['SCRIPT_FILENAME'] = $base; + unset($GLOBALS['DOKU_UNITTEST_ASSUME_WINDOWS']); + } + + function test_windows_paths(){ + $base = $_SERVER['SCRIPT_FILENAME']; + $_SERVER['SCRIPT_FILENAME'] = '/absolute/path/self.php'; + $GLOBALS['DOKU_UNITTEST_ASSUME_WINDOWS'] = true; + + // paths to check + $tests = array( + 'c:foo/bar/baz' => 'c:foo/bar/baz', + 'c:foo//bar/baz' => 'c:foo/bar/baz', + 'c:foo/../bar/baz' => 'c:bar/baz', + 'c:foo/./bar/baz' => 'c:foo/bar/baz', + 'c:foo/bar/..' => 'c:foo', + 'c:foo/bar/../../../baz' => 'c:baz', + + '\\\\server\\share/foo/bar/baz' => '\\\\server\\share/foo/bar/baz', + '\\\\server\\share/foo//bar/baz' => '\\\\server\\share/foo/bar/baz', + '\\\\server\\share/foo/../bar/baz' => '\\\\server\\share/bar/baz', + '\\\\server\\share/foo/./bar/baz' => '\\\\server\\share/foo/bar/baz', + '\\\\server\\share/foo/bar/..' => '\\\\server\\share/foo', + '\\\\server\\share/foo/bar/../../../baz' => '\\\\server\\share/baz', + ); + + foreach($tests as $from => $to){ + $info = "Testing '$from' resulted in '".fullpath($from)."'"; + $this->signal('failinfo',$info); + + $this->assertEqual(fullpath($from),$to); + } + + + $_SERVER['SCRIPT_FILENAME'] = $base; + unset($GLOBALS['DOKU_UNITTEST_ASSUME_WINDOWS']); + } + +} +//Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/_test/runtests.php b/_test/runtests.php index e3489b4cf..c4a4f36b4 100755 --- a/_test/runtests.php +++ b/_test/runtests.php @@ -2,6 +2,7 @@ * @author * @link http://de3.php.net/manual/en/function.realpath.php#75992 */ function fullpath($path){ - $iswin = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'); - $isunc = 0===strpos($path,'\\\\'); - if($iswin) $path = str_replace('\\','/',$path); // windows compatibility + static $run = 0; + $root = ''; + $iswin = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' || $GLOBALS['DOKU_UNITTEST_ASSUME_WINDOWS']); - // check if path begins with "/" or "c:" ie. is absolute - // if it isnt concat with script path - if (!$isunc && - ((!$iswin && $path{0} !== '/') || - ($iswin && $path{1} !== ':'))) { - $base=dirname($_SERVER['SCRIPT_FILENAME']); - $path=$base."/".$path; + // find the (indestructable) root of the path - keeps windows stuff intact + if($path{0} == '/'){ + $root = '/'; + }elseif($iswin){ + // match drive letter and UNC paths + if(preg_match('!^([a-zA-z]:)(.*)!',$path,$match)){ + $root = $match[1]; + $path = $match[2]; + }else if(preg_match('!^(\\\\\\\\[^\\\\/]+\\\\[^\\\\/]+[\\\\/])(.*)!',$path,$match)){ + $root = $match[1]; + $path = $match[2]; + } } + $path = str_replace('\\','/',$path); + + // if the given path wasn't absolute already, prepend the script path and retry + if(!$root){ + $base = dirname($_SERVER['SCRIPT_FILENAME']); + $path = $base.'/'.$path; + if($run == 0){ // avoid endless recursion when base isn't absolute for some reason + $run++; + return fullpath($path,1); + } + } + $run = 0; // canonicalize $path=explode('/', $path); @@ -471,15 +487,13 @@ function fullpath($path){ } array_push($newpath, $p); } - $finalpath = implode('/', $newpath); - if($isunc) $finalpath = '//'.$finalpath; - if(!$iswin) $finalpath = '/'.$finalpath; + $finalpath = $root.implode('/', $newpath); - // check then return valid path or filename - if (@file_exists($finalpath)) { - return ($finalpath); + // check for existance (except when unit testing) + if(!defined('DOKU_UNITTEST') && !@file_exists($finalpath)) { + return false; } - else return false; + return $finalpath; }