Browse Source

Merge pull request #9341 from ndm2/3.x-fix-folder-in-path-checks

3.x - Fix/tighten `Folder::inPath()` checks
Mark Story 9 years ago
parent
commit
724eb681e9
2 changed files with 86 additions and 18 deletions
  1. 13 7
      src/Filesystem/Folder.php
  2. 73 11
      tests/TestCase/Filesystem/FolderTest.php

+ 13 - 7
src/Filesystem/Folder.php

@@ -16,6 +16,7 @@ namespace Cake\Filesystem;
 
 use DirectoryIterator;
 use Exception;
+use InvalidArgumentException;
 use RecursiveDirectoryIterator;
 use RecursiveIteratorIterator;
 
@@ -401,7 +402,7 @@ class Folder
     }
 
     /**
-     * Returns true if the File is in a given CakePath.
+     * Returns true if the Folder is in the given Cake path.
      *
      * @param string $path The path to check.
      * @return bool
@@ -416,21 +417,26 @@ class Folder
     }
 
     /**
-     * Returns true if the File is in given path.
+     * Returns true if the Folder is in the given path.
      *
-     * @param string $path The path to check that the current pwd() resides with in.
-     * @param bool $reverse Reverse the search, check that pwd() resides within $path.
+     * @param string $path The absolute path to check that the current `pwd()` resides within.
+     * @param bool $reverse Reverse the search, check if the given `$path` resides within the current `pwd()`.
      * @return bool
+     * @throws \InvalidArgumentException When the given `$path` argument is not an absolute path.
      */
-    public function inPath($path = '', $reverse = false)
+    public function inPath($path, $reverse = false)
     {
+        if (!Folder::isAbsolute($path)) {
+            throw new InvalidArgumentException('The $path argument is expected to be an absolute path.');
+        }
+
         $dir = Folder::slashTerm($path);
         $current = Folder::slashTerm($this->pwd());
 
         if (!$reverse) {
-            $return = preg_match('/^(.*)' . preg_quote($dir, '/') . '(.*)/', $current);
+            $return = preg_match('/^' . preg_quote($dir, '/') . '(.*)/', $current);
         } else {
-            $return = preg_match('/^(.*)' . preg_quote($current, '/') . '(.*)/', $dir);
+            $return = preg_match('/^' . preg_quote($current, '/') . '(.*)/', $dir);
         }
 
         return (bool)$return;

+ 73 - 11
tests/TestCase/Filesystem/FolderTest.php

@@ -95,28 +95,90 @@ class FolderTest extends TestCase
      */
     public function testInPath()
     {
-        $path = dirname(__DIR__);
-        $inside = dirname($path) . DS;
+        // "/tests/test_app/"
+        $basePath = TEST_APP;
+        $Base = new Folder($basePath);
 
-        $Folder = new Folder($path);
+        $result = $Base->pwd();
+        $this->assertEquals($basePath, $result);
 
-        $result = $Folder->pwd();
-        $this->assertEquals($path, $result);
 
-        $result = Folder::isSlashTerm($inside);
+        // is "/" in "/tests/test_app/"
+        $result = $Base->inPath(realpath(DS), true);
+        $this->assertFalse($result, true);
+
+        // is "/tests/test_app/" in "/tests/test_app/"
+        $result = $Base->inPath($basePath, true);
         $this->assertTrue($result);
 
-        $result = $Folder->realpath('tests' . DS);
-        $this->assertEquals($path . DS . 'tests' . DS, $result);
+        // is "/tests/test_app" in "/tests/test_app/"
+        $result = $Base->inPath(mb_substr($basePath, 0, -1), true);
+        $this->assertTrue($result);
 
-        $result = $Folder->inPath('tests' . DS);
+        // is "/tests/test_app/sub" in "/tests/test_app/"
+        $result = $Base->inPath($basePath . 'sub', true);
         $this->assertTrue($result);
 
-        $result = $Folder->inPath(DS . 'non-existing' . $inside);
+        // is "/tests" in "/tests/test_app/"
+        $result = $Base->inPath(dirname($basePath), true);
+        $this->assertFalse($result);
+
+        // is "/tests/other/(...)tests/test_app" in "/tests/test_app/"
+        $result = $Base->inPath(TMP . 'tests' . DS . 'other' . DS . $basePath, true);
         $this->assertFalse($result);
 
-        $result = $Folder->inPath($path . DS . 'Model', true);
+
+        // is "/tests/test_app/" in "/"
+        $result = $Base->inPath(realpath(DS));
         $this->assertTrue($result);
+
+        // is "/tests/test_app/" in "/tests/test_app/"
+        $result = $Base->inPath($basePath);
+        $this->assertTrue($result);
+
+        // is "/tests/test_app/" in "/tests/test_app"
+        $result = $Base->inPath(mb_substr($basePath, 0, -1));
+        $this->assertTrue($result);
+
+        // is "/tests/test_app/" in "/tests"
+        $result = $Base->inPath(dirname($basePath));
+        $this->assertTrue($result);
+
+        // is "/tests/test_app/" in "/tests/test_app/sub"
+        $result = $Base->inPath($basePath . 'sub');
+        $this->assertFalse($result);
+
+        // is "/other/tests/test_app/" in "/tests/test_app/"
+        $VirtualBase = new Folder();
+        $VirtualBase->path = '/other/tests/test_app';
+        $result = $VirtualBase->inPath('/tests/test_app/');
+        $this->assertFalse($result);
+    }
+
+    /**
+     * Data provider for the testInPathInvalidPathArgument test
+     *
+     * @return array
+     */
+    public function inPathInvalidPathArgumentDataProvider()
+    {
+        return [
+            [''],
+            ['relative/path/'],
+            ['unknown://stream-wrapper']
+        ];
+    }
+
+    /**
+     * @dataProvider inPathInvalidPathArgumentDataProvider
+     * @param string $path
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage The $path argument is expected to be an absolute path.
+     */
+    public function testInPathInvalidPathArgument($path)
+    {
+        $Folder = new Folder();
+        $Folder->inPath($path);
     }
 
     /**