From 4af0b0c3a9fc1c978ac46f4064976bfdf88d9ba2 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 10:11:47 +0100 Subject: [PATCH 01/14] added resolve method to path class --- Tests/PathTest.php | 60 ++++++++++++++++++++++++++++++++++++++++++++++ src/Path.php | 46 +++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/Tests/PathTest.php b/Tests/PathTest.php index d71f9398..504432ef 100644 --- a/Tests/PathTest.php +++ b/Tests/PathTest.php @@ -6,6 +6,7 @@ namespace Joomla\Filesystem\Tests; +use Joomla\Filesystem\Exception\FilesystemException; use Joomla\Filesystem\File; use Joomla\Filesystem\Path; @@ -362,4 +363,63 @@ public function testFind() Path::find(__DIR__, 'PathTest.php') ); } + + /** + * Test resolve method + * + * @param string $path test path + * @param string $expectedResult expected path + * + * @return void + * + * @since 1.4.0 + * + * @dataProvider getResolveData + */ + public function testResolve($path, $expectedResult) + { + $this->assertEquals($expectedResult, Path::resolve($path)); + } + + /** + * Description + * + * @expectedException Joomla\Filesystem\Exception\FilesystemException + * @expectedExceptionMessage Path is outside of the defined root, path: [../var/www/joomla] + * + * @return void + * + * @since 1.4.0 + */ + public function testResolveThrowsExceptionIfRootIsLeft() + { + Path::resolve("../var/www/joomla"); + } + + /** + * Data provider for testResolve() method. + * + * @return array + * + * @since 1.0 + */ + public function getResolveData() + { + return array( + array("/var/www/joomla", "/var/www/joomla"), + array("C:/iis/www/joomla", "C:/iis/www/joomla"), + array("var/www/joomla", "var/www/joomla"), + array("./var/www/joomla", "var/www/joomla"), + array("/var/www/foo/../joomla", "/var/www/joomla"), + array("C:/var/www/foo/../joomla", "C:/var/www/joomla"), + array("/var/www/../foo/../joomla", "/var/joomla"), + array("C:/var/www/..foo../joomla", "C:/var/www/..foo../joomla"), + array("c:/var/www/..foo../joomla", "c:/var/www/..foo../joomla"), + array("/var/www///joomla", "/var/www/joomla"), + array("/var///www///joomla", "/var/www/joomla"), + array("C:/var///www///joomla", "C:/var/www/joomla"), + array("/var/\/../www///joomla", "/www/joomla"), + array("C:/var///www///joomla", "C:/var/www/joomla") + ); + } } diff --git a/src/Path.php b/src/Path.php index 402a96b9..2d4862d4 100644 --- a/src/Path.php +++ b/src/Path.php @@ -340,4 +340,50 @@ public static function find($paths, $file) // Could not find the file in the set of paths return false; } + + /** + * Resolves /./, /../ and multiple / in a string and returns the resulting absolute path, inspired by Flysystem + * + * @param mixed $path A path to resolve + * + * @return string The resolved path + * + * @since 1.0 + */ + public static function resolve($path) + { + $path = self::clean($path); + + // Save start character for absolute path + $startCharacter = ($path[0] === DIRECTORY_SEPARATOR) ? DIRECTORY_SEPARATOR : ''; + + $parts = array(); + + foreach (explode('/', $path) as $part) + { + switch ($part) + { + case '': + case '.': + break; + + case '..': + if (empty($parts)) + { + throw new FilesystemException( + 'Path is outside of the defined root, path: [' . $path . ']' + ); + } + + array_pop($parts); + break; + + default: + $parts[] = $part; + break; + } + } + + return $startCharacter . implode('/', $parts); + } } From a72f30ebbb743dfb4b6e9db642df9a589fe645b3 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 10:44:31 +0100 Subject: [PATCH 02/14] add test case --- Tests/PathTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/PathTest.php b/Tests/PathTest.php index 504432ef..0976a8af 100644 --- a/Tests/PathTest.php +++ b/Tests/PathTest.php @@ -419,7 +419,8 @@ public function getResolveData() array("/var///www///joomla", "/var/www/joomla"), array("C:/var///www///joomla", "C:/var/www/joomla"), array("/var/\/../www///joomla", "/www/joomla"), - array("C:/var///www///joomla", "C:/var/www/joomla") + array("C:/var///www///joomla", "C:/var/www/joomla"), + array("/var\\www///joomla", "/var/www/joomla") ); } } From 669f488ff400f66295763f4e4d780e0d376e6724 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 10:47:05 +0100 Subject: [PATCH 03/14] more tests --- Tests/PathTest.php | 27 +++++++++++++++++++++++---- src/Path.php | 4 +--- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Tests/PathTest.php b/Tests/PathTest.php index 0976a8af..38d3c49c 100644 --- a/Tests/PathTest.php +++ b/Tests/PathTest.php @@ -382,18 +382,22 @@ public function testResolve($path, $expectedResult) } /** - * Description + * Test resolve method + + * @param string $path test path * * @expectedException Joomla\Filesystem\Exception\FilesystemException - * @expectedExceptionMessage Path is outside of the defined root, path: [../var/www/joomla] + * @expectedExceptionMessage Path is outside of the defined root * * @return void * * @since 1.4.0 + * + * @dataProvider getResolveExceptionData */ - public function testResolveThrowsExceptionIfRootIsLeft() + public function testResolveThrowsExceptionIfRootIsLeft($path) { - Path::resolve("../var/www/joomla"); + Path::resolve($path); } /** @@ -423,4 +427,19 @@ public function getResolveData() array("/var\\www///joomla", "/var/www/joomla") ); } + + /** + * Data provider for testResolve() method. + * + * @return array + * + * @since 1.0 + */ + public function getResolveExceptionData() + { + return array( + array("../var/www/joomla"), + array("/var/../../../www/joomla") + ); + } } diff --git a/src/Path.php b/src/Path.php index 2d4862d4..966e0fa5 100644 --- a/src/Path.php +++ b/src/Path.php @@ -370,9 +370,7 @@ public static function resolve($path) case '..': if (empty($parts)) { - throw new FilesystemException( - 'Path is outside of the defined root, path: [' . $path . ']' - ); + throw new FilesystemException('Path is outside of the defined root'); } array_pop($parts); From 554b61eb4046d5eda1f06d3c662483131c2e3dbd Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 10:47:53 +0100 Subject: [PATCH 04/14] more tests --- Tests/PathTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/PathTest.php b/Tests/PathTest.php index 38d3c49c..f331855e 100644 --- a/Tests/PathTest.php +++ b/Tests/PathTest.php @@ -410,6 +410,7 @@ public function testResolveThrowsExceptionIfRootIsLeft($path) public function getResolveData() { return array( + array("/", "/"), array("/var/www/joomla", "/var/www/joomla"), array("C:/iis/www/joomla", "C:/iis/www/joomla"), array("var/www/joomla", "var/www/joomla"), From 1afd9c4c769a2faf2053a64cfa016388eb4995a7 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 10:48:16 +0100 Subject: [PATCH 05/14] more tests --- Tests/PathTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/PathTest.php b/Tests/PathTest.php index f331855e..eee200e4 100644 --- a/Tests/PathTest.php +++ b/Tests/PathTest.php @@ -411,6 +411,7 @@ public function getResolveData() { return array( array("/", "/"), + array("C:/", "C:"), array("/var/www/joomla", "/var/www/joomla"), array("C:/iis/www/joomla", "C:/iis/www/joomla"), array("var/www/joomla", "var/www/joomla"), From 978bae32ff27f9eaf9a4a24be83117d3b69f9559 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 10:48:44 +0100 Subject: [PATCH 06/14] fix tests --- Tests/PathTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/PathTest.php b/Tests/PathTest.php index eee200e4..22fc2205 100644 --- a/Tests/PathTest.php +++ b/Tests/PathTest.php @@ -411,6 +411,7 @@ public function getResolveData() { return array( array("/", "/"), + array("a", "a"), array("C:/", "C:"), array("/var/www/joomla", "/var/www/joomla"), array("C:/iis/www/joomla", "C:/iis/www/joomla"), From 58d4ab93d0d3bf2b21af88ccf9e00fd3cf7f9064 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 10:50:49 +0100 Subject: [PATCH 07/14] one more test --- Tests/PathTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/PathTest.php b/Tests/PathTest.php index 22fc2205..3ef02b4d 100644 --- a/Tests/PathTest.php +++ b/Tests/PathTest.php @@ -412,6 +412,7 @@ public function getResolveData() return array( array("/", "/"), array("a", "a"), + array("/test/", "/test"), array("C:/", "C:"), array("/var/www/joomla", "/var/www/joomla"), array("C:/iis/www/joomla", "C:/iis/www/joomla"), From 4800b966257927f2c46608799fab8e927db9d00b Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 10:54:31 +0100 Subject: [PATCH 08/14] fix docblock --- src/Path.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Path.php b/src/Path.php index 966e0fa5..d016e16d 100644 --- a/src/Path.php +++ b/src/Path.php @@ -346,7 +346,7 @@ public static function find($paths, $file) * * @param mixed $path A path to resolve * - * @return string The resolved path + * @return string The resolved path * * @since 1.0 */ From 32178b0e82a9abafb03fdbbab345c72dafefc080 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 10:56:00 +0100 Subject: [PATCH 09/14] improve doc --- src/Path.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Path.php b/src/Path.php index d016e16d..5f3921f9 100644 --- a/src/Path.php +++ b/src/Path.php @@ -343,6 +343,7 @@ public static function find($paths, $file) /** * Resolves /./, /../ and multiple / in a string and returns the resulting absolute path, inspired by Flysystem + * Removes trailing slashes * * @param mixed $path A path to resolve * From 34090a3827e1188eb9be762b3a4cdc520923cca1 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 14:18:41 +0100 Subject: [PATCH 10/14] fix windows tests --- Tests/PathTest.php | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Tests/PathTest.php b/Tests/PathTest.php index 3ef02b4d..af48e45e 100644 --- a/Tests/PathTest.php +++ b/Tests/PathTest.php @@ -378,7 +378,7 @@ public function testFind() */ public function testResolve($path, $expectedResult) { - $this->assertEquals($expectedResult, Path::resolve($path)); + $this->assertEquals(str_replace("_DS_", DIRECTORY_SEPARATOR, $expectedResult), Path::resolve($path)); } /** @@ -410,25 +410,25 @@ public function testResolveThrowsExceptionIfRootIsLeft($path) public function getResolveData() { return array( - array("/", "/"), + array("/", "_DS_"), array("a", "a"), - array("/test/", "/test"), + array("/test/", "_DS_test"), array("C:/", "C:"), - array("/var/www/joomla", "/var/www/joomla"), - array("C:/iis/www/joomla", "C:/iis/www/joomla"), - array("var/www/joomla", "var/www/joomla"), - array("./var/www/joomla", "var/www/joomla"), - array("/var/www/foo/../joomla", "/var/www/joomla"), - array("C:/var/www/foo/../joomla", "C:/var/www/joomla"), - array("/var/www/../foo/../joomla", "/var/joomla"), - array("C:/var/www/..foo../joomla", "C:/var/www/..foo../joomla"), - array("c:/var/www/..foo../joomla", "c:/var/www/..foo../joomla"), - array("/var/www///joomla", "/var/www/joomla"), - array("/var///www///joomla", "/var/www/joomla"), - array("C:/var///www///joomla", "C:/var/www/joomla"), - array("/var/\/../www///joomla", "/www/joomla"), - array("C:/var///www///joomla", "C:/var/www/joomla"), - array("/var\\www///joomla", "/var/www/joomla") + array("/var/www/joomla", "_DS_var_DS_www_DS_joomla"), + array("C:/iis/www/joomla", "C:_DS_iis_DS_www_DS_joomla"), + array("var/www/joomla", "var_DS_www_DS_joomla"), + array("./var/www/joomla", "var_DS_www_DS_joomla"), + array("/var/www/foo/../joomla", "_DS_var_DS_www_DS_joomla"), + array("C:/var/www/foo/../joomla", "C:_DS_var_DS_www_DS_joomla"), + array("/var/www/../foo/../joomla", "_DS_var_DS_joomla"), + array("C:/var/www/..foo../joomla", "C:_DS_var_DS_www_DS_..foo.._DS_joomla"), + array("c:/var/www/..foo../joomla", "c:_DS_var_DS_www_DS_..foo.._DS_joomla"), + array("/var/www///joomla", "_DS_var_DS_www_DS_joomla"), + array("/var///www///joomla", "_DS_var_DS_www_DS_joomla"), + array("C:/var///www///joomla", "C:_DS_var_DS_www_DS_joomla"), + array("/var/\/../www///joomla", "_DS_www_DS_joomla"), + array("C:/var///www///joomla", "C:_DS_var_DS_www_DS_joomla"), + array("/var\\www///joomla", "_DS_var_DS_www_DS_joomla") ); } From b6bdb5559f9ddacdf08bcdd0463feb12fd65d0a6 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 14:23:44 +0100 Subject: [PATCH 11/14] explode by ds --- src/Path.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Path.php b/src/Path.php index 5f3921f9..18ae5ec0 100644 --- a/src/Path.php +++ b/src/Path.php @@ -360,7 +360,7 @@ public static function resolve($path) $parts = array(); - foreach (explode('/', $path) as $part) + foreach (explode(DIRECTORY_SEPARATOR, $path) as $part) { switch ($part) { @@ -383,6 +383,6 @@ public static function resolve($path) } } - return $startCharacter . implode('/', $parts); + return $startCharacter . implode(DIRECTORY_SEPARATOR, $parts); } } From 97eb13eac35af2ab9755cc85f4fe7134b5a52da3 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 14:27:24 +0100 Subject: [PATCH 12/14] Update src/Path.php Co-Authored-By: Michael Babker --- src/Path.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Path.php b/src/Path.php index 18ae5ec0..b4fad9b9 100644 --- a/src/Path.php +++ b/src/Path.php @@ -349,7 +349,7 @@ public static function find($paths, $file) * * @return string The resolved path * - * @since 1.0 + * @since __DEPLOY_VERSION__ */ public static function resolve($path) { From 1e93d9f916d2a1b8a93ee8147b8d753752dfe5bc Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 14:28:33 +0100 Subject: [PATCH 13/14] Update src/Path.php Co-Authored-By: Michael Babker --- src/Path.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Path.php b/src/Path.php index b4fad9b9..486cb46d 100644 --- a/src/Path.php +++ b/src/Path.php @@ -353,7 +353,7 @@ public static function find($paths, $file) */ public static function resolve($path) { - $path = self::clean($path); + $path = static::clean($path); // Save start character for absolute path $startCharacter = ($path[0] === DIRECTORY_SEPARATOR) ? DIRECTORY_SEPARATOR : ''; From f533bc89ccea0196ed56b9423c0910e40d5744aa Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 26 Mar 2020 14:28:48 +0100 Subject: [PATCH 14/14] Update src/Path.php Co-Authored-By: Michael Babker --- src/Path.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Path.php b/src/Path.php index 486cb46d..c9e538a9 100644 --- a/src/Path.php +++ b/src/Path.php @@ -345,7 +345,7 @@ public static function find($paths, $file) * Resolves /./, /../ and multiple / in a string and returns the resulting absolute path, inspired by Flysystem * Removes trailing slashes * - * @param mixed $path A path to resolve + * @param string $path A path to resolve * * @return string The resolved path *