mirror of https://github.com/gorhill/uBlock.git
this fixes #1100: ability to inject directly a resource from redirection library
This commit is contained in:
parent
520e251112
commit
1fe5a16c32
|
@ -1,5 +1,5 @@
|
||||||
4d0e777a82576a2ec771742abb91925b assets/ublock/unbreak.txt
|
4d0e777a82576a2ec771742abb91925b assets/ublock/unbreak.txt
|
||||||
f2624cc77fae3f1be5a6b5d5b8027bdc assets/ublock/redirect-resources.txt
|
62111a29f0a5cb361ba8dbae92054adb assets/ublock/redirect-resources.txt
|
||||||
6c077d6d5b39e8a5a407966ad62c9c32 assets/ublock/privacy.txt
|
6c077d6d5b39e8a5a407966ad62c9c32 assets/ublock/privacy.txt
|
||||||
9bcc718383fec8b2ce0f9c379f45da9a assets/ublock/filters.txt
|
9bcc718383fec8b2ce0f9c379f45da9a assets/ublock/filters.txt
|
||||||
146704ad1c0393e342afdb416762c183 assets/ublock/badware.txt
|
146704ad1c0393e342afdb416762c183 assets/ublock/badware.txt
|
||||||
|
|
|
@ -228,3 +228,10 @@ yavli-defuser.js application/javascript
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
# Addefend defuser
|
||||||
|
uabinject-defuser.js application/javascript
|
||||||
|
(function() {
|
||||||
|
window.uabpdl = window.uabInject = window.uabDetect = true;
|
||||||
|
})();
|
||||||
|
|
|
@ -90,8 +90,8 @@ return {
|
||||||
|
|
||||||
// read-only
|
// read-only
|
||||||
systemSettings: {
|
systemSettings: {
|
||||||
compiledMagic: 'cxubjrcfrnrq',
|
compiledMagic: 'xtsldiywhvgc',
|
||||||
selfieMagic: 'mnigwksyvgkv'
|
selfieMagic: 'xtsldiywhvgc'
|
||||||
},
|
},
|
||||||
|
|
||||||
restoreBackupSettings: {
|
restoreBackupSettings: {
|
||||||
|
|
|
@ -116,6 +116,8 @@ var cosmeticFilters = function(details) {
|
||||||
vAPI.hideCosmeticFilters = hideCosmeticFilters;
|
vAPI.hideCosmeticFilters = hideCosmeticFilters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
var netFilters = function(details) {
|
var netFilters = function(details) {
|
||||||
var parent = document.head || document.documentElement;
|
var parent = document.head || document.documentElement;
|
||||||
if ( !parent ) {
|
if ( !parent ) {
|
||||||
|
@ -131,6 +133,29 @@ var netFilters = function(details) {
|
||||||
//console.debug('document.querySelectorAll("%s") = %o', text, document.querySelectorAll(text));
|
//console.debug('document.querySelectorAll("%s") = %o', text, document.querySelectorAll(text));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// Create script tags and assign data URIs looked up from our library of
|
||||||
|
// redirection resources: Sometimes it is useful to use these resources as
|
||||||
|
// standalone scriptlets.
|
||||||
|
// Library of redirection resources:
|
||||||
|
// https://github.com/gorhill/uBlock/blob/master/assets/ublock/redirect-resources.txt
|
||||||
|
|
||||||
|
var injectScripts = function(dataURIs) {
|
||||||
|
var parent = document.head || document.documentElement;
|
||||||
|
if ( !parent ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var i = dataURIs.length, scriptTag;
|
||||||
|
while ( i-- ) {
|
||||||
|
scriptTag = document.createElement('script');
|
||||||
|
scriptTag.src = dataURIs[i];
|
||||||
|
parent.appendChild(scriptTag);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
var filteringHandler = function(details) {
|
var filteringHandler = function(details) {
|
||||||
var styleTagCount = vAPI.styles.length;
|
var styleTagCount = vAPI.styles.length;
|
||||||
|
|
||||||
|
@ -144,6 +169,9 @@ var filteringHandler = function(details) {
|
||||||
if ( details.netHide.length !== 0 ) {
|
if ( details.netHide.length !== 0 ) {
|
||||||
netFilters(details);
|
netFilters(details);
|
||||||
}
|
}
|
||||||
|
if ( details.scripts !== 0 ) {
|
||||||
|
injectScripts(details.scripts);
|
||||||
|
}
|
||||||
// The port will never be used again at this point, disconnecting allows
|
// The port will never be used again at this point, disconnecting allows
|
||||||
// the browser to flush this script from memory.
|
// the browser to flush this script from memory.
|
||||||
}
|
}
|
||||||
|
@ -164,6 +192,8 @@ var filteringHandler = function(details) {
|
||||||
localMessager.close();
|
localMessager.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
var hideElements = function(selectors) {
|
var hideElements = function(selectors) {
|
||||||
if ( document.body === null ) {
|
if ( document.body === null ) {
|
||||||
return;
|
return;
|
||||||
|
@ -213,6 +243,8 @@ var hideElements = function(selectors) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
var url = window.location.href;
|
var url = window.location.href;
|
||||||
localMessager.send(
|
localMessager.send(
|
||||||
{
|
{
|
||||||
|
|
|
@ -244,6 +244,7 @@ var FilterParser = function() {
|
||||||
this.hostnames = [];
|
this.hostnames = [];
|
||||||
this.invalid = false;
|
this.invalid = false;
|
||||||
this.cosmetic = true;
|
this.cosmetic = true;
|
||||||
|
this.reScriptTagFilter = /^script:(contains|inject)\((.+?)\)$/;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -353,12 +354,10 @@ FilterParser.prototype.parse = function(raw) {
|
||||||
// Examples:
|
// Examples:
|
||||||
// focus.de##script:contains(/uabInject/)
|
// focus.de##script:contains(/uabInject/)
|
||||||
// focus.de##script:contains(uabInject)
|
// focus.de##script:contains(uabInject)
|
||||||
|
// focus.de##script:inject(uabinject-defuser.js)
|
||||||
|
|
||||||
// Inline script tag filter?
|
var matches = this.reScriptTagFilter.exec(this.suffix);
|
||||||
if (
|
if ( matches === null ) {
|
||||||
this.suffix.startsWith('script:contains(') === false ||
|
|
||||||
this.suffix.endsWith(')') === false
|
|
||||||
) {
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,19 +368,16 @@ FilterParser.prototype.parse = function(raw) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
var suffix = this.suffix.slice(16, -1);
|
var token = matches[2];
|
||||||
this.suffix = 'script//:';
|
|
||||||
|
|
||||||
// Plain string-based?
|
switch ( matches[1] ) {
|
||||||
if ( suffix.startsWith('/') === false || suffix.endsWith('/') === false ) {
|
case 'contains':
|
||||||
this.suffix += suffix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
this.suffix = 'script?';
|
||||||
return this;
|
// Plain string- or regex-based?
|
||||||
}
|
if ( token.startsWith('/') === false || token.endsWith('/') === false ) {
|
||||||
|
this.suffix += token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
// Regex-based
|
} else {
|
||||||
this.suffix += suffix.slice(1, -1);
|
this.suffix += token.slice(1, -1);
|
||||||
|
|
||||||
// Valid regex?
|
|
||||||
if ( isBadRegex(this.suffix) ) {
|
if ( isBadRegex(this.suffix) ) {
|
||||||
console.error(
|
console.error(
|
||||||
"uBlock Origin> discarding bad regular expression-based cosmetic filter '%s': '%s'",
|
"uBlock Origin> discarding bad regular expression-based cosmetic filter '%s': '%s'",
|
||||||
|
@ -389,7 +385,15 @@ FilterParser.prototype.parse = function(raw) {
|
||||||
isBadRegex.message
|
isBadRegex.message
|
||||||
);
|
);
|
||||||
this.invalid = true;
|
this.invalid = true;
|
||||||
return this;
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'inject':
|
||||||
|
this.suffix = 'script+' + token;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.invalid = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
@ -661,6 +665,8 @@ FilterContainer.prototype.reset = function() {
|
||||||
this.entityFilters = {};
|
this.entityFilters = {};
|
||||||
this.scriptTagFilters = {};
|
this.scriptTagFilters = {};
|
||||||
this.scriptTagFilterCount = 0;
|
this.scriptTagFilterCount = 0;
|
||||||
|
this.scriptTags = {};
|
||||||
|
this.scriptTagCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -686,9 +692,12 @@ FilterContainer.prototype.isValidSelector = (function() {
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
}
|
}
|
||||||
if ( s.startsWith('script//:') ) {
|
// We reach this point very rarely.
|
||||||
|
if ( s.startsWith('script') ) {
|
||||||
|
if ( s.startsWith('?', 6) || s.startsWith('+', 6) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
console.error('uBlock> invalid cosmetic filter:', s);
|
console.error('uBlock> invalid cosmetic filter:', s);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -914,8 +923,8 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
|
||||||
// h ir twitter.com .promoted-tweet
|
// h ir twitter.com .promoted-tweet
|
||||||
if ( fields[0] === 'h' ) {
|
if ( fields[0] === 'h' ) {
|
||||||
// Special filter: script tags. Not a real CSS selector.
|
// Special filter: script tags. Not a real CSS selector.
|
||||||
if ( fields[3].startsWith('script//:') ) {
|
if ( fields[3].startsWith('script') ) {
|
||||||
this.createScriptTagFilter(fields[2], fields[3].slice(9));
|
this.createScriptFilter(fields[2], fields[3].slice(6));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
filter = new FilterHostname(fields[3], fields[2]);
|
filter = new FilterHostname(fields[3], fields[2]);
|
||||||
|
@ -950,8 +959,8 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
|
||||||
// entity selector
|
// entity selector
|
||||||
if ( fields[0] === 'e' ) {
|
if ( fields[0] === 'e' ) {
|
||||||
// Special filter: script tags. Not a real CSS selector.
|
// Special filter: script tags. Not a real CSS selector.
|
||||||
if ( fields[2].startsWith('script//:') ) {
|
if ( fields[2].startsWith('script?') ) {
|
||||||
this.createScriptTagFilter(fields[1], fields[2].slice(9));
|
this.createScriptFilter(fields[1], fields[2].slice(6));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
bucket = this.entityFilters[fields[1]];
|
bucket = this.entityFilters[fields[1]];
|
||||||
|
@ -1019,6 +1028,17 @@ FilterContainer.prototype.skipCompiledContent = function(text, lineBeg) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
FilterContainer.prototype.createScriptFilter = function(hostname, s) {
|
||||||
|
if ( s.charAt(0) === '?' ) {
|
||||||
|
return this.createScriptTagFilter(hostname, s.slice(1));
|
||||||
|
}
|
||||||
|
if ( s.charAt(0) === '+' ) {
|
||||||
|
return this.createScriptTagInjector(hostname, s.slice(1));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.createScriptTagFilter = function(hostname, s) {
|
FilterContainer.prototype.createScriptTagFilter = function(hostname, s) {
|
||||||
if ( this.scriptTagFilters.hasOwnProperty(hostname) ) {
|
if ( this.scriptTagFilters.hasOwnProperty(hostname) ) {
|
||||||
this.scriptTagFilters[hostname] += '|' + s;
|
this.scriptTagFilters[hostname] += '|' + s;
|
||||||
|
@ -1062,6 +1082,61 @@ FilterContainer.prototype.retrieveScriptTagRegex = function(domain, hostname) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
FilterContainer.prototype.createScriptTagInjector = function(hostname, s) {
|
||||||
|
if ( this.scriptTags.hasOwnProperty(hostname) ) {
|
||||||
|
this.scriptTags[hostname].push(s);
|
||||||
|
} else {
|
||||||
|
this.scriptTags[hostname] = [s];
|
||||||
|
}
|
||||||
|
this.scriptTagCount += 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
FilterContainer.prototype.retrieveScriptTags = function(domain, hostname) {
|
||||||
|
if ( this.scriptTagCount === 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var reng = µb.redirectEngine;
|
||||||
|
if ( !reng ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var out = [],
|
||||||
|
hn = hostname, pos, rnames, i, dataURI;
|
||||||
|
for (;;) {
|
||||||
|
rnames = this.scriptTags[hn];
|
||||||
|
i = rnames && rnames.length || 0;
|
||||||
|
while ( i-- ) {
|
||||||
|
if ( (dataURI = reng.resourceFromName(rnames[i], 'application/javascript')) ) {
|
||||||
|
out.push(dataURI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( hn === domain ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos = hn.indexOf('.');
|
||||||
|
if ( pos === -1 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hn = hn.slice(pos + 1);
|
||||||
|
}
|
||||||
|
pos = domain.indexOf('.');
|
||||||
|
if ( pos !== -1 ) {
|
||||||
|
hn = domain.slice(0, pos);
|
||||||
|
rnames = this.scriptTags[hn];
|
||||||
|
i = rnames && rnames.length || 0;
|
||||||
|
while ( i-- ) {
|
||||||
|
if ( (dataURI = reng.resourceFromName(rnames[i], 'application/javascript')) ) {
|
||||||
|
out.push(dataURI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterContainer.prototype.freeze = function() {
|
FilterContainer.prototype.freeze = function() {
|
||||||
this.duplicateBuster = {};
|
this.duplicateBuster = {};
|
||||||
|
|
||||||
|
@ -1117,7 +1192,9 @@ FilterContainer.prototype.toSelfie = function() {
|
||||||
highHighGenericHideCount: this.highHighGenericHideCount,
|
highHighGenericHideCount: this.highHighGenericHideCount,
|
||||||
genericDonthide: this.genericDonthide,
|
genericDonthide: this.genericDonthide,
|
||||||
scriptTagFilters: this.scriptTagFilters,
|
scriptTagFilters: this.scriptTagFilters,
|
||||||
scriptTagFilterCount: this.scriptTagFilterCount
|
scriptTagFilterCount: this.scriptTagFilterCount,
|
||||||
|
scriptTags: this.scriptTags,
|
||||||
|
scriptTagCount: this.scriptTagCount
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1180,6 +1257,8 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
|
||||||
this.genericDonthide = selfie.genericDonthide;
|
this.genericDonthide = selfie.genericDonthide;
|
||||||
this.scriptTagFilters = selfie.scriptTagFilters;
|
this.scriptTagFilters = selfie.scriptTagFilters;
|
||||||
this.scriptTagFilterCount = selfie.scriptTagFilterCount;
|
this.scriptTagFilterCount = selfie.scriptTagFilterCount;
|
||||||
|
this.scriptTags = selfie.scriptTags;
|
||||||
|
this.scriptTagCount = selfie.scriptTagCount;
|
||||||
this.frozen = true;
|
this.frozen = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1361,7 +1440,8 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) {
|
||||||
cosmeticHide: [],
|
cosmeticHide: [],
|
||||||
cosmeticDonthide: [],
|
cosmeticDonthide: [],
|
||||||
netHide: [],
|
netHide: [],
|
||||||
netCollapse: µb.userSettings.collapseBlocked
|
netCollapse: µb.userSettings.collapseBlocked,
|
||||||
|
scripts: this.retrieveScriptTags(domain, hostname)
|
||||||
};
|
};
|
||||||
|
|
||||||
var hash, bucket;
|
var hash, bucket;
|
||||||
|
|
|
@ -359,6 +359,15 @@ RedirectEngine.prototype.fromSelfie = function(selfie) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
RedirectEngine.prototype.resourceFromName = function(name, mime) {
|
||||||
|
var entry = this.resources[name];
|
||||||
|
if ( entry && (mime === undefined || entry.mime.startsWith(mime)) ) {
|
||||||
|
return entry.toURL();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
// TODO: combine same key-redirect pairs into a single regex.
|
// TODO: combine same key-redirect pairs into a single regex.
|
||||||
|
|
||||||
RedirectEngine.prototype.resourcesFromString = function(text) {
|
RedirectEngine.prototype.resourcesFromString = function(text) {
|
||||||
|
|
Loading…
Reference in New Issue