From 46d39838e3823959e1e701d4d941ac932e4b4a6e Mon Sep 17 00:00:00 2001 From: gorhill Date: Thu, 26 Nov 2015 17:56:30 -0500 Subject: [PATCH] redirect engine: more fine tuning + proof of concept for dayt.se --- assets/checksums.txt | 2 +- assets/ublock/redirect.txt | 10 +++++ src/js/messaging.js | 19 ++++++---- src/js/redirect-engine.js | 75 +++++++++++++++++++++++++++++++------- src/js/traffic.js | 2 +- 5 files changed, 86 insertions(+), 22 deletions(-) diff --git a/assets/checksums.txt b/assets/checksums.txt index c78bb7783..0116bf3d2 100644 --- a/assets/checksums.txt +++ b/assets/checksums.txt @@ -3,7 +3,7 @@ a65d3b35ba116f897c7ef5db2046da73 assets/ublock/unbreak.txt 7a04294b44b88baa34cf3e4bfe0e59db assets/ublock/privacy.txt b2dbf435507aa0262b289c67cbef2142 assets/ublock/filters.txt 146704ad1c0393e342afdb416762c183 assets/ublock/badware.txt -d3e766dbd8624423a7e5fea878580ee9 assets/ublock/redirect.txt +7793a25fee903eb869984d728cb1920c assets/ublock/redirect.txt e1a6bb625a9ee59cc57f6b77c76108ff assets/ublock/filter-lists.json f549ce62117ff04b63c177227b5cb288 assets/thirdparties/easylist-downloads.adblockplus.org/easyprivacy.txt da709032e6b674de08b7561e3f4e552d assets/thirdparties/easylist-downloads.adblockplus.org/easylist.txt diff --git a/assets/ublock/redirect.txt b/assets/ublock/redirect.txt index 832f80073..3d2791f21 100644 --- a/assets/ublock/redirect.txt +++ b/assets/ublock/redirect.txt @@ -5,3 +5,13 @@ ||s3.amazonaws.com/homad-global-configs.schneevonmorgen.com/hd-main.js$script,domain=cdnapi.kaltura.com,redirect=hd-main.js ||hgc.svonm.com/hd-main.js$script,domain=cdnapi.kaltura.com,redirect=hd-main.js + +# Proof of concept: no need to open ourselves to more 3rd-party scripts/frames in +# order to prevent blocker bypass. The `important` filter option is used here +# to override EasyList exception filters for this case: ideally exception filters +# should be avoided as much as possible. +||ads.ad-center.com/smart_ad/display?ref=*&smart_ad_id=$subdocument,domain=dayt.se,redirect=noopframe,important +||ads.ad-center.com^$subdocument,domain=dayt.se,redirect=noopframe,important +||aflrm.com^$subdocument,domain=dayt.se,redirect=noopframe,important +||dayt.se^*fuckadblock.js$script,redirect=fuckadblock.js-3.2.0,important +||imads.integral-marketing.com^$domain=dayt.se,important diff --git a/src/js/messaging.js b/src/js/messaging.js index 1e7c24b2d..9e29d85ef 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -521,28 +521,33 @@ var filterRequests = function(pageStore, details) { //console.debug('messaging.js/contentscript-end.js: processing %d requests', requests.length); - var µburi = µb.URI; - var isBlockResult = µb.isBlockResult; + var hostnameFromURI = µb.URI.hostnameFromURI; + var redirectEngine = µb.redirectEngine; // Create evaluation context var context = pageStore.createContextFromFrameHostname(details.pageHostname); - var request; + var request, r; var i = requests.length; while ( i-- ) { request = requests[i]; context.requestURL = vAPI.punycodeURL(request.url); - context.requestHostname = µburi.hostnameFromURI(request.url); // https://github.com/gorhill/uBlock/issues/978 // Ignore invalid URLs: these would not occur on the HTTP // observer side. - if ( context.requestHostname === '' ) { + if ( (context.requestHostname = hostnameFromURI(request.url)) === '' ) { continue; } context.requestType = tagNameToRequestTypeMap[request.tagName]; - if ( isBlockResult(pageStore.filterRequest(context)) ) { - request.collapse = true; + r = pageStore.filterRequest(context); + if ( typeof r !== 'string' || r.charAt(1) !== 'b' ) { + continue; } + // Redirected? (We do not hide redirected resources.) + if ( redirectEngine.matches(context) ) { + continue; + } + request.collapse = true; } return requests; }; diff --git a/src/js/redirect-engine.js b/src/js/redirect-engine.js index 779d1a94a..a2225c746 100644 --- a/src/js/redirect-engine.js +++ b/src/js/redirect-engine.js @@ -37,6 +37,44 @@ var toBroaderHostname = function(hostname) { return hostname !== '*' && hostname !== '' ? '*' : ''; }; +/******************************************************************************/ +/******************************************************************************/ + +var RedirectEntry = function(mime, lines) { + this.mime = mime; + this.encoded = mime.indexOf(';') !== -1; + var data = lines.join(this.encoded ? '' : '\n'); + // check for placeholders. + this.ph = this.encoded === false && this.rePlaceHolders.test(data); + if ( this.ph ) { + this.data = data; + } else { + this.data = + 'data:' + + mime + + (this.encoded ? '' : ';base64') + + ',' + + (this.encoded ? data : btoa(data)); + } +}; + +/******************************************************************************/ + +RedirectEntry.prototype.rePlaceHolders = /\{\{.+?\}\}/; +RedirectEntry.prototype.reRequestURL = /\{\{requestURL\}\}/g; + +/******************************************************************************/ + +RedirectEntry.prototype.toURL = function(requestURL) { + if ( this.ph === false ) { + return this.data; + } + return 'data:' + + this.mime + ';base64,' + + btoa(this.data.replace(this.reRequestURL, requestURL)); +}; + +/******************************************************************************/ /******************************************************************************/ var RedirectEngine = function() { @@ -77,7 +115,7 @@ RedirectEngine.prototype.lookup = function(context) { while ( i-- ) { entry = entries[i]; if ( entry.c.test(reqURL) ) { - return this.resources[entry.r]; + return entry.r; } } } @@ -96,6 +134,26 @@ RedirectEngine.prototype.lookup = function(context) { /******************************************************************************/ +RedirectEngine.prototype.toURL = function(context) { + var token = this.lookup(context); + if ( token === undefined ) { + return; + } + var entry = this.resources[token]; + if ( entry !== undefined ) { + return entry.toURL(context.requestURL); + } +}; + +/******************************************************************************/ + +RedirectEngine.prototype.matches = function(context) { + var token = this.lookup(context); + return token !== undefined && this.resources[token] !== undefined; +}; + +/******************************************************************************/ + RedirectEngine.prototype.addRule = function(src, des, type, pattern, redirect) { var typeEntry = this.rules[type]; if ( typeEntry === undefined ) { @@ -225,16 +283,6 @@ RedirectEngine.prototype.resourcesFromString = function(text) { var line, fields, encoded; var reNonEmptyLine = /\S/; - var resourceFromFields = function(fields, encoded) { - var data = fields.slice(2).join(encoded ? '' : '\n'); - this.resources[fields[0]] = - 'data:' + - fields[1] + - (encoded ? '' : ';base64') + - ',' + - (encoded ? data : btoa(data)); - }.bind(this); - this.resources = Object.create(null); while ( lineBeg < textEnd ) { @@ -268,17 +316,18 @@ RedirectEngine.prototype.resourcesFromString = function(text) { } // No more data, add the resource. - resourceFromFields(fields, encoded); + this.resources[fields[0]] = new RedirectEntry(fields[1], fields.slice(2)); fields = undefined; } // Process pending resource data. if ( fields !== undefined ) { - resourceFromFields(fields, encoded); + this.resources[fields[0]] = new RedirectEntry(fields[1], fields.slice(2)); } }; +/******************************************************************************/ /******************************************************************************/ return new RedirectEngine(); diff --git a/src/js/traffic.js b/src/js/traffic.js index 348d65cbf..bcd071b91 100644 --- a/src/js/traffic.js +++ b/src/js/traffic.js @@ -133,7 +133,7 @@ var onBeforeRequest = function(details) { // https://github.com/gorhill/uBlock/issues/949 // Redirect blocked request? - var url = µb.redirectEngine.lookup(requestContext); + var url = µb.redirectEngine.toURL(requestContext); if ( url !== undefined ) { return { redirectUrl: url }; }