diff options
author | Alexandre Alapetite <alexandre@alapetite.fr> | 2024-09-12 11:04:49 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-12 11:04:49 +0200 |
commit | fd1b5e9343b6fe92b4e5dfbbc2f01ddfcd010af9 (patch) | |
tree | 5cc4e7399212d2fdce401465e3590f2275b16c26 | |
parent | d1f1e42c2b180f34276d7ddd1a2bfeaf4e59ed05 (diff) | |
download | freshrss-fd1b5e9343b6fe92b4e5dfbbc2f01ddfcd010af9.tar.gz freshrss-fd1b5e9343b6fe92b4e5dfbbc2f01ddfcd010af9.zip |
Fix inversed encoding logic in paramArray (#6800)
* Fix inversed encoding logic in paramArray
https://github.com/FreshRSS/FreshRSS/pull/6797#discussion_r1754661634
Also fix the possibility to use `<'&">` in shortcuts, and some minor encoding bugs in user queries
* Forgot paramArrayString
-rw-r--r-- | app/Controllers/configureController.php | 9 | ||||
-rw-r--r-- | app/Models/BooleanSearch.php | 1 | ||||
-rw-r--r-- | app/Models/UserQuery.php | 2 | ||||
-rw-r--r-- | app/views/configure/shortcut.phtml | 4 | ||||
-rw-r--r-- | lib/Minz/Request.php | 22 | ||||
-rw-r--r-- | p/scripts/main.js | 5 |
6 files changed, 33 insertions, 10 deletions
diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php index a9304376f..612129b8a 100644 --- a/app/Controllers/configureController.php +++ b/app/Controllers/configureController.php @@ -202,7 +202,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController { $this->view->list_keys = SHORTCUT_KEYS; if (Minz_Request::isPost()) { - $shortcuts = Minz_Request::paramArray('shortcuts'); + $shortcuts = Minz_Request::paramArray('shortcuts', specialchars: true); if (Minz_Request::paramBoolean('load_default_shortcuts')) { $default = Minz_Configuration::load(FRESHRSS_PATH . '/config-user.default.php'); $shortcuts = $default['shortcuts']; @@ -379,12 +379,13 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController { $name = _t('conf.query.number', $id + 1); } if (!empty($params['get']) && is_string($params['get'])) { - $queryParams['get'] = htmlspecialchars_decode($params['get'], ENT_QUOTES); + $queryParams['get'] = $params['get']; } if (!empty($params['order']) && is_string($params['order'])) { - $queryParams['order'] = htmlspecialchars_decode($params['order'], ENT_QUOTES); + $queryParams['order'] = $params['order']; } if (!empty($params['search']) && is_string($params['search'])) { + // Search must be as plain text to be XML-encoded or URL-encoded depending on the situation $queryParams['search'] = htmlspecialchars_decode($params['search'], ENT_QUOTES); } if (!empty($params['state']) && is_array($params['state'])) { @@ -398,7 +399,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController { $queryParams['url'] = Minz_Url::display(['params' => $queryParams]); $queryParams['name'] = $name; if (!empty($params['description']) && is_string($params['description'])) { - $queryParams['description'] = htmlspecialchars_decode($params['description'], ENT_QUOTES); + $queryParams['description'] = $params['description']; } if (!empty($params['imageUrl']) && is_string($params['imageUrl'])) { $queryParams['imageUrl'] = $params['imageUrl']; diff --git a/app/Models/BooleanSearch.php b/app/Models/BooleanSearch.php index 88069c461..9e9dec2a2 100644 --- a/app/Models/BooleanSearch.php +++ b/app/Models/BooleanSearch.php @@ -402,6 +402,7 @@ class FreshRSS_BooleanSearch { return $this->getRawInput(); } + /** @return string Plain text search query. Must be XML-encoded or URL-encoded depending on the situation */ public function getRawInput(): string { return $this->raw_input; } diff --git a/app/Models/UserQuery.php b/app/Models/UserQuery.php index dcd17393e..d701b6b44 100644 --- a/app/Models/UserQuery.php +++ b/app/Models/UserQuery.php @@ -13,6 +13,7 @@ class FreshRSS_UserQuery { private string $get = ''; private string $get_name = ''; private string $get_type = ''; + /** XML-encoded name */ private string $name = ''; private string $order = ''; private FreshRSS_BooleanSearch $search; @@ -25,6 +26,7 @@ class FreshRSS_UserQuery { private array $categories; /** @var array<int,FreshRSS_Tag> $labels */ private array $labels; + /** XML-encoded description */ private string $description = ''; private string $imageUrl = ''; diff --git a/app/views/configure/shortcut.phtml b/app/views/configure/shortcut.phtml index 78b659120..b7930f263 100644 --- a/app/views/configure/shortcut.phtml +++ b/app/views/configure/shortcut.phtml @@ -16,7 +16,9 @@ <?php } ?> </datalist> - <?php $s = FreshRSS_Context::userConf()->shortcuts; ?> + <?php + $s = array_map(static fn(string $string) => htmlspecialchars($string, ENT_COMPAT, 'UTF-8'), FreshRSS_Context::userConf()->shortcuts); + ?> <?php if ([] !== $nonStandard = getNonStandardShortcuts($s)): ?> <p class="alert alert-error"> diff --git a/lib/Minz/Request.php b/lib/Minz/Request.php index fcece464b..542741d4a 100644 --- a/lib/Minz/Request.php +++ b/lib/Minz/Request.php @@ -40,7 +40,7 @@ class Minz_Request { * Read the URL parameter * @param string $key Key name * @param mixed $default default value, if no parameter is given - * @param bool $specialchars special characters + * @param bool $specialchars `true` to return special characters, `false` (default) to XML-encode them * @return mixed value of the parameter * @deprecated use typed versions instead */ @@ -61,21 +61,27 @@ class Minz_Request { return isset(self::$params[$key]); } - /** @return array<string|int,string|array<string,string|int|bool>> */ + /** + * @param bool $specialchars `true` to return special characters, `false` (default) to XML-encode them + * @return array<string|int,string|array<string,string|int|bool>> + */ public static function paramArray(string $key, bool $specialchars = false): array { if (empty(self::$params[$key]) || !is_array(self::$params[$key])) { return []; } - return $specialchars ? Minz_Helper::htmlspecialchars_utf8(self::$params[$key]) : self::$params[$key]; + return $specialchars ? self::$params[$key] : Minz_Helper::htmlspecialchars_utf8(self::$params[$key]); } - /** @return array<string> */ + /** + * @param bool $specialchars `true` to return special characters, `false` (default) to XML-encode them + * @return array<string> + */ public static function paramArrayString(string $key, bool $specialchars = false): array { if (empty(self::$params[$key]) || !is_array(self::$params[$key])) { return []; } $result = array_filter(self::$params[$key], 'is_string'); - return $specialchars ? Minz_Helper::htmlspecialchars_utf8($result) : $result; + return $specialchars ? $result : Minz_Helper::htmlspecialchars_utf8($result); } public static function paramTernary(string $key): ?bool { @@ -106,6 +112,9 @@ class Minz_Request { return 0; } + /** + * @param bool $specialchars `true` to return special characters, `false` (default) to XML-encode them + */ public static function paramStringNull(string $key, bool $specialchars = false): ?string { if (isset(self::$params[$key])) { $s = self::$params[$key]; @@ -120,6 +129,9 @@ class Minz_Request { return null; } + /** + * @param bool $specialchars `true` to return special characters, `false` (default) to XML-encode them + */ public static function paramString(string $key, bool $specialchars = false): string { return self::paramStringNull($key, $specialchars) ?? ''; } diff --git a/p/scripts/main.js b/p/scripts/main.js index 663bfe74e..1566b38cb 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -908,6 +908,11 @@ function init_column_categories() { function init_shortcuts() { Object.keys(context.shortcuts).forEach(function (k) { context.shortcuts[k] = (context.shortcuts[k] || '').toUpperCase(); + if (context.shortcuts[k].indexOf('&') >= 0) { + // Decode potential HTML entities <'&"> + const parser = new DOMParser(); + context.shortcuts[k] = parser.parseFromString(context.shortcuts[k], 'text/html').documentElement.textContent; + } }); document.addEventListener('keydown', ev => { |