diff --git a/lib/SimpleSAML/Configuration.php b/lib/SimpleSAML/Configuration.php index 7461a2ba3152721af884158880c9e6b0bb34b79a..1a07d44870e018a89cefb433963b39be452c1b8f 100644 --- a/lib/SimpleSAML/Configuration.php +++ b/lib/SimpleSAML/Configuration.php @@ -1,5 +1,6 @@ <?php +use SimpleSAML\Utils\System; /** * Configuration of SimpleSAMLphp @@ -568,19 +569,7 @@ class SimpleSAML_Configuration implements \SimpleSAML\Utils\ClearableState assert(is_string($path)); - /* Prepend path with basedir if it doesn't start with a slash or a Windows drive letter (e.g. "C:\"). We assume - * getBaseDir ends with a slash. - */ - if ($path[0] !== '/' && - !(preg_match('@^[a-z]:[\\\\/]@i', $path, $matches) && is_dir($matches[0])) - ) { - $path = $this->getBaseDir().$path; - } - - // remove trailing slashes - $path = rtrim($path, '/'); - - return $path; + return System::resolvePath($path, $this->getBaseDir()); } diff --git a/lib/SimpleSAML/Utils/System.php b/lib/SimpleSAML/Utils/System.php index 43c0b9b55431568f5d4ce3d0585ec5e7fb1343b0..f9d71f029421f85df1a61f2e3becb2d9358b05e1 100644 --- a/lib/SimpleSAML/Utils/System.php +++ b/lib/SimpleSAML/Utils/System.php @@ -122,13 +122,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; @@ -141,7 +148,7 @@ class System } elseif ($d === '..') { $ret = dirname($ret); } else { - if (substr($ret, -1) !== '/') { + if ($ret && substr($ret, -1) !== '/') { $ret .= '/'; } $ret .= $d; @@ -215,4 +222,18 @@ class System opcache_invalidate($filename); } } + + /** + * 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 c299cc28368e4f2bcf966a04e8e5cfd1c8fd25fa..14e3071a27315ac7291d7887293301dfcc597b97 100644 --- a/tests/lib/SimpleSAML/ConfigurationTest.php +++ b/tests/lib/SimpleSAML/ConfigurationTest.php @@ -220,6 +220,9 @@ class Test_SimpleSAML_Configuration extends SimpleSAML\Test\Utils\ClearStateTest $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'); } /**