diff --git a/lib/SimpleSAML/Utils/System.php b/lib/SimpleSAML/Utils/System.php index 61e6bfe7e63d3aebfa742356dd8755efcf6ad3b5..ddaa7f0aac6a2cbc3f3e558467994314577d83cc 100644 --- a/lib/SimpleSAML/Utils/System.php +++ b/lib/SimpleSAML/Utils/System.php @@ -121,13 +121,20 @@ class System $base = $config->getBaseDir(); } + // normalise directory separator + $base = str_replace('\\', '/', $base); + $path = str_replace('\\', '/', $path); + // remove trailing slashes $base = rtrim($base, '/'); + $path = rtrim($path, '/'); // check for absolute path if (substr($path, 0, 1) === '/') { // absolute path. */ $ret = '/'; + } elseif (static::pathContainsDriveLetter($path)) { + $ret = ''; } else { // path relative to base $ret = $base; @@ -140,7 +147,7 @@ class System } elseif ($d === '..') { $ret = dirname($ret); } else { - if (substr($ret, -1) !== '/') { + if ($ret && substr($ret, -1) !== '/') { $ret .= '/'; } $ret .= $d; @@ -204,4 +211,18 @@ class System ); } } + + /** + * Check if the supplied path contains a Windows-style drive letter. + * + * @param string $path + * + * @return bool + */ + private static function pathContainsDriveLetter($path) + { + $letterAsciiValue = ord(strtoupper(substr($path, 0, 1))); + return substr($path, 1, 1) === ':' + && $letterAsciiValue >= 65 && $letterAsciiValue <= 90; + } } diff --git a/tests/lib/SimpleSAML/ConfigurationTest.php b/tests/lib/SimpleSAML/ConfigurationTest.php index 129f658cf01d9272b552998a5d9073fbe20bc952..99cdebe348b41339a3f0c9ae18eb28caf44d1bad 100644 --- a/tests/lib/SimpleSAML/ConfigurationTest.php +++ b/tests/lib/SimpleSAML/ConfigurationTest.php @@ -201,6 +201,9 @@ class Test_SimpleSAML_Configuration extends PHPUnit_Framework_TestCase $this->assertEquals($c->resolvePath('slash/'), '/basedir/slash'); $this->assertEquals($c->resolvePath('slash//'), '/basedir/slash'); + + $this->assertEquals($c->resolvePath('C:\\otherdir'), 'C:/otherdir'); + $this->assertEquals($c->resolvePath('C:/otherdir'), 'C:/otherdir'); } /**