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
|
||||
f2624cc77fae3f1be5a6b5d5b8027bdc assets/ublock/redirect-resources.txt
|
||||
62111a29f0a5cb361ba8dbae92054adb assets/ublock/redirect-resources.txt
|
||||
6c077d6d5b39e8a5a407966ad62c9c32 assets/ublock/privacy.txt
|
||||
9bcc718383fec8b2ce0f9c379f45da9a assets/ublock/filters.txt
|
||||
146704ad1c0393e342afdb416762c183 assets/ublock/badware.txt
|
||||
|
|
|
@ -228,3 +228,10 @@ yavli-defuser.js application/javascript
|
|||
} catch (ex) {
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
# Addefend defuser
|
||||
uabinject-defuser.js application/javascript
|
||||
(function() {
|
||||
window.uabpdl = window.uabInject = window.uabDetect = true;
|
||||
})();
|
||||
|
|
|
@ -90,8 +90,8 @@ return {
|
|||
|
||||
// read-only
|
||||
systemSettings: {
|
||||
compiledMagic: 'cxubjrcfrnrq',
|
||||
selfieMagic: 'mnigwksyvgkv'
|
||||
compiledMagic: 'xtsldiywhvgc',
|
||||
selfieMagic: 'xtsldiywhvgc'
|
||||
},
|
||||
|
||||
restoreBackupSettings: {
|
||||
|
|
|
@ -116,6 +116,8 @@ var cosmeticFilters = function(details) {
|
|||
vAPI.hideCosmeticFilters = hideCosmeticFilters;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var netFilters = function(details) {
|
||||
var parent = document.head || document.documentElement;
|
||||
if ( !parent ) {
|
||||
|
@ -131,6 +133,29 @@ var netFilters = function(details) {
|
|||
//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 styleTagCount = vAPI.styles.length;
|
||||
|
||||
|
@ -144,6 +169,9 @@ var filteringHandler = function(details) {
|
|||
if ( details.netHide.length !== 0 ) {
|
||||
netFilters(details);
|
||||
}
|
||||
if ( details.scripts !== 0 ) {
|
||||
injectScripts(details.scripts);
|
||||
}
|
||||
// The port will never be used again at this point, disconnecting allows
|
||||
// the browser to flush this script from memory.
|
||||
}
|
||||
|
@ -164,6 +192,8 @@ var filteringHandler = function(details) {
|
|||
localMessager.close();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var hideElements = function(selectors) {
|
||||
if ( document.body === null ) {
|
||||
return;
|
||||
|
@ -213,6 +243,8 @@ var hideElements = function(selectors) {
|
|||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var url = window.location.href;
|
||||
localMessager.send(
|
||||
{
|
||||
|
|
|
@ -244,6 +244,7 @@ var FilterParser = function() {
|
|||
this.hostnames = [];
|
||||
this.invalid = false;
|
||||
this.cosmetic = true;
|
||||
this.reScriptTagFilter = /^script:(contains|inject)\((.+?)\)$/;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -353,12 +354,10 @@ FilterParser.prototype.parse = function(raw) {
|
|||
// Examples:
|
||||
// focus.de##script:contains(/uabInject/)
|
||||
// focus.de##script:contains(uabInject)
|
||||
// focus.de##script:inject(uabinject-defuser.js)
|
||||
|
||||
// Inline script tag filter?
|
||||
if (
|
||||
this.suffix.startsWith('script:contains(') === false ||
|
||||
this.suffix.endsWith(')') === false
|
||||
) {
|
||||
var matches = this.reScriptTagFilter.exec(this.suffix);
|
||||
if ( matches === null ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -369,19 +368,16 @@ FilterParser.prototype.parse = function(raw) {
|
|||
return this;
|
||||
}
|
||||
|
||||
var suffix = this.suffix.slice(16, -1);
|
||||
this.suffix = 'script//:';
|
||||
var token = matches[2];
|
||||
|
||||
// Plain string-based?
|
||||
if ( suffix.startsWith('/') === false || suffix.endsWith('/') === false ) {
|
||||
this.suffix += suffix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
return this;
|
||||
}
|
||||
|
||||
// Regex-based
|
||||
this.suffix += suffix.slice(1, -1);
|
||||
|
||||
// Valid regex?
|
||||
switch ( matches[1] ) {
|
||||
case 'contains':
|
||||
this.suffix = 'script?';
|
||||
// Plain string- or regex-based?
|
||||
if ( token.startsWith('/') === false || token.endsWith('/') === false ) {
|
||||
this.suffix += token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
} else {
|
||||
this.suffix += token.slice(1, -1);
|
||||
if ( isBadRegex(this.suffix) ) {
|
||||
console.error(
|
||||
"uBlock Origin> discarding bad regular expression-based cosmetic filter '%s': '%s'",
|
||||
|
@ -389,7 +385,15 @@ FilterParser.prototype.parse = function(raw) {
|
|||
isBadRegex.message
|
||||
);
|
||||
this.invalid = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'inject':
|
||||
this.suffix = 'script+' + token;
|
||||
break;
|
||||
default:
|
||||
this.invalid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -661,6 +665,8 @@ FilterContainer.prototype.reset = function() {
|
|||
this.entityFilters = {};
|
||||
this.scriptTagFilters = {};
|
||||
this.scriptTagFilterCount = 0;
|
||||
this.scriptTags = {};
|
||||
this.scriptTagCount = 0;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -686,9 +692,12 @@ FilterContainer.prototype.isValidSelector = (function() {
|
|||
return true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
console.error('uBlock> invalid cosmetic filter:', s);
|
||||
return false;
|
||||
};
|
||||
|
@ -914,8 +923,8 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
|
|||
// h ir twitter.com .promoted-tweet
|
||||
if ( fields[0] === 'h' ) {
|
||||
// Special filter: script tags. Not a real CSS selector.
|
||||
if ( fields[3].startsWith('script//:') ) {
|
||||
this.createScriptTagFilter(fields[2], fields[3].slice(9));
|
||||
if ( fields[3].startsWith('script') ) {
|
||||
this.createScriptFilter(fields[2], fields[3].slice(6));
|
||||
continue;
|
||||
}
|
||||
filter = new FilterHostname(fields[3], fields[2]);
|
||||
|
@ -950,8 +959,8 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) {
|
|||
// entity selector
|
||||
if ( fields[0] === 'e' ) {
|
||||
// Special filter: script tags. Not a real CSS selector.
|
||||
if ( fields[2].startsWith('script//:') ) {
|
||||
this.createScriptTagFilter(fields[1], fields[2].slice(9));
|
||||
if ( fields[2].startsWith('script?') ) {
|
||||
this.createScriptFilter(fields[1], fields[2].slice(6));
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
if ( this.scriptTagFilters.hasOwnProperty(hostname) ) {
|
||||
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() {
|
||||
this.duplicateBuster = {};
|
||||
|
||||
|
@ -1117,7 +1192,9 @@ FilterContainer.prototype.toSelfie = function() {
|
|||
highHighGenericHideCount: this.highHighGenericHideCount,
|
||||
genericDonthide: this.genericDonthide,
|
||||
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.scriptTagFilters = selfie.scriptTagFilters;
|
||||
this.scriptTagFilterCount = selfie.scriptTagFilterCount;
|
||||
this.scriptTags = selfie.scriptTags;
|
||||
this.scriptTagCount = selfie.scriptTagCount;
|
||||
this.frozen = true;
|
||||
};
|
||||
|
||||
|
@ -1361,7 +1440,8 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) {
|
|||
cosmeticHide: [],
|
||||
cosmeticDonthide: [],
|
||||
netHide: [],
|
||||
netCollapse: µb.userSettings.collapseBlocked
|
||||
netCollapse: µb.userSettings.collapseBlocked,
|
||||
scripts: this.retrieveScriptTags(domain, hostname)
|
||||
};
|
||||
|
||||
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.
|
||||
|
||||
RedirectEngine.prototype.resourcesFromString = function(text) {
|
||||
|
|
Loading…
Reference in New Issue