mirror of
https://github.com/keepassxreboot/keepassxc-browser.git
synced 2026-03-11 08:54:43 +00:00
Replace Match Patterns regex with a simpler function (#1851)
Replace Match Patterns regex with a simpler function
This commit is contained in:
parent
88a4acb1e6
commit
e97df10c60
5 changed files with 78 additions and 119 deletions
|
|
@ -22,9 +22,9 @@ const CHECK_UPDATE_THREE_DAYS = 3;
|
|||
const CHECK_UPDATE_ONE_WEEK = 7;
|
||||
const CHECK_UPDATE_ONE_MONTH = 30;
|
||||
|
||||
const URL_WILDCARD = '1kpxcwc1';
|
||||
const schemeSegment = '(\\*|http|https|ws|wss|ftp)';
|
||||
const hostSegment = '(\\*|(?:\\*\\.)?(?:[^/*]+))?';
|
||||
const pathSegment = '(.*)';
|
||||
|
||||
const isFirefox = function() {
|
||||
return navigator.userAgent.indexOf('Firefox') !== -1 || navigator.userAgent.indexOf('Gecko/') !== -1;
|
||||
|
|
@ -56,86 +56,54 @@ const ManualFill = {
|
|||
BOTH: 2
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms a valid match pattern into a regular expression
|
||||
* which matches all URLs included by that pattern.
|
||||
*
|
||||
* @param {string} pattern The pattern to transform.
|
||||
* @return {RegExp} The pattern's equivalent as a RegExp.
|
||||
* @throws {TypeError} If the pattern is not a valid MatchPattern
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Match_patterns
|
||||
*/
|
||||
const matchPatternToRegExp = function(pattern) {
|
||||
if (pattern === '') {
|
||||
return (/^(?:http|https|file|ftp|app):\/\//);
|
||||
// Match hostname or path with wildcards
|
||||
const matchWithRegex = function(firstUrlPart, secondUrlPart, hostnameUsed = false) {
|
||||
if (firstUrlPart === secondUrlPart) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// special handling of file:// since there is no host
|
||||
if (pattern.startsWith('file://')) {
|
||||
let regex = '^';
|
||||
pattern = pattern.replace(/\./g, '\\.');
|
||||
if (pattern.endsWith('*')) {
|
||||
regex += pattern.slice(0, -1);
|
||||
} else {
|
||||
regex += `${pattern}$`;
|
||||
}
|
||||
return new RegExp(regex);
|
||||
// If there's no wildcard with hostname, just compare directly
|
||||
if (hostnameUsed && !firstUrlPart.includes(URL_WILDCARD) && firstUrlPart !== secondUrlPart) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const matchPatternRegExp = new RegExp(
|
||||
`^${schemeSegment}://${hostSegment}/${pathSegment}$`
|
||||
);
|
||||
|
||||
const match = matchPatternRegExp.exec(pattern);
|
||||
if (!match) {
|
||||
throw new TypeError(`"${pattern}" is not a valid MatchPattern`);
|
||||
// Escape illegal characters
|
||||
let re = firstUrlPart.replaceAll(/[!\^$\+\-\(\)@<>]/g, '\\$&');
|
||||
if (hostnameUsed) {
|
||||
// Replace all host parts with wildcards so e.g. https://*.example.com is accepted with https://example.com
|
||||
re = re.replaceAll(`${URL_WILDCARD}.`, '(.*?)');
|
||||
}
|
||||
|
||||
let [ , scheme, host, path ] = match;
|
||||
if (!host) {
|
||||
throw new TypeError(`"${pattern}" does not have a valid host`);
|
||||
}
|
||||
// Replace any remaining wildcards for paths
|
||||
re = re.replaceAll(URL_WILDCARD, '(.*?)');
|
||||
|
||||
let regex = '^';
|
||||
|
||||
if (scheme === '*') {
|
||||
regex += '(http|https)';
|
||||
} else {
|
||||
regex += scheme;
|
||||
}
|
||||
|
||||
regex += '://';
|
||||
|
||||
if (host && host === '*') {
|
||||
regex += '[^/]+?';
|
||||
} else if (host) {
|
||||
if (host.match(/^\*\./)) {
|
||||
regex += '[^/]*?';
|
||||
host = host.substring(2);
|
||||
}
|
||||
regex += host.replace(/\./g, '\\.');
|
||||
}
|
||||
|
||||
if (path) {
|
||||
path = trimURL(path);
|
||||
|
||||
if (path === '*') {
|
||||
regex += '(/.*)?';
|
||||
} else if (path.charAt(0) !== '/') {
|
||||
regex += '/';
|
||||
regex += path.replace(/\./g, '\\.').replace(/\*/g, '.*?');
|
||||
regex += '/?';
|
||||
}
|
||||
}
|
||||
|
||||
regex += '$';
|
||||
return new RegExp(regex);
|
||||
return secondUrlPart.match(new RegExp(re));
|
||||
};
|
||||
|
||||
// Matches URL in Site Preferences with the current URL
|
||||
const siteMatch = function(site, url) {
|
||||
const rx = matchPatternToRegExp(site);
|
||||
return url.match(rx);
|
||||
try {
|
||||
site = site.replaceAll('*', URL_WILDCARD);
|
||||
const siteUrl = new URL(site);
|
||||
const currentUrl = new URL(url);
|
||||
|
||||
// Match scheme and port
|
||||
if (siteUrl.protocol !== currentUrl.protocol || siteUrl.port !== currentUrl.port) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Match hostname and path
|
||||
if (!matchWithRegex(siteUrl.hostname, currentUrl.hostname, true)
|
||||
|| !matchWithRegex(siteUrl.pathname, currentUrl.pathname)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
logError(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const slashNeededForUrl = function(pattern) {
|
||||
|
|
|
|||
|
|
@ -11,28 +11,8 @@ const PREDEFINED_SITELIST = [
|
|||
'https://outlook.live.com/*',
|
||||
'https://login.live.com/*',
|
||||
'https://odc.officeapps.live.com/*',
|
||||
'https://login.microsoftonline.com/*',
|
||||
'https://login.microsoftonline.us/*',
|
||||
'https://www.amazon.ae/ap/*',
|
||||
'https://www.amazon.ca/ap/*',
|
||||
'https://www.amazon.cn/ap/*',
|
||||
'https://www.amazon.co.jp/ap/*',
|
||||
'https://www.amazon.co.uk/ap/*',
|
||||
'https://www.amazon.com/ap/*',
|
||||
'https://www.amazon.com.au/ap/*',
|
||||
'https://www.amazon.com.br/ap/*',
|
||||
'https://www.amazon.com.mx/ap/*',
|
||||
'https://www.amazon.com.tr/ap/*',
|
||||
'https://www.amazon.de/ap/*',
|
||||
'https://www.amazon.es/ap/*',
|
||||
'https://www.amazon.fr/ap/*',
|
||||
'https://www.amazon.in/ap/*',
|
||||
'https://www.amazon.it/ap/*',
|
||||
'https://www.amazon.nl/ap/*',
|
||||
'https://www.amazon.pl/ap/*',
|
||||
'https://www.amazon.sa/ap/*',
|
||||
'https://www.amazon.se/ap/*',
|
||||
'https://www.amazon.sg/ap/*',
|
||||
'https://login.microsoftonline.*/*',
|
||||
'https://www.amazon.*/ap/*',
|
||||
'https://signin.aws.amazon.com/*',
|
||||
'https://www.upwork.com/ab/*',
|
||||
'https://home.personalcapital.com/*',
|
||||
|
|
@ -41,25 +21,8 @@ const PREDEFINED_SITELIST = [
|
|||
'https://secure.soundcloud.com/*',
|
||||
'https://icloud.com/*',
|
||||
'https://signin.benl.ebay.be/*',
|
||||
'https://signin.ebay.de/*',
|
||||
'https://signin.ebay.com/*',
|
||||
'https://signin.ebay.com.au/*',
|
||||
'https://signin.ebay.com.cn/*',
|
||||
'https://signin.ebay.com.hk/*',
|
||||
'https://signin.ebay.com.my/*',
|
||||
'https://signin.ebay.com.sg/*',
|
||||
'https://signin.ebay.it/*',
|
||||
'https://signin.ebay.co.uk/*',
|
||||
'https://signin.ebay.ca/*',
|
||||
'https://signin.ebay.at/*',
|
||||
'https://signin.ebay.be/*',
|
||||
'https://signin.ebay.fr/*',
|
||||
'https://signin.ebay.ie/*',
|
||||
'https://signin.ebay.nl/*',
|
||||
'https://signin.ebay.es/*',
|
||||
'https://signin.ebay.ch/*',
|
||||
'https://signin.ebay.in/*',
|
||||
'https://signin.ebay.ph/*',
|
||||
'https://signin.ebay.*/*',
|
||||
'https://www.ebay.*/signin/*',
|
||||
'https://login.yahoo.com/*',
|
||||
'https://id.atlassian.com/*',
|
||||
'https://www.fidelity.com/*',
|
||||
|
|
|
|||
|
|
@ -9,14 +9,15 @@ function kpxcAssert(func, expected, card, testName) {
|
|||
createResult(card, false, `Test failed: ${testName}. Result is: ${func}`);
|
||||
}
|
||||
|
||||
function assertRegex(func, expected, card, testName) {
|
||||
if ((func === null && expected === false)
|
||||
|| (func && (func.length > 0) === expected)) {
|
||||
function assertRegex(res, expected, card, testName) {
|
||||
if ((res === null && expected === false)
|
||||
|| (res && (res.length > 0) === expected)
|
||||
|| (res === expected)) {
|
||||
createResult(card, true, `Test passed: ${testName}`);
|
||||
return;
|
||||
}
|
||||
|
||||
createResult(card, false, `Test failed: ${testName}. Result is: ${func}`);
|
||||
createResult(card, false, `Test failed: ${testName}. Result is: ${res}`);
|
||||
}
|
||||
|
||||
async function assertInputFields(localDiv, expectedFieldCount, actionElementId) {
|
||||
|
|
|
|||
|
|
@ -16,14 +16,13 @@
|
|||
<script defer src="../common/sites.js"></script>
|
||||
<script defer src="../content/ui.js"></script>
|
||||
<script defer src="../content/pwgen.js"></script>
|
||||
<script defer src="../content/define.js"></script>
|
||||
<script defer src="../content/autocomplete.js"></script>
|
||||
<script defer src="../content/banner.js"></script>
|
||||
<script defer src="../content/credential-autocomplete.js"></script>
|
||||
<script defer src="../content/fields.js"></script>
|
||||
<script defer src="../content/form.js"></script>
|
||||
<script defer src="../content/fill.js"></script>
|
||||
<script defer src="../content/keepassxc-browser.js"></script>-->
|
||||
<script defer src="../content/keepassxc-browser.js"></script>
|
||||
<script defer src="../content/observer-helper.js"></script>
|
||||
<script defer src="../content/totp-autocomplete.js"></script>
|
||||
<script defer src="../content/totp-field.js"></script>
|
||||
|
|
@ -131,7 +130,7 @@
|
|||
<input placeholder="outsideLeft" type="password" name="outsideLeft">
|
||||
</div>
|
||||
|
||||
<div style="position: absolute; margin-top: -1500px;">
|
||||
<div style="position: absolute; top: -500px;">
|
||||
<input placeholder="outsideTop" type="password" name="outsideTop">
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -29,15 +29,43 @@ async function testGeneral() {
|
|||
// Consider using slighly different URL's for the tests cases.
|
||||
const matches = [
|
||||
[ 'https://example.com/*', 'https://example.com/login_page', true ],
|
||||
[ 'https://*.lexample.com/*', 'https://example.com/login_page', false ],
|
||||
[ 'https://example.com/*', 'https://example2.com/login_page', false ],
|
||||
[ 'https://example.com/*', 'https://subdomain.example.com/login_page', false ],
|
||||
[ 'https://example.com', 'https://subdomain.example.com/login_page', false ],
|
||||
[ 'https://*.example.com/*', 'https://example.com/login_page', true ],
|
||||
[ 'https://*.example.com/*', 'https://test.example.com/login_page', true ],
|
||||
[ 'https://test.example.com/*', 'https://subdomain.example.com/login_page', false ],
|
||||
[ 'https://test.example.com/page/*', 'https://test.example.com/page/login_page', true ],
|
||||
[ 'https://test.example.com/page/*', 'https://test.example.com/page/login_page?dontcare=aboutme', true ],
|
||||
[ 'https://test.example.com/page/another_page/*', 'https://test.example.com/page/login', false ],
|
||||
[ 'https://test.example.com/path/another/a/', 'https://test.example.com/path/another/a/', true ],
|
||||
[ 'https://test.example.com/path/another/a/', 'https://test.example.com/path/another/b/', false ],
|
||||
[ 'https://test.example.com/*/another/a/', 'https://test.example.com/path/another/a/', true ],
|
||||
[ 'https://test.example.com/path/*/a/', 'https://test.example.com/path/another/a/', true ],
|
||||
[ 'https://test.example.com/path2/*/a/', 'https://test.example.com/path/another/a/', false ],
|
||||
[ 'https://example.com:8448/', 'https://example.com/', false ],
|
||||
[ 'https://example.com:8448/', 'https://example.com:8448/', true ],
|
||||
[ 'https://example.com:8448/login/page', 'https://example.com/login/page', false ],
|
||||
[ 'https://example.com:8448/*', 'https://example.com:8448/login/page', true ],
|
||||
[ 'https://example.com/$/*', 'https://example.com/$/login_page', true ], // Special character in URL
|
||||
[ 'https://example.com/*/*', 'https://example.com/$/login_page', true ],
|
||||
[ 'https://example.com/*/*', 'https://example.com/login_page', false ],
|
||||
[ 'https://*.com/*', 'https://example.com/$/login_page', true ],
|
||||
[ 'https://*.com/*', 'https://example.org/$/login_page', false ],
|
||||
[ 'https://*.*/*', 'https://example.org/$/login_page', false ],
|
||||
// IP based URL's
|
||||
[ 'https://127.128.129.130:8448/', 'https://127.128.129.130:8448/', true ],
|
||||
[ 'https://127.128.129.*:8448/', 'https://127.128.129.130:8448/', true ],
|
||||
[ 'https://127.128.*/', 'https://127.128.129.130/', true ],
|
||||
[ 'https://127.128.*/', 'https://127.1.129.130/', false ],
|
||||
[ 'https://127.128.129.130/', 'https://127.128.129.130:8448/', false ],
|
||||
[ 'https://127.128.129.*/', 'https://127.128.129.130:8448/', false ],
|
||||
// Invalid URL's
|
||||
[ '', 'https://example.com', false ],
|
||||
[ 'abcdefgetc', 'https://example.com', false ],
|
||||
[ '{TOTP}\\no', 'https://example.com', false ],
|
||||
[ 'https://320.320.320.320', 'https://example.com', false ]
|
||||
];
|
||||
|
||||
for (const m of matches) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue