Skip to content

Commit

Permalink
[FIX] 0041321: Character "&" and "ß" in page title in wiki resolving …
Browse files Browse the repository at this point in the history
…in crash (due to ilCtrl parameter handling, see comments)
  • Loading branch information
chfsx authored and thibsy committed May 7, 2024
1 parent e5d6c84 commit 2c36cb0
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public function init(Container $dic): void
$dic->refinery(),
$dic["component.factory"],
new ilCtrlSubject(),
new ilCtrlQueryRegexParser(),
);

// add helper function to DI container that
Expand Down
5 changes: 3 additions & 2 deletions components/ILIAS/UICore/classes/class.ilCtrl.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public function __construct(
protected Refinery $refinery,
protected ilComponentFactory $component_factory,
protected ilCtrlSubject $subject,
protected ilCtrlQueryParserInterface $query_parser,
) {
}

Expand Down Expand Up @@ -1089,7 +1090,8 @@ private function appendParameterString(

/** @var array{path: string|null, query: string[]|null} $parsed_url */
$parsed_url = parse_url(str_replace('&', '&', $url));
parse_str(($parsed_url['query'] ?? ''), $query_parameters);

$query_parameters = $this->query_parser->parseQueriesOfURL($parsed_url['query'] ?? '');

// update the given parameter or add it to the list.
$query_parameters[$parameter_name] = $value;
Expand All @@ -1099,7 +1101,6 @@ private function appendParameterString(
$ampersand = ($is_escaped) ? '&' : '&';

foreach ($query_parameters as $parameter => $parameter_value) {
$parameter_value = urlencode($parameter_value);
$new_url .= (strpos($new_url, '?') !== false) ?
$ampersand . "$parameter=$parameter_value" :
"?$parameter=$parameter_value";
Expand Down
39 changes: 39 additions & 0 deletions components/ILIAS/UICore/classes/class.ilCtrlQueryRegexParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/

declare(strict_types=1);

/**
* @author Fabian Schmid <[email protected]>
*/
class ilCtrlQueryRegexParser implements ilCtrlQueryParserInterface
{
private const PATTERN = '/([^=&]*)=([^=&]*)/m';

public function parseQueriesOfURL(string $query_string): array
{
preg_match_all(self::PATTERN, $query_string, $matches, PREG_SET_ORDER, 0);
$query_parameters = [];
foreach ($matches as $match) {
$query_parameters[$match[1]] = $match[2];
}

return $query_parameters;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/

/**
* @author Fabian Schmid <[email protected]>
*/
interface ilCtrlQueryParserInterface
{
/**
* Must return an associative array of key => value pairs from the given query string.
* @param string $query_string
* @return array<string, string>
*/
public function parseQueriesOfURL(string $query_string): array;
}
99 changes: 99 additions & 0 deletions components/ILIAS/UICore/tests/ilCtrlQueryParserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/

declare(strict_types=1);

use PHPUnit\Framework\TestCase;

/**
* @author Fabian Schmid <[email protected]>
*/
class ilCtrlQueryParserTest extends TestCase
{
private ?ilCtrlQueryRegexParser $query_parser = null;

protected function setUp(): void
{
$this->query_parser = new ilCtrlQueryRegexParser();
}

public function queryStringProvider(): array
{
return [
[
'ilias.php?',
[],
],
[
'ilias.php?ref_id=123&parent_ref_id=456',
[
'ref_id' => '123',
'parent_ref_id' => '456',
],
],
[
'ilias.php?param1=some%26value&param2=other_value',
[
'param1' => 'some%26value',
'param2' => 'other_value',
]
],
[
'ilias.php?baseClass=ilwikihandlergui&cmdNode=161:r9:7n:kl&cmdClass=ilnotegui&ref_id=2731&page=Meine_%26_Seite',
[
'ref_id' => '2731',
'baseClass' => 'ilwikihandlergui',
'cmdNode' => '161:r9:7n:kl',
'cmdClass' => 'ilnotegui',
'page' => 'Meine_%26_Seite',
]
],
[
'ilias.php?baseClass=ilwikihandlergui&cmdNode=161:r9:164&cmdClass=ilwikipagegui&cmd=whatLinksHere&ref_id=2731&page=Meine_%26_Seite',
[
'ref_id' => '2731',
'baseClass' => 'ilwikihandlergui',
'cmdNode' => '161:r9:164',
'cmdClass' => 'ilwikipagegui',
'cmd' => 'whatLinksHere',
'page' => 'Meine_%26_Seite',
]
],
[
'ilias.php?baseClass=ilwikihandlergui&cmdNode=161:r9:164:7n:128&cmdClass=iltagginggui&ref_id=2731&page=Meine_%26_Seite&cmdMode=asynch',
[
'ref_id' => '2731',
'baseClass' => 'ilwikihandlergui',
'cmdNode' => '161:r9:164:7n:128',
'cmdClass' => 'iltagginggui',
'page' => 'Meine_%26_Seite',
'cmdMode' => 'asynch',
]
],
];
}

/**
* @dataProvider queryStringProvider
*/
public function testQueryParser(string $query_string, array $expected_queries): void
{
$parsed_queries = $this->query_parser->parseQueriesOfURL($query_string);
$this->assertEquals($expected_queries, $parsed_queries);
}
}
9 changes: 6 additions & 3 deletions components/ILIAS/UICore/tests/ilCtrlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ public function testCallBaseClassWithInvalidProvidedBaseClass(): void
$this->createMock(RequestWrapper::class),
$this->createMock(Refinery::class),
$this->createMock(ilComponentFactory::class),
new ilCtrlSubject()
new ilCtrlSubject(),
$this->createMock(ilCtrlQueryParserInterface::class),
);

$invalid_baseclass = ilCtrlInvalidGuiClass::class;
Expand Down Expand Up @@ -142,7 +143,8 @@ public function testGetCmdWithoutProvidedCmdAndFallback(): void
$this->createMock(RequestWrapper::class),
$this->createMock(Refinery::class),
$this->createMock(ilComponentFactory::class),
new ilCtrlSubject()
new ilCtrlSubject(),
$this->createMock(ilCtrlQueryParserInterface::class),
);

$fallback_cmd = 'fallback_cmd_test';
Expand Down Expand Up @@ -231,7 +233,8 @@ private function getMockedCtrl(): ilCtrlInterface
$this->createMock(RequestWrapper::class),
$this->createMock(Refinery::class),
$this->createMock(ilComponentFactory::class),
new ilCtrlSubject()
new ilCtrlSubject(),
$this->createMock(ilCtrlQueryParserInterface::class),
);
}
}

0 comments on commit 2c36cb0

Please sign in to comment.