ParsePath($path); if($parsed_path != null) { $this->path = $parsed_path; } else { throw new Exception("Invalid path specified"); } } public function ValidatePath($root) { $root_path = $this->ParsePath($root); if($root_path != null) { if($this->RelativeDepth($root) >= 0) { $root_stack = explode("/", $root_path); $path_stack = explode("/", $this->path); for($i = 0; $i < count($root_stack); $i++) { if($root_stack[$i] != $path_stack[$i]) { return false; } } return true; } else { return false; } } else { throw new Exception("Specified root path is invalid."); } } public function RelativeDepth($root) { $root_length = substr_count($this->ParsePath($root), "/"); $path_length = substr_count($this->path, "/"); return $path_length - $root_length; } private function RemoveTrailingSlash($path) { if(substr($path, strlen($path) - 1) == "/") { return substr($path, 0, strlen($path) - 1); } else { return $path; } } private function ParsePath($path) { /* We use a custom function for this since we just want to resolve the path no matter what, * and the realpath() function will return false if the path either doesn't exist or is not * accessible. */ $path = $this->RemoveTrailingSlash($path); if(substr($path, 0, 1) == "/") { /* Absolute path */ return $path; } else { $path_elements = explode("/", $path); if(substr($path, 0, 1) == "~") { /* Home directory path */ if(!empty($_SERVER['home'])) { $homedir = $_SERVER['home']; } elseif(getenv("HOME") != null) { $homedir = getenv("HOME"); } elseif(function_exists("posix_getuid") && function_exists("posix_getpwuid")) { $userinfo = posix_getpwuid(posix_getuid()); $homedir = $userinfo['dir']; } else { throw new Exception("Could not find a way to get the home directory of the current user."); } $homedir = $this->RemoveTrailingSlash($homedir); $stack = explode("/", $homedir); array_shift($path_elements); } else { /* Relative path */ $basepath = $this->RemoveTrailingSlash(getcwd()); $stack = explode("/", $basepath); } foreach($path_elements as $element) { if($element == ".") { /* Ignore */ } elseif($element == "..") { /* Go up one directory */ if(count($stack) > 1) { array_pop($stack); } else { /* There are no elements left to pop, this is an invalid path. */ return null; } } else { /* Append to path */ $stack[] = $element; } } return implode("/", $stack); } } }