/** * Resolves a given $path into given $referenceDirPath if possible. * <b>WARNING:</b> * <ul> * <li>This function is not to be used on URL as (file://..., ftp://..., etc.), only *simple* paths (/my/simple/path).</li> * <li>This function may output incorrect results on Windows platforms when $path is located on a different drive letter * from $referenceDirPath.</li> * </ul> * * @param string $path The path of a file to resolve<br /> * (e.g. "/Documents/Images/..",<br /> * or "./users/john/files/Documents/Images/..",<br /> * or "/home/john/eyeos/users/john/files/Documents/Images/..",<br /> * or "C:\My Documents\john\eyeos\users\john\files\Documents\Images\..") * @param string $referenceDirPath The path of the directory used as a reference for resolution * @param int $flags * OS_WINDOWS: Set it to force resolution assuming a Windows filesystem.<br /> * OS_UNIX: Set it to force resolution assuming a UNIX filesystem. <br /> * RESOLVEPATH_RETURN_REFDIR_RELATIVE: Set it to get a resolved path from current PHP directory (getcwd) * (e.g. "./users/john/files/Documents"), * or don't to get a resolved path in the reference folder (e.g. "/Documents")<br /> * RESOLVEPATH_NOT_LOCALHOST: Set it to resolve the given path as a normal file on the filesystem, * or don't to resolve it according to the reference path only.<br /> * @return mixed The resolved path or FALSE if the given path is not in the reference directory or if an error occured * @throws InvalidArgumentException */ public static function resolvePath($path, $referenceDirPath, $flags = self::NONE) { if ($flags & self::OS_WINDOWS) { $isWindows = true; } elseif ($flags & self::OS_UNIX) { $isWindows = false; } else { $isWindows = self::isCurrentOS(self::OS_WINDOWS); } $path = AdvancedPathLib::unifyPath($path); $resolveOnLocalHost = !($flags & self::RESOLVEPATH_NOT_LOCALHOST); //both following var are used in the next different parts to analyze its structure, but we initialize them //now to avoid multiple calls to self::realpath() $absolutePath = self::realpath($path, $resolveOnLocalHost); $absolutePathReferenceDir = self::realpath($referenceDirPath, $resolveOnLocalHost); //$path is a relative path to the current PHP dir // -OR- $path is a full absolute path if (stripos($path, './') === 0 || $path == $absolutePath) { //designated path is NOT in the reference directory => ERROR if (stripos($absolutePath, $absolutePathReferenceDir) !== 0) { throw new InvalidArgumentException('Unable to process paths resolution: ' . $path . ' is not located in ' . $referenceDirPath . '.'); } $path = $absolutePath; } //$path is an absolute path // UN*X: /home/john/eyeos/eyeos/users/john/files/Documents // WIN: C:\My Documents\john\eyeos\eyeos\users\john\files\Documents if (stripos($path, $absolutePathReferenceDir) === 0) { $relativePath = utf8_substr($absolutePath, utf8_strlen($absolutePathReferenceDir)); $path = $relativePath; } //$path is a relative path if (stripos($path, $referenceDirPath) === 0) { $relativePath = utf8_substr($path, utf8_strlen($referenceDirPath)); $path = $relativePath; } if ($isWindows) { //$path starts with a Windows drive letter but referenceDir doesn't => ERROR if (preg_match('/^([a-z]{1}):/i', $path)) { throw new InvalidArgumentException('Unable to process paths resolution: ' . $path . ' starts with a Windows drive letter but ' . $referenceDirPath . ' does not.'); } } //designated path is NOT in the reference directory => ERROR if (stripos(self::realpath($referenceDirPath . self::dirname($path)), $absolutePathReferenceDir) === false) { throw new InvalidArgumentException('Unable to process paths resolution: ' . $path . ' is not located in ' . $referenceDirPath . '.'); } $resolvedPath = ''; if ($flags & self::RESOLVEPATH_RETURN_REFDIR_RELATIVE) { $resolvedPath = '/' . utf8_substr(self::realpath($referenceDirPath . '/' . $path), utf8_strlen(self::unifyPath($absolutePathReferenceDir . '/'))); } else { $resolvedPath = '.' . utf8_substr(self::realpath($referenceDirPath . '/' . $path), utf8_strlen(self::realpath('.'))); } return $resolvedPath; }
public function testUnifyPath() { $this->assertEquals('/path/to/myFile.ext', AdvancedPathLib::unifyPath('/path//to///myFile.ext')); $this->assertEquals('/path/to/myDir/', AdvancedPathLib::unifyPath('/path//to///myDir////')); $this->assertEquals('C:/path/to/myFile.ext', AdvancedPathLib::unifyPath('C:\\path\\to\\myFile.ext')); $this->assertEquals('file://C:/path/to/myFile.ext', AdvancedPathLib::unifyPath('file://C:\\path\\to\\myFile.ext', true)); }
/** * @param string $pattern Filter pattern (same as *NIX shell) * @param int $flags GLOB_NORMAL | GLOB_ONLY_DIR | GLOB_DIR_IGNORE_PATTERN * | GLOB_DIR_FIRST | GLOB_FORCE_SCANDIR | GLOB_CASEINSENSITIVE * (@see class AdvancedPathLib) * @return array(IFile) The list of the files contained in the "file" itself if $this * is a directory, or the files contained in the parent directory if $this is a * normal file */ public function listFiles($pattern = '*', $flags = AdvancedPathLib::GLOB_NORMAL) { if (is_array($pattern)) { Logger::getLogger('system.services.FileSystem.FTPFile')->warn('FTPFile::listFiles() does not handle array as $pattern yet, using "*" instead.'); //FIXME --NOT IMPLEMENTED-- $pattern = '*'; } if ($this->isDirectory()) { $dir = $this; } else { $dir = $this->getParentFile(); } if ($flags & AdvancedPathLib::GLOB_CASEINSENSITIVE) { $pattern = mb_sql_regcase($pattern); } $res = $this->getConnection(); try { //first let's try with -A option (LIST "ALL"), but some servers may fail $rawList = @ftp_rawlist($res, '-a ' . $dir->getPathFromRoot()); if ($rawList === false) { //then let's try with the classical LIST command alone $rawList = @ftp_rawlist($res, $dir->getPathFromRoot()); if ($rawList === false) { throw new EyeIOException('Unable to list files in directory ' . AdvancedPathLib::getURLForDisplay($this->path) . '.'); } } } catch (EyeErrorException $e) { throw new EyeIOException('Unable to list files in directory ' . AdvancedPathLib::getURLForDisplay($this->path) . '.', 0, $e); } $parsedList = self::parseRawList($rawList, false); $filesObjects = array(); foreach ($parsedList as $fileInfo) { if ($flags & AdvancedPathLib::GLOB_ONLY_DIR && $fileInfo['type'] != 'd') { continue; } if (AdvancedPathLib::fnmatch($pattern, $fileInfo['name']) !== false || $flags & AdvancedPathLib::GLOB_DIR_IGNORE_PATTERN && $fileInfo['type'] == 'd') { $linkTarget = false; if ($fileInfo['type'] == 'l') { $parsedLinkName = self::parseLinkName($this, $fileInfo['name']); if (is_array($parsedLinkName)) { $fileInfo['name'] = $parsedLinkName[0]; $linkTarget = $parsedLinkName[1]; } } $fileParams = array('isDirectory' => $fileInfo['type'] == 'd' ? true : false, 'isFile' => $fileInfo['type'] == 'd' || $fileInfo['type'] == 'l' ? false : true, 'isLink' => $fileInfo['type'] == 'l' ? true : false, 'permissions' => $fileInfo['type'] . $fileInfo['perms'], 'size' => $fileInfo['size'], 'linkTarget' => $linkTarget); $newFileUrlParts = $dir->getURLComponents(); $newFileUrlParts['path'] = AdvancedPathLib::unifyPath($newFileUrlParts['path'] . '/' . $fileInfo['name']); $thisClass = get_class($this); $newFile = new $thisClass(AdvancedPathLib::buildURL($newFileUrlParts), $fileParams); $filesObjects[] = $newFile; } } if ($flags & AdvancedPathLib::GLOB_DIR_FIRST) { $filesObjectsOrdered = array(); //looking for directories foreach ($filesObjects as $i => $fileObject) { if ($fileObject->isDirectory()) { $filesObjectsOrdered[] = $fileObject; } } //looking for files and links foreach ($filesObjects as $i => $fileObject) { if ($fileObject->isFile() || $fileObject->isLink()) { $filesObjectsOrdered[] = $fileObject; } } $filesObjects = $filesObjectsOrdered; } return $filesObjects; }
/** * @return bool TRUE if the file has been successfully renamed. * @throws EyeIOException */ public function renameTo($newName) { if (!$this->exists()) { throw new EyeFileNotFoundException($this->path . ' does not exist.'); } if (!$newName) { return true; } $urlParts = AdvancedPathLib::parse_url($this->path); $urlParts['path'] = AdvancedPathLib::unifyPath(dirname($urlParts['path']) . '/' . $newName); $newPath = AdvancedPathLib::buildURL($urlParts); if ($this->exists()) { $path = AdvancedPathLib::getPhpLocalHackPath($this->path); $newPath = AdvancedPathLib::getPhpLocalHackPath($newPath); try { if (rename($path, $newPath)) { $this->path = $newPath; return true; } throw new EyeIOException('Unable to rename file ' . $this->path . '.'); } catch (EyeErrorException $e) { throw new EyeIOException('Unable to rename file ' . $this->path . '.', 0, $e); } } else { $this->path = $newPath; return true; } }