From 38743404da21c61cc7fa65cf51e10eff21c08e21 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Willms <tleilax+github@gmail.com> Date: Thu, 17 Feb 2022 07:51:00 +0100 Subject: [PATCH] introduce js encodeURI() equivalent in php and use it for X-Location header, fixes #684 --- app/controllers/studip_controller.php | 2 +- lib/functions.php | 34 ++++++++++++++++++++++ resources/assets/javascripts/lib/dialog.js | 2 +- tests/unit/lib/FunctionsTest.php | 18 ++++++++++-- 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/app/controllers/studip_controller.php b/app/controllers/studip_controller.php index 556ff8b6284..7c0991e4806 100644 --- a/app/controllers/studip_controller.php +++ b/app/controllers/studip_controller.php @@ -349,7 +349,7 @@ abstract class StudipController extends Trails_Controller $to = $this->adjustToArguments(...func_get_args()); if (Request::isDialog()) { - $this->response->add_header('X-Location', rawurlencode($to)); + $this->response->add_header('X-Location', encodeURI($to)); $this->render_nothing(); } else { parent::redirect($to); diff --git a/lib/functions.php b/lib/functions.php index 96dd9551731..bbed6298f50 100644 --- a/lib/functions.php +++ b/lib/functions.php @@ -1827,3 +1827,37 @@ function get_default_http_stream_context($url = '') } return stream_context_get_default($opts); } + +/** + * Encodes an uri just like encodeURI() in Javascript would do. + * + * encodeURI() escapes all characters except: + * + * A-Z a-z 0-9 ; , / ? : @ & = + $ - _ . ! ~ * ' ( ) # + * + * @param string $uri + * @return string + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI + */ +function encodeURI(string $uri): string +{ + $replacements = [ + '%21' => '!', + '%23' => '#', + '%24' => '$', + '%26' => '&', + '%27' => "'", + '%28' => '(', + '%29' => ')', + '%2A' => '*', + '%2B' => '+', + '%2C' => ',', + '%3B' => ';', + '%2F' => '/', + '%3A' => ':', + '%3D' => '=', + '%3F' => '?', + '%40' => '@', + ]; + return strtr(rawurlencode($uri), $replacements); +} diff --git a/resources/assets/javascripts/lib/dialog.js b/resources/assets/javascripts/lib/dialog.js index de016ed72f0..0ce30c6eef6 100644 --- a/resources/assets/javascripts/lib/dialog.js +++ b/resources/assets/javascripts/lib/dialog.js @@ -103,7 +103,7 @@ const Dialog = { // Handler for HTTP header X-Location: Relocate to another location Dialog.handlers.header['X-Location'] = function(location, options) { - location = decodeURIComponent(location); + location = decodeURI(location); if (document.location.href === location) { document.location.reload(true); diff --git a/tests/unit/lib/FunctionsTest.php b/tests/unit/lib/FunctionsTest.php index 2d3c868f3ea..61ad409ed50 100644 --- a/tests/unit/lib/FunctionsTest.php +++ b/tests/unit/lib/FunctionsTest.php @@ -42,7 +42,7 @@ class FunctionsTest extends \Codeception\Test\Unit $this->assertEquals(range(1, 7), array_flatten($array)); } - + function testRelsize() { // Test basic sizes and suffixed 's' if value is <> 1 @@ -62,7 +62,7 @@ class FunctionsTest extends \Codeception\Test\Unit $this->assertEquals('1 Exabyte', relsize(pow(1024, 6))); $this->assertEquals('1 Zettabyte', relsize(pow(1024, 7))); $this->assertEquals('1 Yottabyte', relsize(pow(1024, 8))); - + // Test displayed levels $this->assertEquals('1 Megabyte', relsize(1024 * 1024 + 2 * 1024 + 3, true, 1)); $this->assertEquals('1.5 Megabytes', relsize(1024 * 1024 + 512 * 1024 + 3, true, 1)); @@ -70,4 +70,18 @@ class FunctionsTest extends \Codeception\Test\Unit $this->assertEquals('1 Megabyte, 2 Kilobytes, 3 Bytes', relsize(1024 * 1024 + 2 * 1024 + 3, true, 3)); $this->assertEquals('1 Megabyte, 2 Kilobytes, 3 Bytes', relsize(1024 * 1024 + 2 * 1024 + 3, true, 0)); } + + public function testEncodeURI() + { + $input = 'A-Za-z0-9;,/?:@&=+$-_.!~*\'()#'; + $this->assertEquals($input, encodeURI($input)); + + $input = 'https://example.org/?x=шеллы'; + $output = 'https://example.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B'; + $this->assertEquals($output, encodeURI($input)); + + $input = 'https://mäuschen-hüpft.de/öffnungszeiten?menu=Spaß&page=23'; + $output = 'https://m%C3%A4uschen-h%C3%BCpft.de/%C3%B6ffnungszeiten?menu=Spa%C3%9F&page=23'; + $this->assertEquals($output, encodeURI($input)); + } } -- GitLab