diff --git a/common/framework/filters/filenamefilter.php b/common/framework/filters/filenamefilter.php index 42f5a729c..dd99954c9 100644 --- a/common/framework/filters/filenamefilter.php +++ b/common/framework/filters/filenamefilter.php @@ -46,4 +46,43 @@ class FilenameFilter return $filename; } + + /** + * Clean a path to remove ./, ../, trailing slashes, etc. + * + * @param string $path + * @return string + */ + public static function cleanPath($path) + { + // Convert relative paths to absolute paths. + if (!preg_match('@^(?:/|[a-z]:[\\\\/]|\\\\|https?:)@i', $path)) + { + $path = \RX_BASEDIR . $path; + } + + // Convert backslashes to forward slashes. + $path = str_replace('\\', '/', $path); + + // Remove querystrings and URL fragments. + if (($querystring = strpbrk($path, '?#')) !== false) + { + $path = substr($path, 0, -1 * strlen($querystring)); + } + + // Remove single dots, three or more dots, and duplicate slashes. + $path = preg_replace(array( + '@(?loadFile(array('./common/js/common.js', 'body')); $handler->loadFile(array('./common/js/common.js', 'head')); $handler->loadFile(array('./common/js/xml_js_filter.js', 'body')); - $expected[] = array('file' => '/xe/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => null); - $expected[] = array('file' => '/xe/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null); $this->assertEquals($handler->getJsFileList(), $expected); }); @@ -39,8 +38,8 @@ class FrontEndFileHandlerTest extends \Codeception\TestCase\Test $handler = new FrontEndFileHandler(); $handler->loadFile(array('./common/css/xe.css')); $handler->loadFile(array('./common/css/mobile.css')); - $expected[] = array('file' => '/xe/common/css/xe.css' . $this->_filemtime('common/css/xe.css'), 'media' => 'all', 'targetie' => null); - $expected[] = array('file' => '/xe/common/css/mobile.css' . $this->_filemtime('common/css/mobile.css'), 'media' => 'all', 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/css/xe.css' . $this->_filemtime('common/css/xe.css'), 'media' => 'all', 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/css/mobile.css' . $this->_filemtime('common/css/mobile.css'), 'media' => 'all', 'targetie' => null); $this->assertEquals($handler->getCssFileList(), $expected); }); @@ -54,10 +53,10 @@ class FrontEndFileHandlerTest extends \Codeception\TestCase\Test $handler->loadFile(array('./common/js/common.js', 'head', '', -100000)); $handler->loadFile(array('./common/js/xml_handler.js', 'head', '', -100000)); $handler->loadFile(array('./common/js/xml_js_filter.js', 'head', '', -100000)); - $expected[] = array('file' => '/xe/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => null); - $expected[] = array('file' => '/xe/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null); - $expected[] = array('file' => '/xe/common/js/xml_handler.js' . $this->_filemtime('common/js/xml_handler.js'), 'targetie' => null); - $expected[] = array('file' => '/xe/common/js/xml_js_filter.js' . $this->_filemtime('common/js/xml_js_filter.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/xml_handler.js' . $this->_filemtime('common/js/xml_handler.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/xml_js_filter.js' . $this->_filemtime('common/js/xml_js_filter.js'), 'targetie' => null); $this->assertEquals($handler->getJsFileList(), $expected); }); @@ -67,10 +66,10 @@ class FrontEndFileHandlerTest extends \Codeception\TestCase\Test $handler->loadFile(array('./common/js/js_app.js', 'head', '', -100000)); $handler->loadFile(array('./common/js/common.js', 'head', '', -100000)); $handler->loadFile(array('./common/js/xml_js_filter.js', 'head', '', -100000)); - $expected[] = array('file' => '/xe/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => null); - $expected[] = array('file' => '/xe/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null); - $expected[] = array('file' => '/xe/common/js/xml_js_filter.js' . $this->_filemtime('common/js/xml_js_filter.js'), 'targetie' => null); - $expected[] = array('file' => '/xe/common/js/xml_handler.js' . $this->_filemtime('common/js/xml_handler.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/xml_js_filter.js' . $this->_filemtime('common/js/xml_js_filter.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/xml_handler.js' . $this->_filemtime('common/js/xml_handler.js'), 'targetie' => null); $this->assertEquals($handler->getJsFileList(), $expected); }); @@ -81,9 +80,9 @@ class FrontEndFileHandlerTest extends \Codeception\TestCase\Test $handler->loadFile(array('./common/js/xml_handler.js', 'head', '', -100000)); $handler->loadFile(array('./common/js/xml_js_filter.js', 'head', '', -100000)); $handler->unloadFile('./common/js/js_app.js', '', 'all'); - $expected[] = array('file' => '/xe/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null); - $expected[] = array('file' => '/xe/common/js/xml_handler.js' . $this->_filemtime('common/js/xml_handler.js'), 'targetie' => null); - $expected[] = array('file' => '/xe/common/js/xml_js_filter.js' . $this->_filemtime('common/js/xml_js_filter.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/xml_handler.js' . $this->_filemtime('common/js/xml_handler.js'), 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/js/xml_js_filter.js' . $this->_filemtime('common/js/xml_js_filter.js'), 'targetie' => null); $this->assertEquals($handler->getJsFileList(), $expected); }); @@ -92,9 +91,9 @@ class FrontEndFileHandlerTest extends \Codeception\TestCase\Test $handler->loadFile(array('./common/js/js_app.js', 'head', 'ie6')); $handler->loadFile(array('./common/js/js_app.js', 'head', 'ie7')); $handler->loadFile(array('./common/js/js_app.js', 'head', 'ie8')); - $expected[] = array('file' => '/xe/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => 'ie6'); - $expected[] = array('file' => '/xe/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => 'ie7'); - $expected[] = array('file' => '/xe/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => 'ie8'); + $expected[] = array('file' => '/rhymix/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => 'ie6'); + $expected[] = array('file' => '/rhymix/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => 'ie7'); + $expected[] = array('file' => '/rhymix/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => 'ie8'); $this->assertEquals($handler->getJsFileList(), $expected); }); @@ -127,9 +126,9 @@ class FrontEndFileHandlerTest extends \Codeception\TestCase\Test $handler->loadFile(array('./common/css/common.css', null, 'ie7')); $handler->loadFile(array('./common/css/common.css', null, 'ie8')); - $expected[] = array('file' => '/xe/common/css/common.css', 'media'=>'all', 'targetie' => 'ie6'); - $expected[] = array('file' => '/xe/common/css/common.css','media'=>'all', 'targetie' => 'ie7'); - $expected[] = array('file' => '/xe/common/css/common.css', 'media'=>'all', 'targetie' => 'ie8'); + $expected[] = array('file' => '/rhymix/common/css/common.css', 'media'=>'all', 'targetie' => 'ie6'); + $expected[] = array('file' => '/rhymix/common/css/common.css','media'=>'all', 'targetie' => 'ie7'); + $expected[] = array('file' => '/rhymix/common/css/common.css', 'media'=>'all', 'targetie' => 'ie8'); $this->assertEquals($handler->getCssFileList(), $expected); }); @@ -139,9 +138,9 @@ class FrontEndFileHandlerTest extends \Codeception\TestCase\Test $handler->loadFile(array('./common/css/common.css', 'screen')); $handler->loadFile(array('./common/css/common.css', 'handled')); - $expected[] = array('file' => '/xe/common/css/common.css', 'media'=>'all', 'targetie' => null); - $expected[] = array('file' => '/xe/common/css/common.css','media'=>'screen', 'targetie' => null); - $expected[] = array('file' => '/xe/common/css/common.css', 'media'=>'handled', 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/css/common.css', 'media'=>'all', 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/css/common.css','media'=>'screen', 'targetie' => null); + $expected[] = array('file' => '/rhymix/common/css/common.css', 'media'=>'handled', 'targetie' => null); $this->assertEquals($handler->getCssFileList(), $expected); }); @@ -151,8 +150,8 @@ class FrontEndFileHandlerTest extends \Codeception\TestCase\Test $handler = new FrontEndFileHandler(); $handler->loadFile(array('./common/css/xe.css')); $handler->loadFile(array('./common/css/mobile.css')); - $expected[] = array('file' => '/xe/files/cache/minify/common.css.xe.min.css', 'media' => 'all', 'targetie' => null); - $expected[] = array('file' => '/xe/files/cache/minify/common.css.mobile.min.css', 'media' => 'all', 'targetie' => null); + $expected[] = array('file' => '/rhymix/files/cache/minify/common.css.xe.min.css', 'media' => 'all', 'targetie' => null); + $expected[] = array('file' => '/rhymix/files/cache/minify/common.css.mobile.min.css', 'media' => 'all', 'targetie' => null); $result = $handler->getCssFileList(); $result[0]['file'] = preg_replace('/\?\d+$/', '', $result[0]['file']); $result[1]['file'] = preg_replace('/\?\d+$/', '', $result[1]['file']); diff --git a/tests/unit/classes/OldSecurityTest.php b/tests/unit/classes/OldSecurityTest.php index f699b8d1b..85ed5e564 100644 --- a/tests/unit/classes/OldSecurityTest.php +++ b/tests/unit/classes/OldSecurityTest.php @@ -1,5 +1,4 @@ ', - '?>' + '?>' ), // relative path2 array( '', - '?>' + '?>' ), // error case array( @@ -213,7 +210,7 @@ class TemplateHandlerTest extends \Codeception\TestCase\Test // issue 584 array( 'mobile', - PHP_EOL . 'if($__Context->oBodex->display_extra_images[\'mobile\'] && $__Context->arr_extra && $__Context->arr_extra->bodex->mobile){ ?>mobile' + PHP_EOL . 'if($__Context->oBodex->display_extra_images[\'mobile\'] && $__Context->arr_extra && $__Context->arr_extra->bodex->mobile){ ?>mobile' ), // issue 831 array( @@ -222,8 +219,8 @@ class TemplateHandlerTest extends \Codeception\TestCase\Test ), // issue 746 array( - '', - '?>' + '', + '?>' ), // issue 696 array( @@ -233,47 +230,47 @@ class TemplateHandlerTest extends \Codeception\TestCase\Test // https://github.com/xpressengine/xe-core/issues/1510 array( '', - PHP_EOL . 'if($__Context->foo->bar){ ?>' + PHP_EOL . 'if($__Context->foo->bar){ ?>' ), // https://github.com/xpressengine/xe-core/issues/1510 array( 'a!@#$%^&*()_-=[]{}?/', - PHP_EOL . 'if($__Context->foo->bar > 100){ ?>a!@#$%^&*()_-=[]{}?/' + PHP_EOL . 'if($__Context->foo->bar > 100){ ?>a!@#$%^&*()_-=[]{}?/' ), // https://github.com/xpressengine/xe-core/issues/1510 array( '', - PHP_EOL . 'if($__Context->foo->bar){ ?>' + PHP_EOL . 'if($__Context->foo->bar){ ?>' ), // https://github.com/xpressengine/xe-core/issues/1510 array( '', - PHP_EOL . 'if(!$__Context->module_info->title){ ?>' + PHP_EOL . 'if(!$__Context->module_info->title){ ?>' ), // https://github.com/xpressengine/xe-core/issues/1510 array( '', - PHP_EOL . 'if($__Context->mi->title){ ?>mi->use){ ?> class="tmp_class" src="/xe/tests/unit/classes/img/common/blank.gif" />' + PHP_EOL . 'if($__Context->mi->title){ ?>mi->use){ ?> class="tmp_class" src="/rhymix/tests/unit/classes/img/common/blank.gif" />' ), array( ' alt', - '?> foo->bar){ ?>alt' + '?> foo->bar){ ?>alt' ), array( '' . "\n" . ' alt', - '?>' . PHP_EOL . ' foo->bar){ ?>alt' + '?>' . PHP_EOL . ' foo->bar){ ?>alt' ), array( 'asf ', '?>asf ' ), array( - '', - '?>' + '', + '?>' ), array( - 'asdf src="../img/img.gif" asdf src asdf src="../img/img.gif" asdf', - '?>asdf src="../img/img.gif" asdf src asdf src="../img/img.gif" asdf' + 'asdf src="../img/img.gif" asdf src asdf src="../img/img.gif" asdf', + '?>asdf src="../img/img.gif" asdf src asdf src="../img/img.gif" asdf' ), array( 'asdf src="../img/img.gif" asdf', diff --git a/tests/unit/framework/SecurityTest.php b/tests/unit/framework/SecurityTest.php index b28d99ada..f0db07f0d 100644 --- a/tests/unit/framework/SecurityTest.php +++ b/tests/unit/framework/SecurityTest.php @@ -100,11 +100,9 @@ class SecurityTest extends \Codeception\TestCase\Test $_SERVER['REQUEST_METHOD'] = 'POST'; $this->assertTrue(Rhymix\Framework\Security::checkCSRF()); - $_SERVER['HTTP_HOST'] = 'www.rhymix.org'; $_SERVER['HTTP_REFERER'] = 'http://www.foobar.com/'; $this->assertFalse(Rhymix\Framework\Security::checkCSRF()); - $_SERVER['HTTP_HOST'] = 'www.rhymix.org'; $this->assertTrue(Rhymix\Framework\Security::checkCSRF('http://www.rhymix.org/')); } diff --git a/tests/unit/framework/URLTest.php b/tests/unit/framework/URLTest.php index d36dd5fe6..ed60020ee 100644 --- a/tests/unit/framework/URLTest.php +++ b/tests/unit/framework/URLTest.php @@ -4,37 +4,42 @@ class URLTest extends \Codeception\TestCase\Test { public function testGetCurrentURL() { - $protocol = \RX_SSL ? 'https://' : 'http://'; - $_SERVER['HTTP_HOST'] = 'www.rhymix.org'; - $_SERVER['REQUEST_URI'] = '/index.php?foo=bar&xe=sucks'; - $full_url = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; + $old_request_uri = $_SERVER['REQUEST_URI']; + $_SERVER['REQUEST_URI'] = '/rhymix/index.php?foo=bar&xe=sucks'; // Getting the current URL - $this->assertEquals($full_url, Rhymix\Framework\URL::getCurrentURL()); + $this->assertEquals('https://www.rhymix.org/rhymix/index.php?foo=bar&xe=sucks', Rhymix\Framework\URL::getCurrentURL()); // Adding items to the query string - $this->assertEquals($full_url . '&var=1&arr%5B0%5D=2&arr%5B1%5D=3', Rhymix\Framework\URL::getCurrentURL(array('var' => '1', 'arr' => array(2, 3)))); + $this->assertEquals('https://www.rhymix.org/rhymix/index.php?foo=bar&xe=sucks&var=1&arr%5B0%5D=2&arr%5B1%5D=3', Rhymix\Framework\URL::getCurrentURL(array('var' => '1', 'arr' => array(2, 3)))); // Removing item from the query string - $this->assertEquals($protocol . $_SERVER['HTTP_HOST'] . '/index.php?xe=sucks', Rhymix\Framework\URL::getCurrentURL(array('foo' => null))); + $this->assertEquals('https://www.rhymix.org/rhymix/index.php?xe=sucks', Rhymix\Framework\URL::getCurrentURL(array('foo' => null))); // Removing all items from the query string - $this->assertEquals($protocol . $_SERVER['HTTP_HOST'] . '/index.php', Rhymix\Framework\URL::getCurrentURL(array('foo' => null, 'xe' => null))); + $this->assertEquals('https://www.rhymix.org/rhymix/index.php', Rhymix\Framework\URL::getCurrentURL(array('foo' => null, 'xe' => null))); // Adding and removing parameters at the same time - $this->assertEquals($protocol . $_SERVER['HTTP_HOST'] . '/index.php?xe=sucks&l=ko', Rhymix\Framework\URL::getCurrentURL(array('l' => 'ko', 'foo' => null))); + $this->assertEquals('https://www.rhymix.org/rhymix/index.php?xe=sucks&l=ko', Rhymix\Framework\URL::getCurrentURL(array('l' => 'ko', 'foo' => null))); + + $_SERVER['REQUEST_URI'] = $old_request_uri; + } + + public function testGetCurrentDomainURL() + { + $this->assertEquals('https://www.rhymix.org/', Rhymix\Framework\URL::getCurrentDomainURL()); + $this->assertEquals('https://www.rhymix.org/', Rhymix\Framework\URL::getCurrentDomainURL('/')); + $this->assertEquals('https://www.rhymix.org/foo/bar', Rhymix\Framework\URL::getCurrentDomainURL('/foo/bar')); + $this->assertEquals('https://www.rhymix.org/rhymix/index.php?foo=bar', Rhymix\Framework\URL::getCurrentDomainURL('rhymix/index.php?foo=bar')); } public function testGetCanonicalURL() { - $protocol = \RX_SSL ? 'https://' : 'http://'; - $_SERVER['HTTP_HOST'] = 'www.rhymix.org'; - $tests = array( - 'foo/bar' => $protocol . $_SERVER['HTTP_HOST'] . \RX_BASEURL . 'foo/bar', - './foo/bar' => $protocol . $_SERVER['HTTP_HOST'] . \RX_BASEURL . 'foo/bar', - '/foo/bar' => $protocol . $_SERVER['HTTP_HOST'] . \RX_BASEURL . 'foo/bar', - '//www.example.com/foo' => $protocol . 'www.example.com/foo', + 'foo/bar' => 'https://www.rhymix.org/rhymix/foo/bar', + './foo/bar' => 'https://www.rhymix.org/rhymix/foo/bar', + '/foo/bar' => 'https://www.rhymix.org/rhymix/foo/bar', + '//www.example.com/foo' => 'https://www.example.com/foo', 'http://xn--cg4bkiv2oina.com/' => 'http://삼성전자.com/', ); @@ -60,21 +65,17 @@ class URLTest extends \Codeception\TestCase\Test public function testModifyURL() { - $protocol = \RX_SSL ? 'https://' : 'http://'; - $_SERVER['HTTP_HOST'] = 'www.rhymix.org'; - $url = $protocol . $_SERVER['HTTP_HOST'] . \RX_BASEURL . 'index.php?foo=bar'; - // Conversion to absolute - $this->assertEquals($url, Rhymix\Framework\URL::modifyURL('./index.php?foo=bar')); + $this->assertEquals('https://www.rhymix.org/rhymix/index.php?foo=bar', $url = Rhymix\Framework\URL::modifyURL('./index.php?foo=bar')); // Adding items to the query string - $this->assertEquals($url . '&var=1&arr%5B0%5D=2&arr%5B1%5D=3', Rhymix\Framework\URL::modifyURL($url, array('var' => '1', 'arr' => array(2, 3)))); + $this->assertEquals('https://www.rhymix.org/rhymix/index.php?foo=bar&var=1&arr%5B0%5D=2&arr%5B1%5D=3', Rhymix\Framework\URL::modifyURL($url, array('var' => '1', 'arr' => array(2, 3)))); // Removing item from the query string - $this->assertEquals($protocol . $_SERVER['HTTP_HOST'] . \RX_BASEURL . 'index.php', Rhymix\Framework\URL::modifyURL($url, array('foo' => null))); + $this->assertEquals('https://www.rhymix.org/rhymix/index.php', Rhymix\Framework\URL::modifyURL($url, array('foo' => null))); // Adding and removing parameters at the same time - $this->assertEquals($protocol . $_SERVER['HTTP_HOST'] . \RX_BASEURL . 'index.php?l=ko', Rhymix\Framework\URL::modifyURL($url, array('l' => 'ko', 'foo' => null))); + $this->assertEquals('https://www.rhymix.org/rhymix/index.php?l=ko', Rhymix\Framework\URL::modifyURL($url, array('l' => 'ko', 'foo' => null))); } public function testIsInternalURL() @@ -82,6 +83,25 @@ class URLTest extends \Codeception\TestCase\Test // This function is checked in Security::checkCSRF() } + public function testURLFromServerPath() + { + $this->assertEquals('https://www.rhymix.org/rhymix/', Rhymix\Framework\URL::fromServerPath(\RX_BASEDIR)); + $this->assertEquals('https://www.rhymix.org/rhymix/index.php', Rhymix\Framework\URL::fromServerPath(\RX_BASEDIR . 'index.php')); + $this->assertEquals('https://www.rhymix.org/rhymix/foo/bar', Rhymix\Framework\URL::fromServerPath(\RX_BASEDIR . '/foo/bar')); + $this->assertEquals(false, Rhymix\Framework\URL::fromServerPath(dirname(dirname(\RX_BASEDIR)))); + $this->assertEquals(false, Rhymix\Framework\URL::fromServerPath('C:/Windows')); + } + + public function testURLToServerPath() + { + $this->assertEquals(\RX_BASEDIR . 'index.php', Rhymix\Framework\URL::toServerPath('http://www.rhymix.org/rhymix/index.php')); + $this->assertEquals(\RX_BASEDIR . 'foo/bar', Rhymix\Framework\URL::toServerPath('http://www.rhymix.org/rhymix/foo/bar?arg=baz')); + $this->assertEquals(\RX_BASEDIR . 'foo/bar', Rhymix\Framework\URL::toServerPath('./foo/bar')); + $this->assertEquals(\RX_BASEDIR . 'foo/bar', Rhymix\Framework\URL::toServerPath('foo/bar/../bar')); + $this->assertEquals(false, Rhymix\Framework\URL::toServerPath('http://other.domain.com/')); + $this->assertEquals(false, Rhymix\Framework\URL::toServerPath('//other.domain.com/')); + } + public function testEncodeIdna() { $this->assertEquals('xn--9i1bl3b186bf9e.xn--3e0b707e', Rhymix\Framework\URL::encodeIdna('퓨니코드.한국')); diff --git a/tests/unit/framework/filters/FilenameFilterTest.php b/tests/unit/framework/filters/FilenameFilterTest.php index 7fe095d35..ad3b374e3 100644 --- a/tests/unit/framework/filters/FilenameFilterTest.php +++ b/tests/unit/framework/filters/FilenameFilterTest.php @@ -1,5 +1,7 @@ $to) { - $result = Rhymix\Framework\Filters\FilenameFilter::clean($from); + $result = FilenameFilter::clean($from); $this->assertEquals($to, $result); } } + + public function testFilenameFilterCleanPath() + { + // Remove extra dots and slashes. + $this->assertEquals('/usr/share/foo/bar.jpg', FilenameFilter::cleanPath('/usr/share/foo//./baz/../bar.jpg')); + $this->assertEquals('/usr/share/foo/bar.jpg', FilenameFilter::cleanPath('/usr/share/foo/././baz/../../foo/bar.jpg')); + $this->assertEquals('/usr/share', FilenameFilter::cleanPath('/usr/share/foo/..')); + $this->assertEquals('/usr/share', FilenameFilter::cleanPath('/usr/share/foo/bar/../baz/../../')); + + // Test internal paths. + $this->assertEquals(\RX_BASEDIR . 'common/js/debug.js', FilenameFilter::cleanPath('common/js/debug.js')); + $this->assertEquals(\RX_BASEDIR . 'common/js/debug.js', FilenameFilter::cleanPath('./common/js/debug.js')); + + // Test Windows paths. + $this->assertEquals('C:/Windows/Notepad.exe', FilenameFilter::cleanPath('C:\\Windows\\System32\\..\\Notepad.exe')); + $this->assertEquals('//vboxsrv/hello/world', FilenameFilter::cleanPath('\\\\vboxsrv\\hello\\world')); + + // Test absolute URLs. + $this->assertEquals('https://www.rhymix.org/foo/bar', FilenameFilter::cleanPath('https://www.rhymix.org/foo/.//bar')); + $this->assertEquals('//www.rhymix.org/foo/bar', FilenameFilter::cleanPath('//www.rhymix.org/foo/.//bar')); + + // Do not remove .. if there is no parent directory. + $this->assertEquals('C:/../foobar', FilenameFilter::cleanPath('C:\\..\foobar\\')); + $this->assertEquals('/../foobar', FilenameFilter::cleanPath('/../foobar/')); + + // Remove query strings and URL fragments. + $this->assertEquals(\RX_BASEDIR . 'index.php', FilenameFilter::cleanPath('index.php?foo=bar')); + $this->assertEquals(\RX_BASEDIR . 'index.php', FilenameFilter::cleanPath('index.php#baz')); + } }