From 5a796951810bd33d071f417176757a2fa486f7b1 Mon Sep 17 00:00:00 2001 From: FaustineLarmagna Date: Wed, 24 Feb 2016 11:30:11 +0100 Subject: [PATCH 1/6] Ftp adapter: handling long file paths by allowing to change current ftp directory --- src/Gaufrette/Adapter/Ftp.php | 117 ++++++++++++++++++++++++++-------- 1 file changed, 91 insertions(+), 26 deletions(-) diff --git a/src/Gaufrette/Adapter/Ftp.php b/src/Gaufrette/Adapter/Ftp.php index 6e1e93b57..a1204deb1 100644 --- a/src/Gaufrette/Adapter/Ftp.php +++ b/src/Gaufrette/Adapter/Ftp.php @@ -12,10 +12,11 @@ * * @package Gaufrette * @author Antoine Hérault + * @author */ -class Ftp implements Adapter, - FileFactory, - ListKeysAware +class FtpAdapter implements Adapter, + FileFactory, + ListKeysAware { protected $connection = null; protected $directory; @@ -54,7 +55,8 @@ public function __construct($directory, $host, $options = array()) } /** - * {@inheritDoc} + * @param string $key + * @return bool|string */ public function read($key) { @@ -74,34 +76,39 @@ public function read($key) } /** - * {@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) { @@ -116,7 +123,8 @@ public function rename($sourceKey, $targetKey) } /** - * {@inheritDoc} + * @param string $key + * @return bool */ public function exists($key) { @@ -140,7 +148,7 @@ public function exists($key) } /** - * {@inheritDoc} + * @return mixed */ public function keys() { @@ -152,7 +160,8 @@ public function keys() } /** - * {@inheritDoc} + * @param string $prefix + * @return array */ public function listKeys($prefix = '') { @@ -181,13 +190,19 @@ 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(), $this->computePath($key)); + $mtime = ftp_mdtm($this->getConnection(), $file); + //change back to ftp root directory + $this->changeDirectory($this->directory); // the server does not support this function if (-1 === $mtime) { @@ -198,7 +213,8 @@ public function mtime($key) } /** - * {@inheritDoc} + * @param string $key + * @return bool */ public function delete($key) { @@ -212,7 +228,8 @@ public function delete($key) } /** - * {@inheritDoc} + * @param string $key + * @return bool */ public function isDirectory($key) { @@ -263,13 +280,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) { @@ -356,6 +375,11 @@ private function isDir($directory) return true; } + /** + * @param string $directory + * @param bool|true $onlyKeys + * @return array + */ private function fetchKeys($directory = '', $onlyKeys = true) { $directory = preg_replace('/^[\/]*([^\/].*)$/', '/$1', $directory); @@ -458,7 +482,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 +527,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 +578,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 filepath. + * This allows to avoid truncation of too long file paths + * or failure of ftp_mdtm function 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); + } } From 2d5e8b589cfbfe3887fe1ecd5c58be7f059db592 Mon Sep 17 00:00:00 2001 From: FaustineLarmagna Date: Wed, 24 Feb 2016 12:14:24 +0100 Subject: [PATCH 2/6] changed composer.json details --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 44dd83a2f..d2a4f4cb9 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", From ea3a3a357130ff58295be8859af8226643ee1375 Mon Sep 17 00:00:00 2001 From: FaustineLarmagna Date: Wed, 24 Feb 2016 12:36:29 +0100 Subject: [PATCH 3/6] Added author --- composer.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/composer.json b/composer.json index d2a4f4cb9..025d10fe6 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,10 @@ { "name": "The contributors", "homepage": "http://github.com/knplabs/Gaufrette/contributors" + }, + { + "name": "Faustine Larmagna", + "homepage": "http://github.com/FausineLarmagna" } ], "repositories": [ From 8a38cfbda998db86dd9f6dc79ff06849656679e5 Mon Sep 17 00:00:00 2001 From: FaustineLarmagna Date: Wed, 24 Feb 2016 18:31:06 +0100 Subject: [PATCH 4/6] changed wrong filename --- src/Gaufrette/Adapter/Ftp.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Gaufrette/Adapter/Ftp.php b/src/Gaufrette/Adapter/Ftp.php index a1204deb1..a5e4adc3e 100644 --- a/src/Gaufrette/Adapter/Ftp.php +++ b/src/Gaufrette/Adapter/Ftp.php @@ -14,9 +14,9 @@ * @author Antoine Hérault * @author */ -class FtpAdapter implements Adapter, - FileFactory, - ListKeysAware +class Ftp implements Adapter, + FileFactory, + ListKeysAware { protected $connection = null; protected $directory; From 28807f4cd06d23fab29a6eaffc6ba8deeb0d8c7d Mon Sep 17 00:00:00 2001 From: FaustineLarmagna Date: Mon, 29 Feb 2016 14:45:49 +0100 Subject: [PATCH 5/6] Modified other functions that needed changeDirectory to work with long file paths --- src/Gaufrette/Adapter/Ftp.php | 62 ++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/src/Gaufrette/Adapter/Ftp.php b/src/Gaufrette/Adapter/Ftp.php index a5e4adc3e..4a4628bb3 100644 --- a/src/Gaufrette/Adapter/Ftp.php +++ b/src/Gaufrette/Adapter/Ftp.php @@ -60,16 +60,22 @@ public function __construct($directory, $host, $options = array()) */ 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; @@ -112,14 +118,26 @@ public function write($key, $content) */ 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); + + $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 ftp_rename($this->getConnection(), $sourcePath, $targetPath); + return $result; } /** @@ -128,22 +146,26 @@ public function rename($sourceKey, $targetKey) */ 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; } @@ -201,6 +223,7 @@ public function mtime($key) $file = basename($key); $mtime = ftp_mdtm($this->getConnection(), $file); + //change back to ftp root directory $this->changeDirectory($this->directory); @@ -218,13 +241,20 @@ public function mtime($key) */ 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; } /** @@ -605,9 +635,9 @@ protected function changeDirectory($directory) /** * Change current directory to the directory of - * the $key filepath. + * the $key file path. * This allows to avoid truncation of too long file paths - * or failure of ftp_mdtm function due to too long file paths + * or failure of ftp php functions due to too long file paths * * @param string $key */ @@ -622,4 +652,4 @@ protected function moveToTargetDirectory($key) $this->changeDirectory($directory); } -} +} \ No newline at end of file From bad0ca0dba1754cdf191218e5af3314118d8089f Mon Sep 17 00:00:00 2001 From: FaustineLarmagna Date: Mon, 29 Feb 2016 16:44:11 +0100 Subject: [PATCH 6/6] Modified isDir function to avoid change of current ftp path --- src/Gaufrette/Adapter/Ftp.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Gaufrette/Adapter/Ftp.php b/src/Gaufrette/Adapter/Ftp.php index 4a4628bb3..ed02151ca 100644 --- a/src/Gaufrette/Adapter/Ftp.php +++ b/src/Gaufrette/Adapter/Ftp.php @@ -391,6 +391,8 @@ protected function createDirectory($directory) */ private function isDir($directory) { + $currentPath = ftp_pwd($this->getConnection()); + if ('/' === $directory) { return true; } @@ -399,8 +401,8 @@ 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; }