From 5f483bb51a72de1b85e6529aa803f7b0725013e0 Mon Sep 17 00:00:00 2001
From: Luke Carrier <luke@carrier.im>
Date: Tue, 21 Feb 2017 13:17:42 +0000
Subject: [PATCH] Handle paths with drive letters in System::resolvePath()

Note that when normalising the directory separator, using
DIRECTORY_SEPARATOR causes tests to fail on non-Windows platforms
as its value is (correctly) "/".
---
 lib/SimpleSAML/Utils/System.php            | 23 +++++++++++++++++++++-
 tests/lib/SimpleSAML/ConfigurationTest.php |  3 +++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/lib/SimpleSAML/Utils/System.php b/lib/SimpleSAML/Utils/System.php
index 61e6bfe7e..ddaa7f0aa 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 129f658cf..99cdebe34 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');
     }
 
     /**
-- 
GitLab