Skip to content
84 changes: 84 additions & 0 deletions Tests/PathTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

namespace Joomla\Filesystem\Tests;

use Joomla\Filesystem\Exception\FilesystemException;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Path;

Expand Down Expand Up @@ -362,4 +363,87 @@ 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(str_replace("_DS_", DIRECTORY_SEPARATOR, $expectedResult), Path::resolve($path));
}

/**
* Test resolve method

* @param string $path test path
*
* @expectedException Joomla\Filesystem\Exception\FilesystemException
* @expectedExceptionMessage Path is outside of the defined root
*
* @return void
*
* @since 1.4.0
*
* @dataProvider getResolveExceptionData
*/
public function testResolveThrowsExceptionIfRootIsLeft($path)
{
Path::resolve($path);
}

/**
* Data provider for testResolve() method.
*
* @return array
*
* @since 1.0
*/
public function getResolveData()
{
return array(
array("/", "_DS_"),
array("a", "a"),
array("/test/", "_DS_test"),
array("C:/", "C:"),
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")
);
}

/**
* Data provider for testResolve() method.
*
* @return array
*
* @since 1.0
*/
public function getResolveExceptionData()
{
return array(
array("../var/www/joomla"),
array("/var/../../../www/joomla")
);
}
}
45 changes: 45 additions & 0 deletions src/Path.php
Original file line number Diff line number Diff line change
Expand Up @@ -340,4 +340,49 @@ 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
* Removes trailing slashes
*
* @param string $path A path to resolve
*
* @return string The resolved path
*
* @since __DEPLOY_VERSION__
*/
public static function resolve($path)
{
$path = static::clean($path);

// Save start character for absolute path
$startCharacter = ($path[0] === DIRECTORY_SEPARATOR) ? DIRECTORY_SEPARATOR : '';

$parts = array();

foreach (explode(DIRECTORY_SEPARATOR, $path) as $part)
{
switch ($part)
{
case '':
case '.':
break;

case '..':
if (empty($parts))
{
throw new FilesystemException('Path is outside of the defined root');
}

array_pop($parts);
break;

default:
$parts[] = $part;
break;
}
}

return $startCharacter . implode(DIRECTORY_SEPARATOR, $parts);
}
}