This commit is contained in:
gorhill 2015-01-23 11:32:49 -05:00
parent a2ff66e20f
commit 673b8774be
9 changed files with 386 additions and 213 deletions

View file

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "µBlock",
"version": "0.8.5.7",
"version": "0.8.6.0",
"default_locale": "en",
"description": "__MSG_extShortDesc__",

View file

@ -45,7 +45,7 @@ vAPI.firefox = true;
// TODO: read these data from somewhere...
vAPI.app = {
name: 'µBlock',
version: '0.8.5.7'
version: '0.8.6.0'
};
/******************************************************************************/

View file

@ -61,27 +61,31 @@ body[dir="rtl"] #content {
vertical-align: top;
}
#content table tr td:nth-of-type(1) {
padding: 3px 0;
text-align: center;
}
#content table tr td:nth-of-type(2) {
white-space: normal;
width: 25%;
word-break: break-all;
word-wrap: break-word;
}
#content table tr td:nth-of-type(2) {
#content table tr td:nth-of-type(3) {
white-space: nowrap;
}
#content table tr td:nth-of-type(3) {
#content table tr td:nth-of-type(4) {
border-right: none;
white-space: normal;
width: 60%;
word-break: break-all;
word-wrap: break-word;
}
#content table tr td:nth-of-type(3) b {
#content table tr td:nth-of-type(4) b {
font-weight: normal;
}
#content table tr.blocked td:nth-of-type(3) b {
#content table tr.blocked td:nth-of-type(4) b {
background-color: rgba(192, 0, 0, 0.2);
}
#content table tr.allowed td:nth-of-type(3) b {
#content table tr.allowed td:nth-of-type(4) b {
background-color: rgba(0, 160, 0, 0.2);
}

View file

@ -107,7 +107,7 @@ return {
firstUpdateAfter: 5 * oneMinute,
nextUpdateAfter: 7 * oneHour,
selfieMagic: 'qidcglrwobsm',
selfieMagic: 'knreayqtuguf',
selfieAfter: 7 * oneMinute,
pageStores: {},

View file

@ -33,20 +33,29 @@
// https://github.com/gorhill/uBlock/issues/464
if ( document instanceof HTMLDocument === false ) {
//console.debug('contentscript-end.js > not a HTLMDocument');
return false;
}
if ( !vAPI ) {
//console.debug('contentscript-end.js > vAPI not found');
return;
}
if ( vAPI.canExecuteContentScript() !== true ) {
//console.debug('contentscript-end.js > can\'t execute');
return;
}
// Pointless to execute without the start script having done its job.
if ( !vAPI.contentscriptStartInjected ) {
return;
}
// https://github.com/gorhill/uBlock/issues/456
// Already injected?
if ( vAPI.contentscriptEndInjected ) {
//console.debug('contentscript-end.js > content script already injected');
return;
}
vAPI.contentscriptEndInjected = true;

View file

@ -36,22 +36,26 @@
// https://github.com/gorhill/uBlock/issues/464
if ( document instanceof HTMLDocument === false ) {
//console.debug('contentscript-start.js > not a HTLMDocument');
return false;
}
// Because in case
if ( !vAPI ) {
//console.debug('contentscript-start.js > vAPI not found');
return;
}
// Because Safari
if ( vAPI.canExecuteContentScript() !== true ) {
//console.debug('contentscript-start.js > can\'t execute');
return;
}
// https://github.com/gorhill/uBlock/issues/456
// Already injected?
if ( vAPI.contentscriptStartInjected ) {
//console.debug('contentscript-start.js > content script already injected');
return;
}
vAPI.contentscriptStartInjected = true;
@ -139,7 +143,13 @@ var filteringHandler = function(details) {
// The port will never be used again at this point, disconnecting allows
// the browser to flush this script from memory.
}
// Do not close the port before we are done.
// If no filters were found, maybe the script was injected before uBlock's
// process was fully initialized. When this happens, pages won't be
// cleaned right after browser launch.
vAPI.contentscriptStartInjected = !details || details.cosmeticHide.length !== 0;
// Cleanup before leaving
localMessager.close();
};

View file

@ -51,6 +51,8 @@ var renderURL = function(url, filter) {
}
if ( reText === '*' ) {
reText = '\\*';
} else if ( reText.charAt(0) === '/' && reText.slice(-1) === '/' ) {
reText = reText.slice(1, -1);
} else {
reText = reText
.replace(/\./g, '\\.')
@ -87,6 +89,7 @@ var createRow = function() {
tr.appendChild(doc.createElement('td'));
tr.appendChild(doc.createElement('td'));
tr.appendChild(doc.createElement('td'));
tr.appendChild(doc.createElement('td'));
return tr;
};
@ -96,18 +99,26 @@ var renderLogEntry = function(entry) {
var tr = createRow();
if ( entry.result.charAt(1) === 'b' ) {
tr.classList.add('blocked');
tr.cells[0].textContent = '\u2009\u2212\u2009';
} else if ( entry.result.charAt(1) === 'a' ) {
tr.classList.add('allowed');
if ( entry.result.charAt(0) === 'm' ) {
tr.classList.add('mirrored');
}
tr.cells[0].textContent = '\u2009+\u2009';
} else {
tr.cells[0].textContent = '\u2009\u00A0\u2009';
}
if ( entry.type === 'main_frame' ) {
tr.classList.add('maindoc');
}
tr.cells[0].textContent = entry.result.slice(3);
tr.cells[1].textContent = entry.type;
vAPI.insertHTML(tr.cells[2], renderURL(entry.url, entry.result));
var filterText = entry.result.slice(3);
if ( entry.result.lastIndexOf('sa', 0) === 0 ) {
filterText = '@@' + filterText;
}
tr.cells[1].textContent = filterText;
tr.cells[2].textContent = entry.type;
vAPI.insertHTML(tr.cells[3], renderURL(entry.url, entry.result));
tbody.insertBefore(tr, tbody.firstChild);
};

View file

@ -79,8 +79,6 @@ const AllowAnyParty = AllowAction | AnyParty;
var pageHostname = ''; // short-lived register
var reIgnoreEmpty = /^\s+$/;
var reIgnoreComment = /^\[|^!/;
var reHostnameRule = /^[0-9a-z][0-9a-z.-]+[0-9a-z]$/;
var reHostnameToken = /^[0-9a-z]+/g;
var reGoodToken = /[%0-9a-z]{2,}/g;
@ -813,6 +811,61 @@ FilterManyWildcardsHostname.fromSelfie = function(s) {
return new FilterManyWildcardsHostname(args[0], atoi(args[1]), args[2]);
};
/******************************************************************************/
// Regex-based filters
var FilterRegex = function(s) {
this.re = new RegExp(s);
};
FilterRegex.prototype.match = function(url) {
return this.re.test(url);
};
FilterRegex.prototype.fid = '//';
FilterRegex.prototype.toString = function() {
return '/' + this.re.source + '/';
};
FilterRegex.prototype.toSelfie = function() {
return this.re.source;
};
FilterRegex.fromSelfie = function(s) {
return new FilterRegex(s);
};
/******************************************************************************/
var FilterRegexHostname = function(s, hostname) {
this.re = new RegExp(s);
this.hostname = hostname;
};
FilterRegexHostname.prototype.match = function(url) {
// test hostname first, it's cheaper than evaluating a regex
return pageHostname.slice(-this.hostname.length) === this.hostname &&
this.re.test(url);
};
FilterRegexHostname.prototype.fid = '//h';
FilterRegexHostname.prototype.toString = function() {
return '/' + this.re.source + '/$domain=' + this.hostname;
};
FilterRegexHostname.prototype.toSelfie = function() {
return this.re.source + '\t' +
this.hostname;
};
FilterRegexHostname.fromSelfie = function(s) {
var pos = s.indexOf('\t');
return new FilterRegexHostname(s.slice(0, pos), s.slice(pos + 1));
};
/******************************************************************************/
/******************************************************************************/
@ -920,12 +973,15 @@ FilterBucket.fromSelfie = function() {
/******************************************************************************/
var makeFilter = function(details, tokenBeg) {
var makeFilter = function(details) {
var s = details.f;
if ( details.isRegex ) {
return new FilterRegex(s);
}
var wcOffset = s.indexOf('*');
if ( wcOffset !== -1 ) {
if ( s.indexOf('*', wcOffset + 1) !== -1 ) {
return details.anchor === 0 ? new FilterManyWildcards(s, tokenBeg) : null;
return details.anchor === 0 ? new FilterManyWildcards(s, details.tokenBeg) : null;
}
var lSegment = s.slice(0, wcOffset);
var rSegment = s.slice(wcOffset + 1);
@ -935,10 +991,10 @@ var makeFilter = function(details, tokenBeg) {
if ( details.anchor > 0 ) {
return new FilterSingleWildcardRightAnchored(lSegment, rSegment);
}
if ( tokenBeg === 0 ) {
if ( details.tokenBeg === 0 ) {
return new FilterSingleWildcardPrefix0(lSegment, rSegment);
}
return new FilterSingleWildcard(lSegment, rSegment, tokenBeg);
return new FilterSingleWildcard(lSegment, rSegment, details.tokenBeg);
}
if ( details.anchor < 0 ) {
return new FilterPlainLeftAnchored(s);
@ -949,23 +1005,26 @@ var makeFilter = function(details, tokenBeg) {
if ( details.hostnameAnchored ) {
return new FilterPlainHnAnchored(s);
}
if ( tokenBeg === 0 ) {
if ( details.tokenBeg === 0 ) {
return new FilterPlainPrefix0(s);
}
if ( tokenBeg === 1 ) {
if ( details.tokenBeg === 1 ) {
return new FilterPlainPrefix1(s);
}
return new FilterPlain(s, tokenBeg);
return new FilterPlain(s, details.tokenBeg);
};
/******************************************************************************/
var makeHostnameFilter = function(details, tokenBeg, hostname) {
var makeHostnameFilter = function(details, hostname) {
var s = details.f;
if ( details.isRegex ) {
return new FilterRegexHostname(s, hostname);
}
var wcOffset = s.indexOf('*');
if ( wcOffset !== -1 ) {
if ( s.indexOf('*', wcOffset + 1) !== -1 ) {
return details.anchor === 0 ? new FilterManyWildcardsHostname(s, tokenBeg, hostname) : null;
return details.anchor === 0 ? new FilterManyWildcardsHostname(s, details.tokenBeg, hostname) : null;
}
var lSegment = s.slice(0, wcOffset);
var rSegment = s.slice(wcOffset + 1);
@ -975,10 +1034,10 @@ var makeHostnameFilter = function(details, tokenBeg, hostname) {
if ( details.anchor > 0 ) {
return new FilterSingleWildcardRightAnchoredHostname(lSegment, rSegment, hostname);
}
if ( tokenBeg === 0 ) {
if ( details.tokenBeg === 0 ) {
return new FilterSingleWildcardPrefix0Hostname(lSegment, rSegment, hostname);
}
return new FilterSingleWildcardHostname(lSegment, rSegment, tokenBeg, hostname);
return new FilterSingleWildcardHostname(lSegment, rSegment, details.tokenBeg, hostname);
}
if ( details.anchor < 0 ) {
return new FilterPlainLeftAnchoredHostname(s, hostname);
@ -986,13 +1045,13 @@ var makeHostnameFilter = function(details, tokenBeg, hostname) {
if ( details.anchor > 0 ) {
return new FilterPlainRightAnchoredHostname(s, hostname);
}
if ( tokenBeg === 0 ) {
if ( details.tokenBeg === 0 ) {
return new FilterPlainPrefix0Hostname(s, hostname);
}
if ( tokenBeg === 1 ) {
if ( details.tokenBeg === 1 ) {
return new FilterPlainPrefix1Hostname(s, hostname);
}
return new FilterPlainHostname(s, tokenBeg, hostname);
return new FilterPlainHostname(s, details.tokenBeg, hostname);
};
/******************************************************************************/
@ -1060,7 +1119,10 @@ var trimChar = function(s, c) {
/******************************************************************************/
var FilterParser = function() {
this.reHasWildcard = /[\^\*]/;
this.reHasUppercase = /[A-Z]/;
this.hostnames = [];
this.notHostnames = [];
this.types = [];
this.reset();
};
@ -1092,8 +1154,12 @@ FilterParser.prototype.reset = function() {
this.hostnameAnchored = false;
this.hostnamePure = false;
this.hostnames.length = 0;
this.notHostname = false;
this.notHostnames.length = 0;
this.isRegex = false;
this.thirdParty = false;
this.token = '';
this.tokenBeg = 0;
this.tokenEnd = 0;
this.types.length = 0;
this.important = 0;
this.unsupported = false;
@ -1140,101 +1206,22 @@ FilterParser.prototype.parseOptParty = function(not) {
FilterParser.prototype.parseOptHostnames = function(raw) {
var hostnames = raw.split('|');
var hostname, not;
var hostname;
for ( var i = 0; i < hostnames.length; i++ ) {
hostname = hostnames[i];
not = hostname.charAt(0) === '~';
if ( not ) {
hostname = hostname.slice(1);
if ( hostname.charAt(0) === '~' ) {
this.notHostnames.push(hostname.slice(1));
} else {
this.hostnames.push(hostname);
}
// https://github.com/gorhill/uBlock/issues/191
// Well it doesn't seem to make a whole lot of sense to have both
// non-negated hostnames mixed with negated hostnames.
if ( this.hostnames.length !== 0 && not !== this.notHostname ) {
console.error('FilterContainer.parseOptHostnames(): ambiguous filter syntax: "%s"', this.f);
this.unsupported = true;
return;
}
this.notHostname = not;
this.hostnames.push(hostname);
}
};
/******************************************************************************/
FilterParser.prototype.parse = function(s) {
// important!
this.reset();
if ( reHostnameRule.test(s) ) {
this.f = s;
this.hostnamePure = this.hostnameAnchored = true;
return this;
}
// element hiding filter?
if ( s.indexOf('##') >= 0 || s.indexOf('#@') >= 0 ) {
this.elemHiding = true;
return this;
}
// block or allow filter?
if ( s.slice(0, 2) === '@@' ) {
this.action = AllowAction;
s = s.slice(2);
}
// options
var pos = s.indexOf('$');
if ( pos > 0 ) {
this.fopts = s.slice(pos + 1);
s = s.slice(0, pos);
}
// regex? (not supported)
if ( s.charAt(0) === '/' && s.slice(-1) === '/' ) {
this.unsupported = true;
return this;
}
// hostname anchoring
if ( s.slice(0, 2) === '||' ) {
this.hostnameAnchored = true;
s = s.slice(2);
}
// left-anchored
if ( s.charAt(0) === '|' ) {
this.anchor = -1;
s = s.slice(1);
}
// right-anchored
if ( s.slice(-1) === '|' ) {
this.anchor = 1;
s = s.slice(0, -1);
}
// normalize placeholders
// TODO: transforming `^` into `*` is not a strict interpretation of
// ABP syntax.
s = s.replace(/\^/g, '*');
s = s.replace(/\*\*+/g, '*');
// remove leading and trailing wildcards
s = trimChar(s, '*');
// pure hostname-based?
this.hostnamePure = this.hostnameAnchored && reHostnameRule.test(s);
this.f = s;
if ( !this.fopts ) {
return this;
}
// parse options
var opts = this.fopts.split(',');
FilterParser.prototype.parseOptions = function(s) {
this.fopts = s;
var opts = s.split(',');
var opt, not;
for ( var i = 0; i < opts.length; i++ ) {
opt = opts[i];
@ -1270,9 +1257,119 @@ FilterParser.prototype.parse = function(s) {
this.unsupported = true;
break;
}
};
/******************************************************************************/
FilterParser.prototype.parse = function(s) {
// important!
this.reset();
// plain hostname?
if ( reHostnameRule.test(s) ) {
this.f = s;
this.hostnamePure = this.hostnameAnchored = true;
return this;
}
// element hiding filter?
var pos = s.indexOf('#');
if ( pos !== -1 ) {
var c = s.charAt(pos + 1);
if ( c === '#' || c === '@' ) {
console.error('static-net-filtering.js > unexpected cosmetic filters');
this.elemHiding = true;
return this;
}
}
// options
pos = s.indexOf('$');
if ( pos !== -1 ) {
this.parseOptions(s.slice(pos + 1));
s = s.slice(0, pos);
}
// block or allow filter?
if ( s.lastIndexOf('@@', 0) === 0 ) {
this.action = AllowAction;
s = s.slice(2);
}
// regex?
if ( s.charAt(0) === '/' && s.slice(-1) === '/' ) {
this.isRegex = true;
this.f = s.slice(1, -1);
return this;
}
// hostname anchoring
if ( s.lastIndexOf('||', 0) === 0 ) {
this.hostnameAnchored = true;
s = s.slice(2);
}
// left-anchored
if ( s.charAt(0) === '|' ) {
this.anchor = -1;
s = s.slice(1);
}
// right-anchored
if ( s.slice(-1) === '|' ) {
this.anchor = 1;
s = s.slice(0, -1);
}
// normalize placeholders
// TODO: transforming `^` into `*` is not a strict interpretation of
// ABP syntax.
if ( this.reHasWildcard.test(s) ) {
s = s.replace(/\^/g, '*').replace(/\*\*+/g, '*');
s = trimChar(s, '*');
}
// plain hostname?
this.hostnamePure = this.hostnameAnchored && reHostnameRule.test(s);
// This might look weird but we gain memory footprint by not going through
// toLowerCase(), at least on Chromium. Because copy-on-write?
this.f = this.reHasUppercase.test(s) ? s.toLowerCase() : s;
return this;
};
/******************************************************************************/
FilterParser.prototype.makeToken = function() {
if ( this.isRegex ) {
this.token = '*';
return;
}
var matches;
if ( this.hostnameAnchored ) {
matches = findHostnameToken(this.f);
if ( !matches || matches[0].length === 0 ) {
return;
}
this.tokenBeg = matches.index;
this.tokenEnd = reHostnameToken.lastIndex;
this.token = this.f.slice(this.tokenBeg, this.tokenEnd);
return;
}
matches = findFirstGoodToken(this.f);
if ( !matches || matches[0].length === 0 ) {
return;
}
this.tokenBeg = matches.index;
this.tokenEnd = reGoodToken.lastIndex;
this.token = this.f.slice(this.tokenBeg, this.tokenEnd);
};
/******************************************************************************/
/******************************************************************************/
@ -1410,7 +1507,9 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
'*|': FilterSingleWildcardRightAnchored,
'*|h': FilterSingleWildcardRightAnchoredHostname,
'*+': FilterManyWildcards,
'*+h': FilterManyWildcardsHostname
'*+h': FilterManyWildcardsHostname,
'//': FilterRegex,
'//h': FilterRegexHostname
};
var catKey, tokenKey;
@ -1463,26 +1562,28 @@ FilterContainer.prototype.add = function(s) {
// ORDER OF TESTS IS IMPORTANT!
// Ignore empty lines
if ( reIgnoreEmpty.test(s) ) {
s = s.trim();
if ( s.length === 0 ) {
return false;
}
// Ignore comments
if ( reIgnoreComment.test(s) ) {
var c = s.charAt(0);
if ( c === '[' || c === '!' ) {
return false;
}
var parsed = this.filterParser.parse(s);
// Ignore rules with other conditions for now
if ( parsed.unsupported ) {
this.rejectedCount += 1;
// console.log('µBlock> abp-filter.js/FilterContainer.add(): unsupported filter "%s"', s);
// Ignore element-hiding filters
if ( parsed.elemHiding ) {
return false;
}
// Ignore element-hiding filters
if ( parsed.elemHiding ) {
// Ignore filters with unsupported options
if ( parsed.unsupported ) {
this.rejectedCount += 1;
// console.log('µBlock> abp-filter.js/FilterContainer.add(): unsupported filter "%s"', s);
return false;
}
@ -1533,95 +1634,95 @@ FilterContainer.prototype.add = function(s) {
/******************************************************************************/
FilterContainer.prototype.addFilter = function(parsed) {
// TODO: avoid duplicates
var matches = parsed.hostnameAnchored ?
findHostnameToken(parsed.f) :
findFirstGoodToken(parsed.f);
if ( !matches || !matches[0].length ) {
parsed.makeToken();
if ( parsed.token === '' ) {
console.error('static-net-filtering.js > FilterContainer.addFilter("%s"): can\'t tokenize', parsed.f);
return false;
}
var tokenBeg = matches.index;
var tokenEnd = parsed.hostnameAnchored ?
reHostnameToken.lastIndex :
reGoodToken.lastIndex;
var filter;
var i = parsed.hostnames.length;
// Applies to specific domains
if ( i !== 0 && !parsed.notHostname ) {
while ( i-- ) {
filter = makeHostnameFilter(parsed, tokenBeg, parsed.hostnames[i]);
if ( !filter ) {
return false;
}
this.addFilterEntry(filter, parsed, AnyParty, tokenBeg, tokenEnd);
}
return true;
}
var party = AnyParty;
if ( parsed.firstParty !== parsed.thirdParty ) {
party = parsed.firstParty ? FirstParty : ThirdParty;
}
// Applies to all domains, with exception(s)
var filter;
var i = parsed.hostnames.length;
var j = parsed.notHostnames.length;
// https://github.com/gorhill/uBlock/issues/191
// Invert the purpose of the filter for negated hostnames
if ( i !== 0 && parsed.notHostname ) {
filter = makeFilter(parsed, tokenBeg);
// Applies to all domains without exceptions
if ( i === 0 && j === 0 ) {
filter = makeFilter(parsed);
if ( !filter ) {
return false;
}
this.addFilterEntry(filter, parsed, party);
return true;
}
// Applies to specific domains
if ( i !== 0 ) {
while ( i-- ) {
filter = makeHostnameFilter(parsed, parsed.hostnames[i]);
if ( !filter ) {
return false;
}
this.addFilterEntry(filter, parsed, party);
}
}
// No exceptions
if ( j === 0 ) {
return true;
}
// Case:
// - applies everywhere except to specific domains
// Example:
// - ||adm.fwmrm.net/p/msnbc_live/$object-subrequest,third-party,domain=~msnbc.msn.com|~www.nbcnews.com
if ( i === 0 ) {
filter = makeFilter(parsed);
if ( !filter ) {
return false;
}
// https://github.com/gorhill/uBlock/issues/251
// Apply third-party option if it is present
this.addFilterEntry(filter, parsed, party, tokenBeg, tokenEnd);
// Reverse purpose of filter
parsed.action ^= ToggleAction;
while ( i-- ) {
filter = makeHostnameFilter(parsed, tokenBeg, parsed.hostnames[i]);
if ( !filter ) {
return false;
}
// https://github.com/gorhill/uBlock/issues/191#issuecomment-53654024
// If it is a block filter, we need to reverse the order of
// evaluation.
if ( parsed.action === BlockAction ) {
parsed.important = Important;
}
this.addFilterEntry(filter, parsed, AnyParty, tokenBeg, tokenEnd);
this.addFilterEntry(filter, parsed, party);
}
// Cases:
// - applies everywhere except to specific domains
// - applies to specific domains except other specific domains
// Example:
// - /^https?\:\/\/(?!(...)\/)/$script,third-party,xmlhttprequest,domain=photobucket.com|~secure.photobucket.com
// Reverse purpose of filter
parsed.action ^= ToggleAction;
while ( j-- ) {
filter = makeHostnameFilter(parsed, parsed.notHostnames[j]);
if ( !filter ) {
return false;
}
return true;
// https://github.com/gorhill/uBlock/issues/191#issuecomment-53654024
// If it is a block filter, we need to reverse the order of
// evaluation.
if ( parsed.action === BlockAction ) {
parsed.important = Important;
}
this.addFilterEntry(filter, parsed, party);
}
// Applies to all domains without exceptions
filter = makeFilter(parsed, tokenBeg);
if ( !filter ) {
return false;
}
this.addFilterEntry(filter, parsed, party, tokenBeg, tokenEnd);
return true;
};
/******************************************************************************/
FilterContainer.prototype.addFilterEntry = function(filter, parsed, party, tokenBeg, tokenEnd) {
var s = parsed.f;
var tokenKey = s.slice(tokenBeg, tokenEnd);
FilterContainer.prototype.addFilterEntry = function(filter, parsed, party) {
var bits = parsed.action | parsed.important | party;
if ( parsed.types.length === 0 ) {
this.addToCategory(bits | AnyType, tokenKey, filter);
this.addToCategory(bits | AnyType, parsed.token, filter);
return;
}
var n = parsed.types.length;
for ( var i = 0; i < n; i++ ) {
this.addToCategory(bits | parsed.types[i], tokenKey, filter);
this.addToCategory(bits | parsed.types[i], parsed.token, filter);
}
};
@ -1691,6 +1792,13 @@ FilterContainer.prototype.matchTokens = function(bucket, url) {
return f;
}
}
// Regex-based filters
f = bucket['*'];
if ( f !== undefined && f.match(url) !== false ) {
return f;
}
return false;
};
@ -1756,7 +1864,7 @@ FilterContainer.prototype.matchStringExactType = function(context, requestURL, r
var type = typeNameToTypeValue[requestType];
var categories = this.categories;
var bucket;
var bf = false, bucket;
// Tokenize only once
this.tokenize(url);
@ -1777,7 +1885,6 @@ FilterContainer.prototype.matchStringExactType = function(context, requestURL, r
}
// Test against block filters
bf = false;
if ( bucket = categories[this.makeCategoryKey(BlockAnyParty | type)] ) {
bf = this.matchTokens(bucket, url);
}
@ -1853,7 +1960,7 @@ FilterContainer.prototype.matchString = function(context) {
pageHostname = context.pageHostname || '';
var categories = this.categories;
var bucket;
var bf, bucket;
// Tokenize only once
this.tokenize(url);

View file

@ -374,12 +374,15 @@
var cosmeticFilteringEngine = this.cosmeticFilteringEngine;
var parseCosmeticFilters = this.userSettings.parseAllABPHideFilters;
var reIsCosmeticFilter = /#@?#/;
var reLocalhost = /(?:^|\s)(?:localhost\.localdomain|localhost|local|broadcasthost|0\.0\.0\.0|127\.0\.0\.1|::1|fe80::1%lo0)(?=\s|$)/g;
var reAsciiSegment = /^[\x21-\x7e]+$/;
var reIsCosmeticFilter = /#[@#]/;
var reIsWhitespaceChar = /\s/;
var reMaybeLocalIp = /^[\d:f]/;
var reIsLocalhostRedirect = /\s+(?:broadcasthost|local|localhost|localhost\.localdomain)(?=\s|$)/;
var reLocalIp = /^(?:0\.0\.0\.0|127\.0\.0\.1|::1|fe80::1%lo0)/;
//var reAsciiSegment = /^[\x21-\x7e]+$/;
var matches;
var lineBeg = 0, lineEnd, currentLineBeg;
var line, c;
var line, lineRaw, c, pos;
while ( lineBeg < rawEnd ) {
lineEnd = rawText.indexOf('\n', lineBeg);
@ -393,10 +396,14 @@
// rhill 2014-04-18: The trim is important here, as without it there
// could be a lingering `\r` which would cause problems in the
// following parsing code.
line = rawText.slice(lineBeg, lineEnd).trim();
line = lineRaw = rawText.slice(lineBeg, lineEnd).trim();
currentLineBeg = lineBeg;
lineBeg = lineEnd + 1;
if ( line.length === 0 ) {
continue;
}
// Strip comments
c = line.charAt(0);
if ( c === '!' || c === '[' ) {
@ -404,6 +411,7 @@
}
// Parse or skip cosmetic filters
// All cosmetic filters are caught here
if ( parseCosmeticFilters ) {
if ( cosmeticFilteringEngine.add(line) ) {
continue;
@ -412,36 +420,59 @@
continue;
}
// Whatever else is next can be assumed to not be a cosmetic filter
// Most comments start in first column
if ( c === '#' ) {
continue;
}
// Catch comments somewhere on the line
// Remove:
// ... #blah blah blah
// ... # blah blah blah
// Don't remove:
// ...#blah blah blah
// because some ABP filters uses the `#` character (URL fragment)
pos = line.indexOf('#');
if ( pos !== -1 && reIsWhitespaceChar.test(line.charAt(pos - 1)) ) {
line = line.slice(0, pos).trim();
}
// https://github.com/gorhill/httpswitchboard/issues/15
// Ensure localhost et al. don't end up in the ubiquitous blacklist.
// TODO: do this only if it's not an [Adblock] list
line = line
.replace(/\s+#.*$/, '')
.toLowerCase()
.replace(reLocalhost, '')
.trim();
// With hosts files, we need to remove local IP redirection
if ( reMaybeLocalIp.test(c) ) {
// Ignore hosts file redirect configuration
// 127.0.0.1 localhost
// 255.255.255.255 broadcasthost
if ( reIsLocalhostRedirect.test(line) ) {
continue;
}
line = line.replace(reLocalIp, '').trim();
}
if ( line.length === 0 ) {
continue;
}
// The filter is whatever sequence of printable ascii character without
// whitespaces
matches = reAsciiSegment.exec(line);
if ( matches === null ) {
//console.debug('µBlock.mergeFilterList(): skipping "%s"', lineRaw);
continue;
}
//matches = reAsciiSegment.exec(line);
//if ( matches === null ) {
// console.debug('storage.js > µBlock.mergeFilterList(): skipping "%s"', lineRaw);
// continue;
//}
// Bypass anomalies
// For example, when a filter contains whitespace characters, or
// whatever else outside the range of printable ascii characters.
if ( matches[0] !== line ) {
// console.error('"%s" !== "%s"', matches[0], line);
continue;
}
//if ( matches[0] !== line ) {
// console.error('"%s" !== "%s"', matches[0], line);
// continue;
//}
staticNetFilteringEngine.add(matches[0]);
staticNetFilteringEngine.add(line);
}
};
@ -607,16 +638,17 @@
if ( countdown !== 0 ) {
return;
}
// https://github.com/gorhill/uBlock/issues/426
// Important: remove barrier to remote fetching, this was useful only
// for launch time.
µb.assets.allowRemoteFetch = true;
vAPI.onLoadAllCompleted();
// https://github.com/gorhill/uBlock/issues/184
// Check for updates not too far in the future.
µb.updater.restart(µb.firstUpdateAfter);
vAPI.onLoadAllCompleted();
};
// Filters are in memory.