Merge pull request #176 from keepassxreboot/ignored_sites_improvements

Improvements to Ignored Sites
This commit is contained in:
Janek Bevendorff 2018-06-08 09:53:31 +02:00 committed by GitHub
commit ab240bc4a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 211 additions and 51 deletions

View file

@ -206,8 +206,8 @@ browserAction.setRememberPopup = function(tabId, username, password, url, userna
const settings = item.settings;
// Don't show anything if the site is in the ignore list
for (const site in settings.ignoredSites) {
if (site === url) {
for (const site of settings.ignoredSites) {
if (siteMatch(site.url, url)) {
return;
}
}

View file

@ -15,3 +15,74 @@ var showNotification = function(message) {
'message': message
});
};
/**
* 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
*/
var matchPatternToRegExp = function(pattern) {
if (pattern === '') {
return (/^(?:http|https|file|ftp|app):\/\//);
}
const schemeSegment = '(\\*|http|https|ws|wss|file|ftp)';
const hostSegment = '(\\*|(?:\\*\\.)?(?:[^/*]+))?';
const pathSegment = '(.*)';
const matchPatternRegExp = new RegExp(
`^${schemeSegment}://${hostSegment}/${pathSegment}$`
);
let match = matchPatternRegExp.exec(pattern);
if (!match) {
throw new TypeError('"${pattern}" is not a valid MatchPattern');
}
let [, scheme, host, path] = match;
if (!host) {
throw new TypeError('"${pattern}" does not have a valid host');
}
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) {
if (path === '*') {
regex += '(/.*)?';
} else if (path.charAt(0) !== '/') {
regex += '/';
regex += path.replace(/\./g, '\\.').replace(/\*/g, '.*?');
regex += '/?';
}
}
regex += '$';
return new RegExp(regex);
};
var siteMatch = function(site, url) {
const rx = matchPatternToRegExp(site);
return url.match(rx);
};

View file

@ -1315,6 +1315,16 @@ cip.initCredentialFields = function(forceCall) {
browser.runtime.sendMessage({ 'action': 'page_clear_logins', args: [_called.clearLogins] }).then(() => {
_called.clearLogins = true;
// Ignore sites with full ignore
if (cip.settings.ignoredSites) {
for (const site of cip.settings.ignoredSites) {
if (site.fullIgnore && siteMatch(site.url, document.location.href)) {
return;
}
}
}
const inputs = cipFields.getAllFields();
if (inputs.length === 0) {
return;
@ -1932,14 +1942,20 @@ cip.ignoreSite = function(sites) {
return;
}
const site = sites[0];
if (!cip.settings['ignoredSites']) {
cip.settings['ignoredSites'] = {};
// Delete previously created Object if it exists. It will be replaced by an Array
if (cip.settings['ignoredSites'] !== null && cip.settings['ignoredSites'].constructor === Object) {
delete cip.settings['ignoredSites'];
}
cip.settings['ignoredSites'][site] = {
url: site
};
const site = sites[0];
if (!cip.settings['ignoredSites']) {
cip.settings['ignoredSites'] = [];
}
cip.settings['ignoredSites'].push({
url: site,
fullIgnore: false
});
browser.runtime.sendMessage({
action: 'save_settings',

View file

@ -3,6 +3,10 @@ body {
padding-bottom: 60px;
}
table td {
width: 100%;
}
/* Custom container */
.container {
margin: 0 auto;
@ -111,6 +115,10 @@ h2+hr {
margin-right: 5px;
}
#ignoreUrl {
width: 75%;
}
tr.clone {
display: none;
}

View file

@ -297,21 +297,36 @@
Sites in this list are ignored when new credentials are detected.
<br />
Go to the page with new credentials, click the blinking KeePassXC-Browser icon or the notification and select <em>Never ask for this page</em>.
<br />
If full ignore is enabled, no input fields are detected and no credentials are received for that site.
</p>
<hr />
<div class="form-group">
<label for="ignoreManualAdd">Add URL manually:</label>
<div class="control-group">
<div class="input-append">
<input type="url" id="ignoreUrl"/>
<button class="btn btn-sm btn-primary" id="ignoreManualAddButton" type="button"><span class="glyphicon glyphicon-plus-sign"></span> Add</button>
</div>
</div>
</div>
<hr />
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Page URL</th>
<th>Delete</th>
<th>Full ignore</th>
</tr>
</thead>
<tbody>
<tr class="empty">
<td colspan="2">No ignored sites found.</td>
<td colspan="3">No ignored sites found.</td>
</tr>
<tr class="clone">
<td></td>
<td><button class="btn delete btn-danger btn"><span class="glyphicon glyphicon-remove-sign"></span> Remove</button></td>
<td><input type="checkbox" name="fullIgnore" value="false" /></td>
</tr>
</tbody>
</table>

View file

@ -52,9 +52,9 @@ options.saveSettingsPromise = function() {
}
options.saveSetting = function(name) {
const $id = '#' + name;
$($id).closest('.control-group').removeClass('error').addClass('success');
setTimeout(() => { $($id).closest('.control-group').removeClass('success'); }, 2500);
const id = '#' + name;
$(id).closest('.control-group').removeClass('error').addClass('success');
setTimeout(() => { $(id).closest('.control-group').removeClass('success'); }, 2500);
browser.storage.local.set({'settings': options.settings});
browser.runtime.sendMessage({
@ -168,10 +168,10 @@ options.initConnectedDatabases = function() {
$('#dialogDeleteConnectedDatabase .modal-footer:first button.yes:first').click(function(e) {
$('#dialogDeleteConnectedDatabase').modal('hide');
const $hash = $('#dialogDeleteConnectedDatabase').data('hash');
$('#tab-connected-databases #tr-cd-' + $hash).remove();
const hash = $('#dialogDeleteConnectedDatabase').data('hash');
$('#tab-connected-databases #tr-cd-' + hash).remove();
delete options.keyRing[$hash];
delete options.keyRing[hash];
options.saveKeyRing();
if ($('#tab-connected-databases table tbody:first tr').length > 2) {
@ -183,22 +183,22 @@ options.initConnectedDatabases = function() {
$('#tab-connected-databases tr.clone:first .dropdown-menu:first').width('230px');
const $trClone = $('#tab-connected-databases table tr.clone:first').clone(true);
$trClone.removeClass('clone');
const trClone = $('#tab-connected-databases table tr.clone:first').clone(true);
trClone.removeClass('clone');
for (let hash in options.keyRing) {
const $tr = $trClone.clone(true);
$tr.data('hash', hash);
$tr.attr('id', 'tr-cd-' + hash);
const tr = trClone.clone(true);
tr.data('hash', hash);
tr.attr('id', 'tr-cd-' + hash);
$('a.dropdown-toggle:first img:first', $tr).attr('src', '/icons/19x19/icon_normal_19x19.png');
$('a.dropdown-toggle:first img:first', tr).attr('src', '/icons/19x19/icon_normal_19x19.png');
$tr.children('td:first').text(options.keyRing[hash].id);
$tr.children('td:eq(1)').text(options.keyRing[hash].key);
tr.children('td:first').text(options.keyRing[hash].id);
tr.children('td:eq(1)').text(options.keyRing[hash].key);
const lastUsed = (options.keyRing[hash].lastUsed) ? new Date(options.keyRing[hash].lastUsed).toLocaleString() : 'unknown';
$tr.children('td:eq(2)').text(lastUsed);
tr.children('td:eq(2)').text(lastUsed);
const date = (options.keyRing[hash].created) ? new Date(options.keyRing[hash].created).toLocaleDateString() : 'unknown';
$tr.children('td:eq(3)').text(date);
$('#tab-connected-databases table tbody:first').append($tr);
tr.children('td:eq(3)').text(date);
$('#tab-connected-databases table tbody:first').append(tr);
}
if ($('#tab-connected-databases table tbody:first tr').length > 2) {
@ -227,11 +227,11 @@ options.initSpecifiedCredentialFields = function() {
$('#dialogDeleteSpecifiedCredentialFields .modal-footer:first button.yes:first').click(function(e) {
$('#dialogDeleteSpecifiedCredentialFields').modal('hide');
const $url = $('#dialogDeleteSpecifiedCredentialFields').data('url');
const $trId = $('#dialogDeleteSpecifiedCredentialFields').data('tr-id');
$('#tab-specified-fields #' + $trId).remove();
const url = $('#dialogDeleteSpecifiedCredentialFields').data('url');
const trId = $('#dialogDeleteSpecifiedCredentialFields').data('tr-id');
$('#tab-specified-fields #' + trId).remove();
delete options.settings['defined-credential-fields'][$url];
delete options.settings['defined-credential-fields'][url];
options.saveSettings();
if ($('#tab-specified-fields table tbody:first tr').length > 2) {
@ -241,17 +241,17 @@ options.initSpecifiedCredentialFields = function() {
}
});
const $trClone = $('#tab-specified-fields table tr.clone:first').clone(true);
$trClone.removeClass('clone');
const trClone = $('#tab-specified-fields table tr.clone:first').clone(true);
trClone.removeClass('clone');
let counter = 1;
for (let url in options.settings['defined-credential-fields']) {
const $tr = $trClone.clone(true);
$tr.data('url', url);
$tr.attr('id', 'tr-scf' + counter);
const tr = trClone.clone(true);
tr.data('url', url);
tr.attr('id', 'tr-scf' + counter);
++counter;
$tr.children('td:first').text(url);
$('#tab-specified-fields table tbody:first').append($tr);
tr.children('td:first').text(url);
$('#tab-specified-fields table tbody:first').append(tr);
}
if ($('#tab-specified-fields table tbody:first tr').length > 2) {
@ -271,14 +271,61 @@ options.initIgnoredSites = function() {
$('#dialogDeleteIgnoredSite').modal('show');
});
$('#tab-ignored-sites tr.clone:first input[type=checkbox]:first').change(function() {
const url = $(this).closest('tr').data('url');
for (let site of options.settings['ignoredSites']) {
if (site.url === url) {
site.fullIgnore = $(this).is(':checked');
}
}
options.saveSettings();
});
$("#ignoreUrl").keyup(function(event) {
if (event.keyCode === 13) {
$("#ignoreManualAddButton").click();
}
});
$('#ignoreManualAddButton').click(function(e) {
e.preventDefault();
const value = $('#ignoreUrl').val();
if (value.length > 10 && value.length <= 2000) {
if (options.settings['ignoredSites'] === undefined) {
options.settings['ignoredSites'] = [];
}
const newValue = options.settings['ignoredSites'].length + 1;
const trClone = $('#tab-ignored-sites table tr.clone:first').clone(true);
trClone.removeClass('clone');
const tr = trClone.clone(true);
tr.data('url', value);
tr.attr('id', 'tr-scf' + newValue);
tr.children('td:first').text(value);
tr.children('td:nth-child(3)').children('input[type=checkbox]').attr('checked', false);
$('#tab-ignored-sites table tbody:first').append(tr);
$('#tab-ignored-sites table tbody:first tr.empty:first').hide();
options.settings['ignoredSites'].push({url: value, fullIgnore: false});
options.saveSettings();
$('#ignoreUrl').val('');
}
});
$('#dialogDeleteIgnoredSite .modal-footer:first button.yes:first').click(function(e) {
$('#dialogDeleteIgnoredSite').modal('hide');
const $url = $('#dialogDeleteIgnoredSite').data('url');
const $trId = $('#dialogDeleteIgnoredSite').data('tr-id');
$('#tab-ignored-sites #' + $trId).remove();
const url = $('#dialogDeleteIgnoredSite').data('url');
const trId = $('#dialogDeleteIgnoredSite').data('tr-id');
$('#tab-ignored-sites #' + trId).remove();
delete options.settings['ignoredSites'][$url];
for (let i = 0; i < options.settings['ignoredSites'].length; ++i) {
if (options.settings['ignoredSites'][i].url === url) {
options.settings['ignoredSites'].splice(i, 1);
}
}
options.saveSettings();
if ($('#tab-ignored-sites table tbody:first tr').length > 2) {
@ -288,19 +335,22 @@ options.initIgnoredSites = function() {
}
});
const $trClone = $('#tab-ignored-sites table tr.clone:first').clone(true);
$trClone.removeClass('clone');
const trClone = $('#tab-ignored-sites table tr.clone:first').clone(true);
trClone.removeClass('clone');
let counter = 1;
for (let url in options.settings['ignoredSites']) {
const $tr = $trClone.clone(true);
$tr.data('url', url);
$tr.attr('id', 'tr-scf' + counter);
++counter;
if (options.settings['ignoredSites']){
for (let site of options.settings['ignoredSites']) {
const tr = trClone.clone(true);
tr.data('url', site.url);
tr.attr('id', 'tr-scf' + counter);
++counter;
$tr.children('td:first').text(url);
$('#tab-ignored-sites table tbody:first').append($tr);
tr.children('td:first').text(site.url);
tr.children('td:nth-child(3)').children('input[type=checkbox]').attr('checked', site.fullIgnore);
$('#tab-ignored-sites table tbody:first').append(tr);
}
}
if ($('#tab-ignored-sites table tbody:first tr').length > 2) {
$('#tab-ignored-sites table tbody:first tr.empty:first').hide();
} else {