From 72309b227fdbb001d6458e5d93ee25d06fdcad8b Mon Sep 17 00:00:00 2001 From: Rob Allen Date: Fri, 3 Nov 2017 18:41:53 +0000 Subject: [PATCH] Encode user info If the username or password includes an `@`, `:` or other reserved characters, they need to be encoded. Fixes #2201 --- Slim/Http/Uri.php | 23 +++++++++++++++++++++-- tests/Http/UriTest.php | 15 +++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Slim/Http/Uri.php b/Slim/Http/Uri.php index f8526024d..eac6e2be5 100644 --- a/Slim/Http/Uri.php +++ b/Slim/Http/Uri.php @@ -378,12 +378,31 @@ public function getUserInfo() public function withUserInfo($user, $password = null) { $clone = clone $this; - $clone->user = $user; - $clone->password = $password ? $password : ''; + $clone->user = $this->filterUserInfo($user); + if ($clone->user) { + $clone->password = $password ? $this->filterUserInfo($password) : ''; + } return $clone; } + /** + * Filters the user info string. + * + * @param string $query The raw uri query string. + * @return string The percent-encoded query string. + */ + protected function filterUserInfo($query) + { + return preg_replace_callback( + '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=]+|%(?![A-Fa-f0-9]{2}))/u', + function ($match) { + return rawurlencode($match[0]); + }, + $query + ); + } + /** * Retrieve the host component of the URI. * diff --git a/tests/Http/UriTest.php b/tests/Http/UriTest.php index 9b1b1bc2c..dafb97ea6 100644 --- a/tests/Http/UriTest.php +++ b/tests/Http/UriTest.php @@ -180,6 +180,13 @@ public function testGetUserInfoNone() $this->assertEquals('', $uri->getUserInfo()); } + public function testGetUserInfoWithUsernameAndPasswordEncodesCorrectly() + { + $uri = Uri::createFromString('https://bob%40example.com:pass%3Aword@example.com:443/foo/bar?abc=123#section3'); + + $this->assertEquals('bob%40example.com:pass%3Aword', $uri->getUserInfo()); + } + public function testWithUserInfo() { $uri = $this->uriFactory()->withUserInfo('bob', 'pass'); @@ -188,6 +195,14 @@ public function testWithUserInfo() $this->assertAttributeEquals('pass', 'password', $uri); } + public function testWithUserInfoEncodesCorrectly() + { + $uri = $this->uriFactory()->withUserInfo('bob@example.com', 'pass:word'); + + $this->assertAttributeEquals('bob%40example.com', 'user', $uri); + $this->assertAttributeEquals('pass%3Aword', 'password', $uri); + } + public function testWithUserInfoRemovesPassword() { $uri = $this->uriFactory()->withUserInfo('bob');