Skip to content

Commit 63a4727

Browse files
authored
Merge pull request #25 from SniperSister/pathresolve
Add a "resolve" method to Path
2 parents dda0d4c + f533bc8 commit 63a4727

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

Tests/PathTest.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Joomla\Filesystem\Tests;
88

9+
use Joomla\Filesystem\Exception\FilesystemException;
910
use Joomla\Filesystem\File;
1011
use Joomla\Filesystem\Path;
1112

@@ -362,4 +363,87 @@ public function testFind()
362363
Path::find(__DIR__, 'PathTest.php')
363364
);
364365
}
366+
367+
/**
368+
* Test resolve method
369+
*
370+
* @param string $path test path
371+
* @param string $expectedResult expected path
372+
*
373+
* @return void
374+
*
375+
* @since 1.4.0
376+
*
377+
* @dataProvider getResolveData
378+
*/
379+
public function testResolve($path, $expectedResult)
380+
{
381+
$this->assertEquals(str_replace("_DS_", DIRECTORY_SEPARATOR, $expectedResult), Path::resolve($path));
382+
}
383+
384+
/**
385+
* Test resolve method
386+
387+
* @param string $path test path
388+
*
389+
* @expectedException Joomla\Filesystem\Exception\FilesystemException
390+
* @expectedExceptionMessage Path is outside of the defined root
391+
*
392+
* @return void
393+
*
394+
* @since 1.4.0
395+
*
396+
* @dataProvider getResolveExceptionData
397+
*/
398+
public function testResolveThrowsExceptionIfRootIsLeft($path)
399+
{
400+
Path::resolve($path);
401+
}
402+
403+
/**
404+
* Data provider for testResolve() method.
405+
*
406+
* @return array
407+
*
408+
* @since 1.0
409+
*/
410+
public function getResolveData()
411+
{
412+
return array(
413+
array("/", "_DS_"),
414+
array("a", "a"),
415+
array("/test/", "_DS_test"),
416+
array("C:/", "C:"),
417+
array("/var/www/joomla", "_DS_var_DS_www_DS_joomla"),
418+
array("C:/iis/www/joomla", "C:_DS_iis_DS_www_DS_joomla"),
419+
array("var/www/joomla", "var_DS_www_DS_joomla"),
420+
array("./var/www/joomla", "var_DS_www_DS_joomla"),
421+
array("/var/www/foo/../joomla", "_DS_var_DS_www_DS_joomla"),
422+
array("C:/var/www/foo/../joomla", "C:_DS_var_DS_www_DS_joomla"),
423+
array("/var/www/../foo/../joomla", "_DS_var_DS_joomla"),
424+
array("C:/var/www/..foo../joomla", "C:_DS_var_DS_www_DS_..foo.._DS_joomla"),
425+
array("c:/var/www/..foo../joomla", "c:_DS_var_DS_www_DS_..foo.._DS_joomla"),
426+
array("/var/www///joomla", "_DS_var_DS_www_DS_joomla"),
427+
array("/var///www///joomla", "_DS_var_DS_www_DS_joomla"),
428+
array("C:/var///www///joomla", "C:_DS_var_DS_www_DS_joomla"),
429+
array("/var/\/../www///joomla", "_DS_www_DS_joomla"),
430+
array("C:/var///www///joomla", "C:_DS_var_DS_www_DS_joomla"),
431+
array("/var\\www///joomla", "_DS_var_DS_www_DS_joomla")
432+
);
433+
}
434+
435+
/**
436+
* Data provider for testResolve() method.
437+
*
438+
* @return array
439+
*
440+
* @since 1.0
441+
*/
442+
public function getResolveExceptionData()
443+
{
444+
return array(
445+
array("../var/www/joomla"),
446+
array("/var/../../../www/joomla")
447+
);
448+
}
365449
}

src/Path.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,4 +340,49 @@ public static function find($paths, $file)
340340
// Could not find the file in the set of paths
341341
return false;
342342
}
343+
344+
/**
345+
* Resolves /./, /../ and multiple / in a string and returns the resulting absolute path, inspired by Flysystem
346+
* Removes trailing slashes
347+
*
348+
* @param string $path A path to resolve
349+
*
350+
* @return string The resolved path
351+
*
352+
* @since __DEPLOY_VERSION__
353+
*/
354+
public static function resolve($path)
355+
{
356+
$path = static::clean($path);
357+
358+
// Save start character for absolute path
359+
$startCharacter = ($path[0] === DIRECTORY_SEPARATOR) ? DIRECTORY_SEPARATOR : '';
360+
361+
$parts = array();
362+
363+
foreach (explode(DIRECTORY_SEPARATOR, $path) as $part)
364+
{
365+
switch ($part)
366+
{
367+
case '':
368+
case '.':
369+
break;
370+
371+
case '..':
372+
if (empty($parts))
373+
{
374+
throw new FilesystemException('Path is outside of the defined root');
375+
}
376+
377+
array_pop($parts);
378+
break;
379+
380+
default:
381+
$parts[] = $part;
382+
break;
383+
}
384+
}
385+
386+
return $startCharacter . implode(DIRECTORY_SEPARATOR, $parts);
387+
}
343388
}

0 commit comments

Comments
 (0)