From a2a255a2411c7e2b006fb2b067634607719eb716 Mon Sep 17 00:00:00 2001 From: Isaac Hill <71404865+isaachilly@users.noreply.github.com> Date: Wed, 5 Aug 2026 17:27:29 +0200 Subject: [PATCH 1/2] Use a more extensive URI encoder that covers special characters such as plusses `+` does not get encoded by the minimal `encodeURI` method. The `encodeURIComponent` method is more suitable for encoding individual query parameters. --- InfoLogger/public/logFilter/LogFilter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InfoLogger/public/logFilter/LogFilter.js b/InfoLogger/public/logFilter/LogFilter.js index cf83a3fc1..29c45b0cc 100644 --- a/InfoLogger/public/logFilter/LogFilter.js +++ b/InfoLogger/public/logFilter/LogFilter.js @@ -142,7 +142,7 @@ export default class LogFilter extends Observable { delete criterias[field][operator]; } else if (operator === 'match' || operator === 'exclude') { // encode potential breaking characters and escape double quotes as are used by browser by default - criterias[field][operator] = encodeURI(criterias[field][operator].replace(/["]+/g, '\\"')); + criterias[field][operator] = encodeURIComponent(criterias[field][operator].replace(/["]+/g, '\\"')); } // remove empty fields From e0bbb4dcddd4698bb944b03e6ed2c1e089dabe41 Mon Sep 17 00:00:00 2001 From: Isaac Hill <71404865+isaachilly@users.noreply.github.com> Date: Wed, 5 Aug 2026 17:37:21 +0200 Subject: [PATCH 2/2] Adds tests that cover the correct encoding/decoding of special characters in filters --- .../test/public/log-filter-actions-mocha.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/InfoLogger/test/public/log-filter-actions-mocha.js b/InfoLogger/test/public/log-filter-actions-mocha.js index 6f7da8e8b..cab6a8768 100644 --- a/InfoLogger/test/public/log-filter-actions-mocha.js +++ b/InfoLogger/test/public/log-filter-actions-mocha.js @@ -249,6 +249,30 @@ describe('Filter actions test-suite', async () => { assert.deepStrictEqual($in, ['I', 'W', 'E', 'F']); }); + it('should encode special characters correctly into the URL', async () => { + const pidMatch = await page.evaluate(() => { + window.model.log.filter.setCriteria('pid', 'match', 'a+b c %d #anchor & = héllo wörld 日本語'); + return window.model.log.filter.criterias.pid.$match; + }); + + assert.strictEqual(pidMatch, 'a+b c %d #anchor & = héllo wörld 日本語'); + + const searchParams = await page.evaluate(() => { + window.model.updateRouteOnModelChange(); + return window.location.search; + }); + + assert.ok(searchParams.includes('a%2Bb%20c%20%25d%20%23anchor%20%26%20%3D%20h%C3%A9llo%20w%C3%B6rld%20%E6%97%A5%E6%9C%AC%E8%AA%9E')); + }); + + it('should decode special characters correctly from the URL', async () => { + await page.goto(`${baseUrl}?q={%22pid%22:{%22match%22:%22a%2Bb%20c%20%25d%20%23anchor%20%26%20%3D%20h%C3%A9llo%20w%C3%B6rld%20%E6%97%A5%E6%9C%AC%E8%AA%9E%22}}`, { waitUntil: 'networkidle0' }); + + const pidMatch = await page.evaluate(() => window.model.log.filter.criterias.pid.$match); + + assert.strictEqual(pidMatch, 'a+b c %d #anchor & = héllo wörld 日本語'); + }); + it('should reset filters and set them again', async () => { const criterias = await page.evaluate(() => { window.model.log.filter.resetCriteria();