Improve window.open-defuser scriptlet

The new syntax deprecate the old syntax, though the
old syntax will still be supported until it's no
longer used in mainstream filter lists.

The new syntax is:

    example.com##+js(window.open-defuser, pattern, seconds)

`pattern`:

A pattern to match for the defusing to take place.
Patterns which starts and ends with `/` will be
interpreted as regular expressions. To NOT match a
pattern, prefix with `!`.

`seconds`:

If not present, no window will be opened and the
scriptlet will return `null`.

If present and a valid integer value, the defuser
will return a valid window object even though no
popup window is opened. The returned window object
will cease to be valid after the specified number
of seconds.
This commit is contained in:
Raymond Hill 2020-03-08 16:15:58 -04:00
parent 1d9421b8b2
commit b27848a060
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
1 changed files with 52 additions and 10 deletions

View File

@ -21,23 +21,65 @@
(function() {
'use strict';
let result = parseInt('{{1}}', 10);
result = isNaN(result) === false && result === 0;
let needle = '{{2}}';
if ( needle === '' || needle === '{{2}}' ) {
needle = '.?';
} else if ( /^\/.+\/$/.test(needle) ) {
needle = needle.slice(1,-1);
} else {
needle = needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
let arg1 = '{{1}}';
if ( arg1 === '{{1}}' ) { arg1 = ''; }
let arg2 = '{{2}}';
if ( arg2 === '{{2}}' ) { arg2 = ''; }
let arg3 = '{{3}}';
if ( arg3 === '{{3}}' ) { arg3 = ''; }
const newSyntax = /^[01]?$/.test(arg1) === false;
let pattern = '';
let targetResult = true;
let autoRemoveAfter = -1;
if ( newSyntax ) {
pattern = arg1;
if ( pattern.startsWith('!') ) {
targetResult = false;
pattern = pattern.slice(1);
}
needle = new RegExp(needle);
autoRemoveAfter = parseInt(arg2);
if ( isNaN(autoRemoveAfter) ) {
autoRemoveAfter = -1;
}
} else {
pattern = arg2;
if ( arg1 === '0' ) {
targetResult = false;
}
}
if ( pattern === '' ) {
pattern = '.?';
} else if ( /^\/.+\/$/.test(pattern) ) {
pattern = pattern.slice(1,-1);
} else {
pattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
const rePattern = new RegExp(pattern);
window.open = new Proxy(window.open, {
apply: function(target, thisArg, args) {
const url = args[0];
if ( needle.test(url) === result ) {
if ( rePattern.test(url) !== targetResult ) {
return target.apply(thisArg, args);
}
if ( autoRemoveAfter < 0 ) { return null; }
const iframe = document.createElement('iframe');
iframe.src = url;
iframe.style.setProperty('display','none', 'important');
iframe.style.setProperty('height','1px', 'important');
iframe.style.setProperty('width','1px', 'important');
document.body.appendChild(iframe);
setTimeout(( ) => iframe.remove(), autoRemoveAfter * 1000);
if ( arg3 === '' ) { return iframe.contentWindow; }
return new Proxy(iframe.contentWindow, {
get: function(target, prop) {
console.log('get', prop, '===', target[prop]);
return target[prop];
},
set: function(target, prop, value) {
console.log('set', prop, '=', value);
target[prop] = value;
},
});
}
});
})();