diff --git a/composer.json b/composer.json index 44dd83a2f..025d10fe6 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { - "name": "knplabs/gaufrette", + "name": "FaustineLarmagna/gaufrette", "type": "library", - "description": "PHP5 library that provides a filesystem abstraction layer", + "description": "Fork of knplabs/gaufrette library: PHP5 library that provides a filesystem abstraction layer", "keywords": ["file", "filesystem", "media", "abstraction"], "minimum-stability": "dev", "homepage": "http://knplabs.com", @@ -14,6 +14,10 @@ { "name": "The contributors", "homepage": "http://github.com/knplabs/Gaufrette/contributors" + }, + { + "name": "Faustine Larmagna", + "homepage": "http://github.com/FausineLarmagna" } ], "repositories": [ diff --git a/src/Gaufrette/Adapter/Ftp.php b/src/Gaufrette/Adapter/Ftp.php index 6e1e93b57..ed02151ca 100644 --- a/src/Gaufrette/Adapter/Ftp.php +++ b/src/Gaufrette/Adapter/Ftp.php @@ -12,6 +12,7 @@ * * @package Gaufrette * @author Antoine Hérault + * @author */ class Ftp implements Adapter, FileFactory, @@ -54,93 +55,122 @@ public function __construct($directory, $host, $options = array()) } /** - * {@inheritDoc} + * @param string $key + * @return bool|string */ public function read($key) { - $this->ensureDirectoryExists($this->directory, $this->create); + //change to the directory that contain the file + $this->moveToTargetDirectory($key); + $file = basename($key); $temp = fopen('php://temp', 'r+'); - if (!ftp_fget($this->getConnection(), $temp, $this->computePath($key), $this->mode)) { + if (!ftp_fget($this->getConnection(), $temp, $file, $this->mode)) { + //change back to ftp root directory + $this->changeDirectory($this->directory); return false; } rewind($temp); $contents = stream_get_contents($temp); + //change back to ftp root directory + $this->changeDirectory($this->directory); fclose($temp); return $contents; } /** - * {@inheritDoc} + * @param string $key + * @param string $content + * @return bool|int */ public function write($key, $content) { - $this->ensureDirectoryExists($this->directory, $this->create); - - $path = $this->computePath($key); - $directory = dirname($path); - - $this->ensureDirectoryExists($directory, true); + //change to the directory that will contain the written file + $this->moveToTargetDirectory($key); + $file = basename($key); $temp = fopen('php://temp', 'r+'); $size = fwrite($temp, $content); rewind($temp); - if (!ftp_fput($this->getConnection(), $path, $temp, $this->mode)) { + if (!ftp_fput($this->getConnection(), $file, $temp, $this->mode)) { + //change back to ftp root directory + $this->changeDirectory($this->directory); fclose($temp); return false; } + //change back to ftp root directory + $this->changeDirectory($this->directory); fclose($temp); return $size; } /** - * {@inheritDoc} + * @param string $sourceKey + * @param string $targetKey + * @return bool */ public function rename($sourceKey, $targetKey) { - $this->ensureDirectoryExists($this->directory, $this->create); - $sourcePath = $this->computePath($sourceKey); $targetPath = $this->computePath($targetKey); + $targetDirectory = dirname($targetPath); + + $this->ensureDirectoryExists($targetDirectory, true); - $this->ensureDirectoryExists(dirname($targetPath), true); + if (dirname($sourcePath) == $targetDirectory) { + //change to the directory that contains the file to rename + $this->changeDirectory($targetDirectory); - return ftp_rename($this->getConnection(), $sourcePath, $targetPath); + $result = ftp_rename($this->getConnection(), basename($sourceKey), basename($targetKey)); + + //change back to ftp root directory + $this->changeDirectory($this->directory); + } else { + // don't change current ftp directory. May fail if paths are too long + $result = ftp_rename($this->getConnection(), $sourcePath, $targetPath); + } + + return $result; } /** - * {@inheritDoc} + * @param string $key + * @return bool */ public function exists($key) { - $this->ensureDirectoryExists($this->directory, $this->create); + //change to the directory that contain the source file + $this->moveToTargetDirectory($key); - $file = $this->computePath($key); - $lines = ftp_rawlist($this->getConnection(), '-al ' . dirname($file)); + $lines = ftp_rawlist($this->getConnection(), '-al ' . '.'); if (false === $lines) { return false; } - $pattern = '{(?) '.preg_quote(basename($file)).'( -> |$)}m'; + $pattern = '{(?) '.preg_quote(basename($key)).'( -> |$)}m'; foreach ($lines as $line) { if (preg_match($pattern, $line)) { + //change back to ftp root directory + $this->changeDirectory($this->directory); return true; } } + //change back to ftp root directory + $this->changeDirectory($this->directory); return false; } /** - * {@inheritDoc} + * @return mixed */ public function keys() { @@ -152,7 +182,8 @@ public function keys() } /** - * {@inheritDoc} + * @param string $prefix + * @return array */ public function listKeys($prefix = '') { @@ -181,13 +212,20 @@ public function listKeys($prefix = '') } /** - * {@inheritDoc} + * @param string $key + * @return int + * @throws \RuntimeException */ public function mtime($key) { - $this->ensureDirectoryExists($this->directory, $this->create); + //change directory to avoid truncation of too long paths + $this->moveToTargetDirectory($key); + $file = basename($key); + + $mtime = ftp_mdtm($this->getConnection(), $file); - $mtime = ftp_mdtm($this->getConnection(), $this->computePath($key)); + //change back to ftp root directory + $this->changeDirectory($this->directory); // the server does not support this function if (-1 === $mtime) { @@ -198,21 +236,30 @@ public function mtime($key) } /** - * {@inheritDoc} + * @param string $key + * @return bool */ public function delete($key) { - $this->ensureDirectoryExists($this->directory, $this->create); + //change to directory containing the $key to delete + $this->moveToTargetDirectory($key); + $keyName = basename($key); if ($this->isDirectory($key)) { - return ftp_rmdir($this->getConnection(), $this->computePath($key)); + $result = ftp_rmdir($this->getConnection(), $keyName); + } else { + $result = ftp_delete($this->getConnection(), $keyName); } - return ftp_delete($this->getConnection(), $this->computePath($key)); + //move back to ftp root directory + $this->changeDirectory($this->directory); + + return $result; } /** - * {@inheritDoc} + * @param string $key + * @return bool */ public function isDirectory($key) { @@ -263,13 +310,15 @@ public function listDirectory($directory = '') $this->fileData = array_merge($fileData, $this->fileData); return array( - 'keys' => array_keys($fileData), - 'dirs' => $dirs + 'keys' => array_keys($fileData), + 'dirs' => $dirs ); } /** - * {@inheritDoc} + * @param string $key + * @param Filesystem $filesystem + * @return File */ public function createFile($key, Filesystem $filesystem) { @@ -342,6 +391,8 @@ protected function createDirectory($directory) */ private function isDir($directory) { + $currentPath = ftp_pwd($this->getConnection()); + if ('/' === $directory) { return true; } @@ -350,12 +401,17 @@ private function isDir($directory) return false; } - // change directory again to return in the base directory - ftp_chdir($this->getConnection(), $this->directory); + // change directory again to return to where we were + ftp_chdir($this->getConnection(), $currentPath); return true; } + /** + * @param string $directory + * @param bool|true $onlyKeys + * @return array + */ private function fetchKeys($directory = '', $onlyKeys = true) { $directory = preg_replace('/^[\/]*([^\/].*)$/', '/$1', $directory); @@ -458,7 +514,8 @@ private function parseRawlist(array $rawlist) /** * Computes the path for the given key * - * @param string $key + * @param $key + * @return string */ private function computePath($key) { @@ -502,7 +559,7 @@ private function connect() $this->connection = ftp_connect($this->host, $this->port); } else { if(function_exists('ftp_ssl_connect')) { - $this->connection = ftp_ssl_connect($this->host, $this->port); + $this->connection = ftp_ssl_connect($this->host, $this->port); } else { throw new \RuntimeException('This Server Has No SSL-FTP Available.'); } @@ -553,8 +610,48 @@ private function close() } } + /** + * @param $info + * @return bool + */ private function isLinuxListing($info) { return count($info) >= 9; } -} + + /** + * Change current directory to the specified directory + * + * @param string $directory + * @throws \RuntimeException + * @return bool + */ + protected function changeDirectory($directory) + { + $moved = ftp_chdir($this->getConnection(), $directory); + + if (false === $moved) { + throw new \RuntimeException(sprintf('Could not move to the \'%s\' directory.', $directory)); + } + } + + /** + * Change current directory to the directory of + * the $key file path. + * This allows to avoid truncation of too long file paths + * or failure of ftp php functions due to too long file paths + * + * @param string $key + */ + protected function moveToTargetDirectory($key) + { + $this->ensureDirectoryExists($this->directory, $this->create); + + $path = $this->computePath($key); + $directory = dirname($path); + + $this->ensureDirectoryExists($directory, true); + + $this->changeDirectory($directory); + } +} \ No newline at end of file