mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-10 01:02:08 +01:00
This commit is contained in:
parent
47152560af
commit
287f04b47e
5 changed files with 68 additions and 71 deletions
|
@ -29,78 +29,44 @@
|
|||
/******************************************************************************/
|
||||
|
||||
var warResolve = (function() {
|
||||
var timer;
|
||||
var toResolve = new Set();
|
||||
var toProcess = new Set();
|
||||
var reMimeParser = /^[^/]+\/([^\s;]+)/;
|
||||
var warPairs = [];
|
||||
|
||||
var replacer = function(s) {
|
||||
if ( s === '+' ) { return '-'; }
|
||||
if ( s === '/' ) { return '_'; }
|
||||
if ( s === '=' ) { return ''; }
|
||||
return s;
|
||||
};
|
||||
|
||||
var filenameFromToken = function(token, mime) {
|
||||
var name = btoa(token).replace(/[+/=]/g, replacer);
|
||||
var match = reMimeParser.exec(mime);
|
||||
if ( match !== null ) {
|
||||
name += '.' + match[1];
|
||||
}
|
||||
return name;
|
||||
};
|
||||
|
||||
var onResolved = function(success, token, url) {
|
||||
var onPairsReady = function() {
|
||||
var reng = µBlock.redirectEngine;
|
||||
this.onload = this.onerror = null;
|
||||
var resource = reng.resources.get(token);
|
||||
if ( resource !== undefined && success ) {
|
||||
resource.warURL = url;
|
||||
}
|
||||
toProcess.delete(token);
|
||||
if ( toResolve.size === 0 && toProcess.size === 0 ) {
|
||||
reng.selfieFromResources();
|
||||
}
|
||||
};
|
||||
|
||||
var resolvePending = function() {
|
||||
timer = undefined;
|
||||
var reng = µBlock.redirectEngine,
|
||||
resources = reng.resources,
|
||||
n = 8; // max number of xhr at once
|
||||
for ( var token of toResolve ) {
|
||||
var resource = resources.get(token);
|
||||
toResolve.delete(token);
|
||||
for ( var i = 0; i < warPairs.length; i += 2 ) {
|
||||
var resource = reng.resources.get(warPairs[i+0]);
|
||||
if ( resource === undefined ) { continue; }
|
||||
toProcess.add(token);
|
||||
var url = vAPI.getURL(
|
||||
'/web_accessible_resources/' +
|
||||
filenameFromToken(token, resource.mime)
|
||||
resource.warURL = vAPI.getURL(
|
||||
'/web_accessible_resources/' + warPairs[i+1]
|
||||
);
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.timeout = 1000;
|
||||
xhr.open('head', url + '?secret=' + vAPI.warSecret);
|
||||
xhr.onload = onResolved.bind(this, true, token, url);
|
||||
xhr.onerror = onResolved.bind(this, false, token, url);
|
||||
xhr.responseType = 'text';
|
||||
xhr.send();
|
||||
n -= 1;
|
||||
if ( n === 0 ) { break; }
|
||||
}
|
||||
if ( toResolve.size !== 0 ) {
|
||||
timer = vAPI.setTimeout(resolvePending, 5);
|
||||
} else if ( toProcess.size === 0 ) {
|
||||
reng.selfieFromResources();
|
||||
}
|
||||
reng.selfieFromResources();
|
||||
};
|
||||
|
||||
return function(token) {
|
||||
if ( vAPI.warSecret !== undefined ) {
|
||||
toResolve.add(token);
|
||||
}
|
||||
if ( timer === undefined ) {
|
||||
timer = vAPI.setTimeout(resolvePending, 1);
|
||||
return function() {
|
||||
if ( vAPI.warSecret === undefined || warPairs.length !== 0 ) {
|
||||
return onPairsReady();
|
||||
}
|
||||
|
||||
var onPairsLoaded = function(details) {
|
||||
var marker = '>>>>>';
|
||||
var pos = details.content.indexOf(marker);
|
||||
if ( pos === -1 ) { return; }
|
||||
var pairs = details.content.slice(pos + marker.length)
|
||||
.trim()
|
||||
.split('\n');
|
||||
if ( (pairs.length & 1) !== 0 ) { return; }
|
||||
for ( var i = 0; i < pairs.length; i++ ) {
|
||||
pairs[i] = pairs[i].trim();
|
||||
}
|
||||
warPairs = pairs;
|
||||
onPairsReady();
|
||||
};
|
||||
|
||||
µBlock.assets.fetchText(
|
||||
'/web_accessible_resources/imported.txt?secret=' + vAPI.warSecret,
|
||||
onPairsLoaded
|
||||
);
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -500,7 +466,6 @@ RedirectEngine.prototype.resourcesFromString = function(text) {
|
|||
|
||||
// No more data, add the resource.
|
||||
this.resources.set(fields[0], RedirectEntry.fromFields(fields[1], fields.slice(2)));
|
||||
warResolve(fields[0]);
|
||||
|
||||
fields = undefined;
|
||||
}
|
||||
|
@ -508,13 +473,14 @@ RedirectEngine.prototype.resourcesFromString = function(text) {
|
|||
// Process pending resource data.
|
||||
if ( fields !== undefined ) {
|
||||
this.resources.set(fields[0], RedirectEntry.fromFields(fields[1], fields.slice(2)));
|
||||
warResolve(fields[0]);
|
||||
}
|
||||
|
||||
warResolve();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var resourcesSelfieVersion = 1;
|
||||
var resourcesSelfieVersion = 2;
|
||||
|
||||
RedirectEngine.prototype.selfieFromResources = function() {
|
||||
vAPI.cacheStorage.set({
|
||||
|
|
11
src/web_accessible_resources/README.txt
Normal file
11
src/web_accessible_resources/README.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
IMPORTANT
|
||||
|
||||
Content of this folder cannot be accessed without the internal secret token
|
||||
created each time uBlock Origin launched.
|
||||
|
||||
Any fetch operation made without uBlock Origin's internal secret will result
|
||||
in failure. This means that despite the content of the folder here declared as
|
||||
"web accessible resources", it still cannot be seen by the outside world.
|
||||
|
||||
Only uBlock Origin knows the secret token at runtime and hence only
|
||||
uBlock Origin can see the content of this folder.
|
7
src/web_accessible_resources/imported.txt
Normal file
7
src/web_accessible_resources/imported.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
# List of resources imported as "web accessible resources".
|
||||
#
|
||||
# To ensure valid filename characters on any platform OS, the filenames are
|
||||
# constructed using the md5 hash of the respective tokens.
|
||||
#
|
||||
# DO NOT REMOVE THIS LINE >>>>>
|
||||
|
|
@ -11,9 +11,8 @@
|
|||
# page to use one of these "web accessible resource" to directly
|
||||
# detect the presence of uBO.
|
||||
#
|
||||
# To ensure valid filename on any platform OS, the resource tokens are
|
||||
# converted to base64 (https://tools.ietf.org/html/rfc7515#appendix-C),
|
||||
# and the result is used as filename.
|
||||
# To ensure valid filename characters on any platform OS, the filenames are
|
||||
# constructed using the md5 hash of the respective tokens.
|
||||
#
|
||||
# In case uBO redirects to a resource which has not been converted into
|
||||
# a "web accessible resource", the redirection code will fall back to
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
@ -19,6 +20,8 @@ with open('./src/web_accessible_resources/to-import.txt', 'r') as f:
|
|||
if len(line) != 0 and line[0] != '#':
|
||||
to_import.add(line)
|
||||
|
||||
imported = []
|
||||
|
||||
# scan the file until a resource to import is found
|
||||
def find_next_resource(f):
|
||||
for line in f:
|
||||
|
@ -31,7 +34,9 @@ def find_next_resource(f):
|
|||
return ('', '')
|
||||
|
||||
def safe_filename_from_token(token, mime):
|
||||
name = str(base64.b64encode(bytes(token, 'utf-8'), b'-_'), 'utf-8').strip('=')
|
||||
h = hashlib.md5()
|
||||
h.update(bytes(token, 'utf-8'))
|
||||
name = h.hexdigest()
|
||||
# extract file extension from mime
|
||||
match = re.search('^[^/]+/([^\s;]+)', mime)
|
||||
if match:
|
||||
|
@ -58,6 +63,7 @@ def import_resource(f, token, mime):
|
|||
filedata = bytes(filedata, 'utf-8')
|
||||
with open(filepath, 'wb') as fo:
|
||||
fo.write(filedata)
|
||||
imported.append(token + '\n\t' + filename)
|
||||
|
||||
# Read content of the resources to convert
|
||||
# - At this point, it is assumed resources.txt has been imported into the
|
||||
|
@ -70,3 +76,11 @@ with open(resources_filename, 'r') as f:
|
|||
break
|
||||
import_resource(f, token, mime)
|
||||
|
||||
# Output associations
|
||||
content = ''
|
||||
with open('./src/web_accessible_resources/imported.txt', 'r') as f:
|
||||
content = f.read() + '\n'.join(imported)
|
||||
filename = os.path.join(build_dir, 'web_accessible_resources/imported.txt')
|
||||
with open(filename, 'w') as f:
|
||||
f.write(content)
|
||||
|
||||
|
|
Loading…
Reference in a new issue