From ba8b9ba008e83b9f5b6d1f1b7ccdc2f7f3d8bc0f Mon Sep 17 00:00:00 2001 From: gorhill Date: Mon, 23 Nov 2015 23:34:03 -0500 Subject: [PATCH] redirection engine: code review --- assets/checksums.txt | 2 +- ...irect-rules.txt => redirect-resources.txt} | 13 +++- src/js/redirect-engine.js | 67 +++++++++---------- src/js/start.js | 2 +- src/js/static-net-filtering.js | 10 ++- src/js/storage.js | 9 +-- 6 files changed, 60 insertions(+), 43 deletions(-) rename assets/ublock/{redirect-rules.txt => redirect-resources.txt} (50%) diff --git a/assets/checksums.txt b/assets/checksums.txt index 67b1fdf75..04b240472 100644 --- a/assets/checksums.txt +++ b/assets/checksums.txt @@ -1,11 +1,11 @@ d644ffec21b802b4efb76365a576b86f assets/ublock/unbreak.txt +e65fbcaa573c028770f1d0afada55672 assets/ublock/redirect-resources.txt 7a04294b44b88baa34cf3e4bfe0e59db assets/ublock/privacy.txt b2dbf435507aa0262b289c67cbef2142 assets/ublock/filters.txt 146704ad1c0393e342afdb416762c183 assets/ublock/badware.txt 4b3df06f0b27c57cea0006ae559e078b assets/ublock/redirect.txt c9c5cc56bec563bc1885847f925b9be2 assets/ublock/mirror-candidates.txt f9455a47b5024cc08ff3675ce79b58a9 assets/ublock/filter-lists.json -b7781a2ab4094b0ffa363caa6e29801d assets/ublock/redirect-rules.txt 94c0a3eab74c42783855f07b22a429cf assets/thirdparties/home.fredfiber.no/langsholt/adblock.txt a82cb5ba5caf035ce00e97de81db5de7 assets/thirdparties/www.zoso.ro/pages/rolist.txt 72373316d0e7ad22604d307c2d93e7cc assets/thirdparties/adblock.gardar.net/is.abp.txt diff --git a/assets/ublock/redirect-rules.txt b/assets/ublock/redirect-resources.txt similarity index 50% rename from assets/ublock/redirect-rules.txt rename to assets/ublock/redirect-resources.txt index bde2080f0..a96c1cf08 100644 --- a/assets/ublock/redirect-rules.txt +++ b/assets/ublock/redirect-resources.txt @@ -1,4 +1,12 @@ -redirects: +# Resources to be used as redirect destinations. +# +# - Each distinct resource entry is separated by an empty line. +# - The first line in a resource entry is: token mime-type[;encoding] +# - All following lines are the data. An empty line signals the end of the +# data. +# +# If the encoding is absent, the data will be converted to base64, and the +# encoding will be set to `;base64`. hd-main.js application/javascript var L = (function(){ @@ -11,3 +19,6 @@ var L = (function(){ return l; })(); +# http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever +handtinytrans.gif image/gif;base64 +R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== diff --git a/src/js/redirect-engine.js b/src/js/redirect-engine.js index d5c2adff1..21a22a1a0 100644 --- a/src/js/redirect-engine.js +++ b/src/js/redirect-engine.js @@ -40,7 +40,7 @@ var toBroaderHostname = function(hostname) { /******************************************************************************/ var RedirectEngine = function() { - this.redirects = Object.create(null); + this.resources = Object.create(null); this.reset(); }; @@ -77,7 +77,7 @@ RedirectEngine.prototype.lookup = function(context) { while ( i-- ) { entry = entries[i]; if ( entry.c.test(reqURL) ) { - return this.redirects[entry.r]; + return this.resources[entry.r]; } } } @@ -96,8 +96,6 @@ RedirectEngine.prototype.lookup = function(context) { /******************************************************************************/ -// TODO: combine same key-redirect pairs into a single regex. - RedirectEngine.prototype.addRule = function(src, des, type, pattern, redirect) { var typeEntry = this.rules[type]; if ( typeEntry === undefined ) { @@ -159,7 +157,13 @@ RedirectEngine.prototype.compileRuleFromStaticFilter = function(line) { } } - if ( redirect === '' || types.length === 0 ) { + // Need a resource token. + if ( redirect === '' ) { + return ''; + } + + // Need one single type (not negated). + if ( types.length !== 1 || types[0].charAt(0) === '~' ) { return ''; } @@ -172,12 +176,13 @@ RedirectEngine.prototype.compileRuleFromStaticFilter = function(line) { } var out = []; - var i = srcs.length, j; + var i = srcs.length, src; while ( i-- ) { - j = types.length; - while ( j-- ) { - out.push(srcs[i] + '\t' + des + '\t' + types[j] + '\t' + pattern + '\t' + redirect); + src = srcs[i]; + if ( src.charAt(0) === '~' ) { + continue; } + out.push(srcs[i] + '\t' + des + '\t' + types[0] + '\t' + pattern + '\t' + redirect); } return out; @@ -203,12 +208,12 @@ RedirectEngine.prototype.supportedTypes = (function() { // TODO: combine same key-redirect pairs into a single regex. -RedirectEngine.prototype.redirectDataFromString = function(text) { +RedirectEngine.prototype.resourcesFromString = function(text) { var textEnd = text.length; var lineBeg = 0, lineEnd; - var mode, modeData, line, fields, encoded, data; + var line, fields, resource, encoded, data; - this.redirects = Object.create(null); + this.resources = Object.create(null); while ( lineBeg < textEnd ) { lineEnd = text.indexOf('\n', lineBeg); @@ -225,37 +230,31 @@ RedirectEngine.prototype.redirectDataFromString = function(text) { continue; } - if ( line.slice(-1) === ':' ) { - mode = line.slice(0, -1); - continue; - } - - if ( mode === 'redirects' ) { + if ( resource === undefined ) { fields = line.split(/\s+/); if ( fields.length !== 2 ) { continue; } - mode = 'redirects/redirect'; - modeData = fields; + resource = fields; continue; } - if ( mode === 'redirects/redirect' ) { - if ( line !== '' ) { - modeData.push(line); - continue; - } - encoded = modeData[1].indexOf(';') !== -1; - data = modeData.slice(2).join(encoded ? '' : '\n'); - this.redirects[modeData[0]] = - 'data:' + - modeData[1] + - (encoded ? '' : ';base64') + - ',' + - (encoded ? data : btoa(data)); - mode = 'redirects'; + if ( line !== '' ) { + resource.push(line); continue; } + + // No more data, store the resource. + encoded = resource[1].indexOf(';') !== -1; + data = resource.slice(2).join(encoded ? '' : '\n'); + this.resources[resource[0]] = + 'data:' + + resource[1] + + (encoded ? '' : ';base64') + + ',' + + (encoded ? data : btoa(data)); + + resource = undefined; } }; diff --git a/src/js/start.js b/src/js/start.js index 517131d8b..23c192cf4 100644 --- a/src/js/start.js +++ b/src/js/start.js @@ -211,7 +211,7 @@ var onFirstFetchReady = function(fetched) { fromFetch(µb.restoreBackupSettings, fetched); onNetWhitelistReady(fetched.netWhitelist); onVersionReady(fetched.version); - µb.loadRedirectRules(); + µb.loadRedirectResources(); // If we have a selfie, skip loading PSL, filters if ( onSelfieReady(fetched.selfie) ) { diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index 679fd4756..01640fd23 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -1503,9 +1503,15 @@ FilterParser.prototype.parseOptions = function(s) { continue; } if ( opt.lastIndexOf('redirect=', 0) === 0 ) { - this.redirect = true; - continue; + if ( this.action === BlockAction ) { + this.redirect = true; + continue; + } + this.unsupported = true; + break; } + + // Unrecognized filter option: ignore whole filter. this.unsupported = true; break; } diff --git a/src/js/storage.js b/src/js/storage.js index c29ed3949..58089dd7d 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -650,20 +650,21 @@ // TODO: toSelfie/fromSelfie. -µBlock.loadRedirectRules = function(callback) { +µBlock.loadRedirectResources = function(callback) { var µb = this; if ( typeof callback !== 'function' ) { callback = this.noopFunc; } - var onRulesLoaded = function(details) { + + var onResourcesLoaded = function(details) { if ( details.content !== '' ) { - µb.redirectEngine.redirectDataFromString(details.content); + µb.redirectEngine.resourcesFromString(details.content); } callback(); }; - this.assets.get('assets/ublock/redirect-rules.txt', onRulesLoaded); + this.assets.get('assets/ublock/redirect-resources.txt', onResourcesLoaded); }; /******************************************************************************/