From 547bda6e4fa03386448148664f05aaf5c672f91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 22 Feb 2024 09:33:21 +0100 Subject: [PATCH 1/4] fix #4964 --- addons/addon-web-links/src/WebLinkProvider.ts | 30 ++++++++----------- addons/addon-web-links/src/WebLinksAddon.ts | 2 +- .../addon-web-links/test/WebLinksAddon.api.ts | 13 ++++++++ 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/addons/addon-web-links/src/WebLinkProvider.ts b/addons/addon-web-links/src/WebLinkProvider.ts index 713f9c23..63211dad 100644 --- a/addons/addon-web-links/src/WebLinkProvider.ts +++ b/addons/addon-web-links/src/WebLinkProvider.ts @@ -41,16 +41,18 @@ export class WebLinkProvider implements ILinkProvider { } } -function baseUrlString(url: URL): string { - if (url.password && url.username) { - return `${url.protocol}//${url.username}:${url.password}@${url.host}`; +function isUrl(urlString: string): boolean { + try { + const url = new URL(urlString); + const parsedBase = url.password && url.username + ? `${url.protocol}//${url.username}:${url.password}@${url.host}` + : url.username + ? `${url.protocol}//${url.username}@${url.host}` + : `${url.protocol}//${url.host}`; + return urlString.toLocaleLowerCase().startsWith(parsedBase); + } catch (e) { + return false; } - - if (url.username) { - return `${url.protocol}//${url.username}@${url.host}`; - } - - return `${url.protocol}//${url.host}`; } export class LinkComputer { @@ -67,15 +69,7 @@ export class LinkComputer { const text = match[0]; // check via URL if the matched text would form a proper url - // NOTE: This outsources the ugly url parsing to the browser. - // we check if the provided string resembles the URL-parsed one - // up to the end of the domain name (ignoring path and params) - try { - const url = new URL(text); - if (!text.startsWith(baseUrlString(url))) { - continue; - } - } catch (e) { + if (!isUrl(text)) { continue; } diff --git a/addons/addon-web-links/src/WebLinksAddon.ts b/addons/addon-web-links/src/WebLinksAddon.ts index 8902d8e0..b3f0548c 100644 --- a/addons/addon-web-links/src/WebLinksAddon.ts +++ b/addons/addon-web-links/src/WebLinksAddon.ts @@ -18,7 +18,7 @@ import { ILinkProviderOptions, WebLinkProvider } from './WebLinkProvider'; // - final interpunction like ,.!? // - any sort of brackets <>()[]{} (not spec conform, but often used to enclose urls) // - unsafe chars from rfc1738: {}|\^~[]` -const strictUrlRegex = /https?:[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/; +const strictUrlRegex = /(https?|HTTPS?):[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/; function handleLink(event: MouseEvent, uri: string): void { diff --git a/addons/addon-web-links/test/WebLinksAddon.api.ts b/addons/addon-web-links/test/WebLinksAddon.api.ts index 5b05ce2e..26a7421d 100644 --- a/addons/addon-web-links/test/WebLinksAddon.api.ts +++ b/addons/addon-web-links/test/WebLinksAddon.api.ts @@ -123,6 +123,19 @@ describe('WebLinksAddon', () => { await evalLinkStateData('http://test:password@example.com/some_path?param=1%202%3', { start: { x: 12, y: 1 }, end: { x: 27, y: 2 } }); }); }); + + // issue #4964 + it.only('uppercase in protocol and host, default ports', async () => { + const data = ` HTTP://EXAMPLE.COM \\r\\n` + + ` HTTPS://Example.com \\r\\n` + + ` HTTP://Example.com:80 \\r\\n` + + ` HTTP://Example.com:80/staysUpper \\r\\n`; + await writeSync(page, data); + await pollForLinkAtCell(3, 0, `HTTP://EXAMPLE.COM`); + await pollForLinkAtCell(3, 1, `HTTPS://Example.com`); + await pollForLinkAtCell(3, 2, `HTTP://Example.com:80`); + await pollForLinkAtCell(3, 3, `HTTP://Example.com:80/staysUpper`); + }); }); async function testHostName(hostname: string): Promise { From 768452a519e96bb53faa1eb7e306113295c6346b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 22 Feb 2024 09:38:36 +0100 Subject: [PATCH 2/4] make linter happy --- addons/addon-web-links/test/WebLinksAddon.api.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/addon-web-links/test/WebLinksAddon.api.ts b/addons/addon-web-links/test/WebLinksAddon.api.ts index 26a7421d..e4e5ce94 100644 --- a/addons/addon-web-links/test/WebLinksAddon.api.ts +++ b/addons/addon-web-links/test/WebLinksAddon.api.ts @@ -126,15 +126,15 @@ describe('WebLinksAddon', () => { // issue #4964 it.only('uppercase in protocol and host, default ports', async () => { - const data = ` HTTP://EXAMPLE.COM \\r\\n` + + const data = ` HTTP://EXAMPLE.COM \\r\\n` + ` HTTPS://Example.com \\r\\n` + ` HTTP://Example.com:80 \\r\\n` + ` HTTP://Example.com:80/staysUpper \\r\\n`; - await writeSync(page, data); - await pollForLinkAtCell(3, 0, `HTTP://EXAMPLE.COM`); - await pollForLinkAtCell(3, 1, `HTTPS://Example.com`); - await pollForLinkAtCell(3, 2, `HTTP://Example.com:80`); - await pollForLinkAtCell(3, 3, `HTTP://Example.com:80/staysUpper`); + await writeSync(page, data); + await pollForLinkAtCell(3, 0, `HTTP://EXAMPLE.COM`); + await pollForLinkAtCell(3, 1, `HTTPS://Example.com`); + await pollForLinkAtCell(3, 2, `HTTP://Example.com:80`); + await pollForLinkAtCell(3, 3, `HTTP://Example.com:80/staysUpper`); }); }); From 5143f904ee7926740f194328356594ebf2c9a8b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 22 Feb 2024 09:40:38 +0100 Subject: [PATCH 3/4] remove leftover .only --- addons/addon-web-links/test/WebLinksAddon.api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/addon-web-links/test/WebLinksAddon.api.ts b/addons/addon-web-links/test/WebLinksAddon.api.ts index e4e5ce94..6c3c8b1e 100644 --- a/addons/addon-web-links/test/WebLinksAddon.api.ts +++ b/addons/addon-web-links/test/WebLinksAddon.api.ts @@ -125,7 +125,7 @@ describe('WebLinksAddon', () => { }); // issue #4964 - it.only('uppercase in protocol and host, default ports', async () => { + it('uppercase in protocol and host, default ports', async () => { const data = ` HTTP://EXAMPLE.COM \\r\\n` + ` HTTPS://Example.com \\r\\n` + ` HTTP://Example.com:80 \\r\\n` + From 10fe2498777abe45691ec427826299c476a85e01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 22 Feb 2024 09:55:42 +0100 Subject: [PATCH 4/4] allow user+password to still match --- addons/addon-web-links/src/WebLinkProvider.ts | 2 +- addons/addon-web-links/test/WebLinksAddon.api.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/addon-web-links/src/WebLinkProvider.ts b/addons/addon-web-links/src/WebLinkProvider.ts index 63211dad..66691f44 100644 --- a/addons/addon-web-links/src/WebLinkProvider.ts +++ b/addons/addon-web-links/src/WebLinkProvider.ts @@ -49,7 +49,7 @@ function isUrl(urlString: string): boolean { : url.username ? `${url.protocol}//${url.username}@${url.host}` : `${url.protocol}//${url.host}`; - return urlString.toLocaleLowerCase().startsWith(parsedBase); + return urlString.toLocaleLowerCase().startsWith(parsedBase.toLocaleLowerCase()); } catch (e) { return false; } diff --git a/addons/addon-web-links/test/WebLinksAddon.api.ts b/addons/addon-web-links/test/WebLinksAddon.api.ts index 6c3c8b1e..99c11600 100644 --- a/addons/addon-web-links/test/WebLinksAddon.api.ts +++ b/addons/addon-web-links/test/WebLinksAddon.api.ts @@ -129,12 +129,14 @@ describe('WebLinksAddon', () => { const data = ` HTTP://EXAMPLE.COM \\r\\n` + ` HTTPS://Example.com \\r\\n` + ` HTTP://Example.com:80 \\r\\n` + - ` HTTP://Example.com:80/staysUpper \\r\\n`; + ` HTTP://Example.com:80/staysUpper \\r\\n` + + ` HTTP://Ab:xY@abc.com:80/staysUpper \\r\\n`; await writeSync(page, data); await pollForLinkAtCell(3, 0, `HTTP://EXAMPLE.COM`); await pollForLinkAtCell(3, 1, `HTTPS://Example.com`); await pollForLinkAtCell(3, 2, `HTTP://Example.com:80`); await pollForLinkAtCell(3, 3, `HTTP://Example.com:80/staysUpper`); + await pollForLinkAtCell(3, 4, `HTTP://Ab:xY@abc.com:80/staysUpper`); }); });