mirror of https://github.com/gorhill/uBlock.git
Refactor management of injectable resources
This is a first step, the ultimate goal is to remove the need for resources.txt, or at least to reduce to only hotfixes or for trivial resources targeting very specific websites. Most resources will become immutable, i.e. they will be part of uBO's code base. Advantages include easier code maintenance (jshint, syntax highlight), and to make scriptlets more easy to code review by external parties (for example extension store reviewers). TODO: - More scriptlets need to be imported before next release. - Need to make legacy versions of uBO use a legacy version of resources.txt, as all the now obsolete scriptlets will have to be removed once uBO's next release become widespread. - Possibly need to add code to load binary resources so that they can be injected as data: URI. So far it's unclear whether this is really needed. For example, this would be needed if a xmlhttprequest is redirected to an image resource.
This commit is contained in:
parent
41636c59fb
commit
152cea2dfe
|
@ -23,52 +23,166 @@
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.redirectEngine = (function(){
|
||||
µBlock.redirectEngine = (( ) => {
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
const warResolve = (function() {
|
||||
let warPairs = [];
|
||||
const immutableResources = new Map([
|
||||
[ '1x1.gif', {
|
||||
alias: '1x1-transparent.gif',
|
||||
inject: false
|
||||
} ],
|
||||
[ '2x2.png', {
|
||||
alias: '2x2-transparent.png',
|
||||
inject: false
|
||||
} ],
|
||||
[ '3x2.png', {
|
||||
alias: '3x2-transparent.png',
|
||||
inject: false
|
||||
} ],
|
||||
[ '32x32.png', {
|
||||
alias: '32x32-transparent.png',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'abort-current-inline-script.js', {
|
||||
alias: 'acis.js',
|
||||
redirect: false
|
||||
} ],
|
||||
[ 'abort-on-property-read.js', {
|
||||
alias: 'aopr.js',
|
||||
redirect: false
|
||||
} ],
|
||||
[ 'abort-on-property-write.js', {
|
||||
alias: 'aopw.js',
|
||||
redirect: false
|
||||
} ],
|
||||
[ 'addthis_widget.js', {
|
||||
alias: 'addthis.com/addthis_widget.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'ampproject_v0.js', {
|
||||
alias: 'ampproject.org/v0.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'chartbeat.js', {
|
||||
alias: 'static.chartbeat.com/chartbeat.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'amazon_ads.js', {
|
||||
alias: 'amazon-adsystem.com/aax2/amzn_ads.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'disqus_embed.js', {
|
||||
alias: 'disqus.com/embed.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'disqus_forums_embed.js', {
|
||||
alias: 'disqus.com/forums/*/embed.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'doubleclick_instream_ad_status.js', {
|
||||
alias: 'doubleclick.net/instream/ad_status.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'fookadblock.js', {
|
||||
alias: 'fuckadblock.js-3.2.0',
|
||||
} ],
|
||||
[ 'google-analytics_analytics.js', {
|
||||
alias: 'google-analytics.com/analytics.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'google-analytics_cx_api.js', {
|
||||
alias: 'google-analytics.com/cx/api.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'google-analytics_ga.js', {
|
||||
alias: 'google-analytics.com/ga.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'google-analytics_inpage_linkid.js', {
|
||||
alias: 'google-analytics.com/inpage_linkid.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'googlesyndication_adsbygoogle.js', {
|
||||
alias: 'googlesyndication.com/adsbygoogle.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'googletagmanager_gtm.js', {
|
||||
alias: 'googletagmanager.com/gtm.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'googletagservices_gpt.js', {
|
||||
alias: 'googletagservices.com/gpt.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'hd-main.js', {
|
||||
inject: false
|
||||
} ],
|
||||
[ 'ligatus_angular-tag.js', {
|
||||
alias: 'ligatus.com/*/angular-tag.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'monkeybroker.js', {
|
||||
alias: 'd3pkae9owd2lcf.cloudfront.net/mb105.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'noeval-silent.js', {
|
||||
alias: 'silent-noeval.js',
|
||||
} ],
|
||||
[ 'noop-0.1s.mp3', {
|
||||
alias: 'noopmp3-0.1s',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'noop-1s.mp4', {
|
||||
alias: 'noopmp4-1s',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'noop.html', {
|
||||
alias: 'noopframe',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'noop.js', {
|
||||
alias: 'noopjs',
|
||||
} ],
|
||||
[ 'noop.txt', {
|
||||
alias: 'nooptext',
|
||||
} ],
|
||||
[ 'outbrain-widget.js', {
|
||||
alias: 'widgets.outbrain.com/outbrain.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'popads.js', {
|
||||
alias: 'popads.net.js',
|
||||
} ],
|
||||
[ 'popads-dummy.js', {
|
||||
alias: 'popads-dummy.js',
|
||||
} ],
|
||||
[ 'scorecardresearch_beacon.js', {
|
||||
alias: 'scorecardresearch.com/beacon.js',
|
||||
inject: false
|
||||
} ],
|
||||
[ 'set-constant.js', {
|
||||
redirect: false
|
||||
} ],
|
||||
[ 'setTimeout-defuser.js', {
|
||||
alias: 'stod.js',
|
||||
redirect: false
|
||||
} ],
|
||||
[ 'webrtc-if.js', {
|
||||
redirect: false
|
||||
} ],
|
||||
]);
|
||||
|
||||
const onPairsReady = function() {
|
||||
const reng = µBlock.redirectEngine;
|
||||
for ( let i = 0; i < warPairs.length; i += 2 ) {
|
||||
const resource = reng.resources.get(warPairs[i+0]);
|
||||
if ( resource === undefined ) { continue; }
|
||||
resource.warURL = vAPI.getURL(
|
||||
'/web_accessible_resources/' + warPairs[i+1]
|
||||
);
|
||||
}
|
||||
reng.selfieFromResources();
|
||||
};
|
||||
|
||||
return function() {
|
||||
if ( vAPI.warSecret === undefined || warPairs.length !== 0 ) {
|
||||
return onPairsReady();
|
||||
}
|
||||
|
||||
const onPairsLoaded = function(details) {
|
||||
const marker = '>>>>>';
|
||||
const pos = details.content.indexOf(marker);
|
||||
if ( pos === -1 ) { return; }
|
||||
const pairs = details.content.slice(pos + marker.length)
|
||||
.trim()
|
||||
.split('\n');
|
||||
if ( (pairs.length & 1) !== 0 ) { return; }
|
||||
for ( let i = 0; i < pairs.length; i++ ) {
|
||||
pairs[i] = pairs[i].trim();
|
||||
}
|
||||
warPairs = pairs;
|
||||
onPairsReady();
|
||||
};
|
||||
|
||||
µBlock.assets.fetchText(
|
||||
`/web_accessible_resources/imported.txt${vAPI.warSecret()}`,
|
||||
onPairsLoaded
|
||||
);
|
||||
};
|
||||
})();
|
||||
const mimeMap = {
|
||||
gif: 'image/gif',
|
||||
html: 'text/html',
|
||||
js: 'application/javascript',
|
||||
mp3: 'audio/mp3',
|
||||
mp4: 'video/mp4',
|
||||
png: 'image/png',
|
||||
txt: 'text/plain',
|
||||
};
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/3639
|
||||
// https://github.com/EFForg/https-everywhere/issues/14961
|
||||
|
@ -107,6 +221,7 @@ RedirectEntry.prototype.toURL = function(fctxt) {
|
|||
) {
|
||||
return `${this.warURL}${vAPI.warSecret()}`;
|
||||
}
|
||||
if ( this.data === undefined ) { return; }
|
||||
if ( this.data.startsWith('data:') === false ) {
|
||||
if ( this.mime.indexOf(';') === -1 ) {
|
||||
this.data = 'data:' + this.mime + ';base64,' + btoa(this.data);
|
||||
|
@ -134,9 +249,11 @@ RedirectEntry.prototype.toContent = function() {
|
|||
/******************************************************************************/
|
||||
|
||||
RedirectEntry.fromFields = function(mime, lines) {
|
||||
var r = new RedirectEntry();
|
||||
const r = new RedirectEntry();
|
||||
r.mime = mime;
|
||||
r.data = lines.join(mime.indexOf(';') !== -1 ? '' : '\n');
|
||||
r.data = µBlock.orphanizeString(
|
||||
lines.join(mime.indexOf(';') !== -1 ? '' : '\n')
|
||||
);
|
||||
return r;
|
||||
};
|
||||
|
||||
|
@ -474,12 +591,13 @@ RedirectEngine.prototype.resourceContentFromName = function(name, mime) {
|
|||
// https://github.com/uBlockOrigin/uAssets/commit/deefe875551197d655f79cb540e62dfc17c95f42
|
||||
// Consider 'none' a reserved keyword, to be used to disable redirection.
|
||||
|
||||
RedirectEngine.prototype.resourcesFromString = function(text) {
|
||||
let fields, encoded,
|
||||
reNonEmptyLine = /\S/,
|
||||
lineIter = new µBlock.LineIterator(text);
|
||||
|
||||
this.resources = new Map();
|
||||
RedirectEngine.prototype.resourcesFromString = function(
|
||||
text,
|
||||
override = true
|
||||
) {
|
||||
const lineIter = new µBlock.LineIterator(text);
|
||||
const reNonEmptyLine = /\S/;
|
||||
let fields, encoded;
|
||||
|
||||
while ( lineIter.eot() === false ) {
|
||||
let line = lineIter.next();
|
||||
|
@ -500,10 +618,15 @@ RedirectEngine.prototype.resourcesFromString = function(text) {
|
|||
}
|
||||
|
||||
// No more data, add the resource.
|
||||
this.resources.set(
|
||||
fields[0],
|
||||
RedirectEntry.fromFields(fields[1], fields.slice(2))
|
||||
);
|
||||
if (
|
||||
this.resources.has(fields[0]) === false ||
|
||||
override !== false
|
||||
) {
|
||||
this.resources.set(
|
||||
fields[0],
|
||||
RedirectEntry.fromFields(fields[1], fields.slice(2))
|
||||
);
|
||||
}
|
||||
|
||||
fields = undefined;
|
||||
}
|
||||
|
@ -516,13 +639,71 @@ RedirectEngine.prototype.resourcesFromString = function(text) {
|
|||
);
|
||||
}
|
||||
|
||||
warResolve();
|
||||
|
||||
this.modifyTime = Date.now();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
RedirectEngine.prototype.loadBuiltinResources = function() {
|
||||
this.resources = new Map();
|
||||
const mimeFromName = function(name) {
|
||||
const match = /\.([^.]+)$/.exec(name);
|
||||
if ( match !== null ) {
|
||||
return mimeMap[match[1]];
|
||||
}
|
||||
};
|
||||
const fetches = [
|
||||
µBlock.assets.get('ublock-resources'),
|
||||
];
|
||||
for ( const [ name, details ] of immutableResources ) {
|
||||
if ( details.inject !== false ) {
|
||||
fetches.push(
|
||||
µBlock.assets.fetchText(
|
||||
`/web_accessible_resources/${name}${vAPI.warSecret()}`
|
||||
)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
const entry = RedirectEntry.fromSelfie({
|
||||
mime: mimeFromName(name),
|
||||
warURL: vAPI.getURL(`/web_accessible_resources/${name}`),
|
||||
});
|
||||
this.resources.set(name, entry);
|
||||
if ( details.alias !== undefined ) {
|
||||
this.resources.set(details.alias, entry);
|
||||
}
|
||||
}
|
||||
return Promise.all(fetches).then(results => {
|
||||
// Immutable resources
|
||||
for ( let i = 1; i < results.length; i++ ) {
|
||||
const result = results[i];
|
||||
const match = /^\/web_accessible_resources\/([^?]+)/.exec(result.url);
|
||||
if ( match === null ) { continue; }
|
||||
const name = match[1];
|
||||
const content = result.content.replace(/^\/\*[\S\s]+?\*\/\s*/, '');
|
||||
const details = immutableResources.get(name);
|
||||
const entry = RedirectEntry.fromSelfie({
|
||||
mime: mimeFromName(name),
|
||||
data: content,
|
||||
warURL: details.redirect !== false
|
||||
? vAPI.getURL(`/web_accessible_resources/${name}`)
|
||||
: undefined,
|
||||
});
|
||||
this.resources.set(name, entry);
|
||||
if ( details.alias !== undefined ) {
|
||||
this.resources.set(details.alias, entry);
|
||||
}
|
||||
}
|
||||
// Mutable resources
|
||||
const content = results[0].content;
|
||||
if ( typeof content === 'string' && content.length !== 0 ) {
|
||||
this.resourcesFromString(content, false);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const resourcesSelfieVersion = 3;
|
||||
|
||||
RedirectEngine.prototype.selfieFromResources = function() {
|
||||
|
|
|
@ -177,15 +177,9 @@ const onCommandShortcutsReady = function(commandShortcuts) {
|
|||
const onVersionReady = function(lastVersion) {
|
||||
if ( lastVersion === vAPI.app.version ) { return; }
|
||||
|
||||
// Since AMO does not allow updating resources.txt, force a reload when a
|
||||
// new version is detected, as resources.txt may have changed since last
|
||||
// release. This will be done only for release versions of Firefox.
|
||||
if (
|
||||
vAPI.webextFlavor.soup.has('firefox') &&
|
||||
vAPI.webextFlavor.soup.has('devbuild') === false
|
||||
) {
|
||||
µb.redirectEngine.invalidateResourcesSelfie();
|
||||
}
|
||||
// Since built-in resources may have changed since last version, we
|
||||
// force a reload of all resources.
|
||||
µb.redirectEngine.invalidateResourcesSelfie();
|
||||
|
||||
// If unused, just comment out for when we need to compare versions in the
|
||||
// future.
|
||||
|
@ -320,7 +314,6 @@ const onFirstFetchReady = function(fetched) {
|
|||
µb.loadPublicSuffixList().then(( ) => {
|
||||
onPSLReady();
|
||||
});
|
||||
µb.loadRedirectResources();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -987,9 +987,11 @@
|
|||
|
||||
µBlock.loadRedirectResources = function() {
|
||||
return this.redirectEngine.resourcesFromSelfie().then(success => {
|
||||
if ( success === true ) { return; }
|
||||
if ( success === true ) { return true; }
|
||||
|
||||
const fetchPromises = [ this.assets.get('ublock-resources') ];
|
||||
const fetchPromises = [
|
||||
this.redirectEngine.loadBuiltinResources()
|
||||
];
|
||||
|
||||
const userResourcesLocation = this.hiddenSettings.userResourcesLocation;
|
||||
if ( userResourcesLocation !== 'unset' ) {
|
||||
|
@ -1000,11 +1002,11 @@
|
|||
|
||||
return Promise.all(fetchPromises);
|
||||
}).then(results => {
|
||||
if ( Array.isArray(results) === false ) { return; }
|
||||
if ( Array.isArray(results) === false ) { return results; }
|
||||
|
||||
let content = '';
|
||||
|
||||
for ( const result of results ) {
|
||||
for ( let i = 1; i < results.length; i++ ) {
|
||||
const result = results[i];
|
||||
if (
|
||||
result instanceof Object === false ||
|
||||
typeof result.content !== 'string' ||
|
||||
|
@ -1016,6 +1018,11 @@
|
|||
}
|
||||
|
||||
this.redirectEngine.resourcesFromString(content);
|
||||
this.redirectEngine.selfieFromResources();
|
||||
return true;
|
||||
}).catch(reason => {
|
||||
log.info(reason);
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1109,9 +1116,12 @@
|
|||
µb.redirectEngine.fromSelfie('selfie/redirectEngine'),
|
||||
µb.staticExtFilteringEngine.fromSelfie('selfie/staticExtFilteringEngine'),
|
||||
µb.staticNetFilteringEngine.fromSelfie('selfie/staticNetFilteringEngine'),
|
||||
]).then(results =>
|
||||
results.reduce((acc, v) => acc && v, true)
|
||||
).catch(reason => {
|
||||
]).then(results => {
|
||||
if ( results.reduce((acc, v) => acc && v, true) ) {
|
||||
return µb.loadRedirectResources();
|
||||
}
|
||||
return false;
|
||||
}).catch(reason => {
|
||||
log.info(reason);
|
||||
return false;
|
||||
});
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 43 B |
Binary file not shown.
After Width: | Height: | Size: 68 B |
Binary file not shown.
After Width: | Height: | Size: 83 B |
Binary file not shown.
After Width: | Height: | Size: 68 B |
|
@ -0,0 +1,79 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const target = '{{1}}';
|
||||
if ( target === '' || target === '{{1}}' ) { return; }
|
||||
const needle = '{{2}}';
|
||||
let reText = '.?';
|
||||
if ( needle !== '' && needle !== '{{2}}' ) {
|
||||
reText = /^\/.+\/$/.test(needle)
|
||||
? needle.slice(1,-1)
|
||||
: needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
const thisScript = document.currentScript;
|
||||
const re = new RegExp(reText);
|
||||
const chain = target.split('.');
|
||||
let owner = window;
|
||||
let prop;
|
||||
for (;;) {
|
||||
prop = chain.shift();
|
||||
if ( chain.length === 0 ) { break; }
|
||||
owner = owner[prop];
|
||||
if ( owner instanceof Object === false ) { return; }
|
||||
}
|
||||
const desc = Object.getOwnPropertyDescriptor(owner, prop);
|
||||
if ( desc && desc.get !== undefined ) { return; }
|
||||
const magic = String.fromCharCode(Date.now() % 26 + 97) +
|
||||
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
|
||||
let value = owner[prop];
|
||||
const validate = function() {
|
||||
const e = document.currentScript;
|
||||
if (
|
||||
e instanceof HTMLScriptElement &&
|
||||
e.src === '' &&
|
||||
e !== thisScript &&
|
||||
re.test(e.textContent)
|
||||
) {
|
||||
throw new ReferenceError(magic);
|
||||
}
|
||||
};
|
||||
Object.defineProperty(owner, prop, {
|
||||
get: function() {
|
||||
validate();
|
||||
return value;
|
||||
},
|
||||
set: function(a) {
|
||||
validate();
|
||||
value = a;
|
||||
}
|
||||
});
|
||||
const oe = window.onerror;
|
||||
window.onerror = function(msg) {
|
||||
if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
|
||||
return true;
|
||||
}
|
||||
if ( oe instanceof Function ) {
|
||||
return oe.apply(this, arguments);
|
||||
}
|
||||
}.bind();
|
||||
})();
|
|
@ -0,0 +1,72 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const magic = String.fromCharCode(Date.now() % 26 + 97) +
|
||||
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
|
||||
const abort = function() {
|
||||
throw new ReferenceError(magic);
|
||||
};
|
||||
const makeProxy = function(owner, chain) {
|
||||
const pos = chain.indexOf('.');
|
||||
if ( pos === -1 ) {
|
||||
const desc = Object.getOwnPropertyDescriptor(owner, chain);
|
||||
if ( !desc || desc.get !== abort ) {
|
||||
Object.defineProperty(owner, chain, {
|
||||
get: abort,
|
||||
set: function(){}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
const prop = chain.slice(0, pos);
|
||||
let v = owner[prop];
|
||||
chain = chain.slice(pos + 1);
|
||||
if ( v ) {
|
||||
makeProxy(v, chain);
|
||||
return;
|
||||
}
|
||||
const desc = Object.getOwnPropertyDescriptor(owner, prop);
|
||||
if ( desc && desc.set !== undefined ) { return; }
|
||||
Object.defineProperty(owner, prop, {
|
||||
get: function() { return v; },
|
||||
set: function(a) {
|
||||
v = a;
|
||||
if ( a instanceof Object ) {
|
||||
makeProxy(a, chain);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
const owner = window;
|
||||
let chain = '{{1}}';
|
||||
makeProxy(owner, chain);
|
||||
const oe = window.onerror;
|
||||
window.onerror = function(msg, src, line, col, error) {
|
||||
if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
|
||||
return true;
|
||||
}
|
||||
if ( oe instanceof Function ) {
|
||||
return oe(msg, src, line, col, error);
|
||||
}
|
||||
}.bind();
|
||||
})();
|
|
@ -0,0 +1,50 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const magic = String.fromCharCode(Date.now() % 26 + 97) +
|
||||
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
|
||||
let prop = '{{1}}';
|
||||
let owner = window;
|
||||
for (;;) {
|
||||
const pos = prop.indexOf('.');
|
||||
if ( pos === -1 ) { break; }
|
||||
owner = owner[prop.slice(0, pos)];
|
||||
if ( owner instanceof Object === false ) { return; }
|
||||
prop = prop.slice(pos + 1);
|
||||
}
|
||||
delete owner[prop];
|
||||
Object.defineProperty(owner, prop, {
|
||||
set: function() {
|
||||
throw new ReferenceError(magic);
|
||||
}
|
||||
});
|
||||
const oe = window.onerror;
|
||||
window.onerror = function(msg, src, line, col, error) {
|
||||
if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
|
||||
return true;
|
||||
}
|
||||
if ( oe instanceof Function ) {
|
||||
return oe(msg, src, line, col, error);
|
||||
}
|
||||
}.bind();
|
||||
})();
|
|
@ -0,0 +1,38 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const noopfn = function() {
|
||||
};
|
||||
window.addthis = {
|
||||
addEventListener: noopfn,
|
||||
button: noopfn,
|
||||
init: noopfn,
|
||||
layers: noopfn,
|
||||
ready: noopfn,
|
||||
sharecounters: {
|
||||
getShareCounts: noopfn
|
||||
},
|
||||
toolbox: noopfn,
|
||||
update: noopfn
|
||||
};
|
||||
})();
|
|
@ -0,0 +1,70 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
if ( amznads ) {
|
||||
return;
|
||||
}
|
||||
var w = window;
|
||||
var noopfn = function() {
|
||||
;
|
||||
}.bind();
|
||||
var amznads = {
|
||||
appendScriptTag: noopfn,
|
||||
appendTargetingToAdServerUrl: noopfn,
|
||||
appendTargetingToQueryString: noopfn,
|
||||
clearTargetingFromGPTAsync: noopfn,
|
||||
doAllTasks: noopfn,
|
||||
doGetAdsAsync: noopfn,
|
||||
doTask: noopfn,
|
||||
detectIframeAndGetURL: noopfn,
|
||||
getAds: noopfn,
|
||||
getAdsAsync: noopfn,
|
||||
getAdForSlot: noopfn,
|
||||
getAdsCallback: noopfn,
|
||||
getDisplayAds: noopfn,
|
||||
getDisplayAdsAsync: noopfn,
|
||||
getDisplayAdsCallback: noopfn,
|
||||
getKeys: noopfn,
|
||||
getReferrerURL: noopfn,
|
||||
getScriptSource: noopfn,
|
||||
getTargeting: noopfn,
|
||||
getTokens: noopfn,
|
||||
getValidMilliseconds: noopfn,
|
||||
getVideoAds: noopfn,
|
||||
getVideoAdsAsync: noopfn,
|
||||
getVideoAdsCallback: noopfn,
|
||||
handleCallBack: noopfn,
|
||||
hasAds: noopfn,
|
||||
renderAd: noopfn,
|
||||
saveAds: noopfn,
|
||||
setTargeting: noopfn,
|
||||
setTargetingForGPTAsync: noopfn,
|
||||
setTargetingForGPTSync: noopfn,
|
||||
tryGetAdsAsync: noopfn,
|
||||
updateAds: noopfn
|
||||
};
|
||||
w.amznads = amznads;
|
||||
w.amzn_ads = w.amzn_ads || noopfn;
|
||||
w.aax_write = w.aax_write || noopfn;
|
||||
w.aax_render_ad = w.aax_render_ad || noopfn;
|
||||
})();
|
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const head = document.head;
|
||||
if ( !head ) { return; }
|
||||
const style = document.createElement('style');
|
||||
style.textContent = [
|
||||
'body {',
|
||||
' animation: none !important;',
|
||||
' overflow: unset !important;',
|
||||
'}'
|
||||
].join('\n');
|
||||
head.appendChild(style);
|
||||
})();
|
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const noopfn = function() {
|
||||
};
|
||||
window.pSUPERFLY = {
|
||||
activity: noopfn,
|
||||
virtualPage: noopfn
|
||||
};
|
||||
})();
|
|
@ -0,0 +1,42 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const p = document.getElementById(window.disqus_container_id || 'disqus_thread');
|
||||
if ( p === null ) { return; }
|
||||
const b = document.createElement('button');
|
||||
b.textContent = 'Disqus blocked by uBlock Origin: click to unblock';
|
||||
b.type = 'button';
|
||||
p.appendChild(b);
|
||||
const loadDisqus = function(ev) {
|
||||
b.removeEventListener('click', loadDisqus);
|
||||
p.removeChild(b);
|
||||
const script = document.createElement('script');
|
||||
script.async = true;
|
||||
const t = Date.now().toString();
|
||||
script.src = '//' + window.disqus_shortname + '.disqus.com/embed.js?_=1457540' + t.slice(-6);
|
||||
document.body.appendChild(script);
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
};
|
||||
b.addEventListener('click', loadDisqus);
|
||||
})();
|
|
@ -0,0 +1,52 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
|
||||
Completely experimental: load Disqus on demand only. Purpose is to avoid
|
||||
connecting to Disqus' servers, unless the user explicitly asks for the
|
||||
comments to be loaded.
|
||||
Works with following filters:
|
||||
||disqus.com/forums/*embed.js$script,redirect=disqus.com/forums/*embed.js
|
||||
||disqus.com/embed.js$script,redirect=disqus.com/embed.js
|
||||
||disqus.com/count.js$script
|
||||
@@||disqus.com/embed.js?_=1457540*$script
|
||||
If you want a site you regularly visit to always have the comment loaded,
|
||||
just use an exception static filter. Example for wired.com:
|
||||
@@||wired.disqus.com/embed.js
|
||||
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const ee = document.getElementsByTagName('script');
|
||||
let i = ee.length, src;
|
||||
while ( i-- ) {
|
||||
src = ee[i].src || '';
|
||||
if ( src === '' ) {
|
||||
continue;
|
||||
}
|
||||
if ( src.lastIndexOf('disqus.com/embed.js') === (src.length - 19) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const e = document.createElement('script');
|
||||
e.async = true;
|
||||
e.src = '//' + window.disqus_shortname + '.disqus.com/embed.js';
|
||||
document.body.appendChild(e);
|
||||
})();
|
|
@ -0,0 +1 @@
|
|||
window.google_ad_status = 1;
|
|
@ -0,0 +1,63 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const noopfn = function() {
|
||||
};
|
||||
const Fab = function() {};
|
||||
Fab.prototype.check = noopfn;
|
||||
Fab.prototype.clearEvent = noopfn;
|
||||
Fab.prototype.emitEvent = noopfn;
|
||||
Fab.prototype.on = function(a, b) {
|
||||
if ( !a ) { b(); }
|
||||
return this;
|
||||
};
|
||||
Fab.prototype.onDetected = function() {
|
||||
return this;
|
||||
};
|
||||
Fab.prototype.onNotDetected = function(a) {
|
||||
a();
|
||||
return this;
|
||||
};
|
||||
Fab.prototype.setOption = noopfn;
|
||||
const fab = new Fab(),
|
||||
getSetFab = {
|
||||
get: function() { return Fab; },
|
||||
set: function() {}
|
||||
},
|
||||
getsetfab = {
|
||||
get: function() { return fab; },
|
||||
set: function() {}
|
||||
};
|
||||
if ( window.hasOwnProperty('FuckAdBlock') ) { window.FuckAdBlock = Fab; }
|
||||
else { Object.defineProperty(window, 'FuckAdBlock', getSetFab); }
|
||||
if ( window.hasOwnProperty('BlockAdBlock') ) { window.BlockAdBlock = Fab; }
|
||||
else { Object.defineProperty(window, 'BlockAdBlock', getSetFab); }
|
||||
if ( window.hasOwnProperty('SniffAdBlock') ) { window.SniffAdBlock = Fab; }
|
||||
else { Object.defineProperty(window, 'SniffAdBlock', getSetFab); }
|
||||
if ( window.hasOwnProperty('fuckAdBlock') ) { window.fuckAdBlock = fab; }
|
||||
else { Object.defineProperty(window, 'fuckAdBlock', getsetfab); }
|
||||
if ( window.hasOwnProperty('blockAdBlock') ) { window.blockAdBlock = fab; }
|
||||
else { Object.defineProperty(window, 'blockAdBlock', getsetfab); }
|
||||
if ( window.hasOwnProperty('sniffAdBlock') ) { window.sniffAdBlock = fab; }
|
||||
else { Object.defineProperty(window, 'sniffAdBlock', getsetfab); }
|
||||
})();
|
|
@ -0,0 +1,70 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
// https://developers.google.com/analytics/devguides/collection/analyticsjs/
|
||||
const noopfn = function() {
|
||||
};
|
||||
const noopnullfn = function() {
|
||||
return null;
|
||||
};
|
||||
//
|
||||
const Tracker = function() {
|
||||
};
|
||||
const p = Tracker.prototype;
|
||||
p.get = noopfn;
|
||||
p.set = noopfn;
|
||||
p.send = noopfn;
|
||||
//
|
||||
const w = window;
|
||||
const gaName = w.GoogleAnalyticsObject || 'ga';
|
||||
const ga = function() {
|
||||
var len = arguments.length;
|
||||
if ( len === 0 ) {
|
||||
return;
|
||||
}
|
||||
var f = arguments[len-1];
|
||||
if ( typeof f !== 'object' || f === null || typeof f.hitCallback !== 'function' ) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
f.hitCallback();
|
||||
} catch (ex) {
|
||||
}
|
||||
};
|
||||
ga.create = function() {
|
||||
return new Tracker();
|
||||
};
|
||||
ga.getByName = noopnullfn;
|
||||
ga.getAll = function() {
|
||||
return [];
|
||||
};
|
||||
ga.remove = noopfn;
|
||||
// https://github.com/uBlockOrigin/uAssets/issues/2107
|
||||
ga.loaded = true;
|
||||
w[gaName] = ga;
|
||||
// https://github.com/gorhill/uBlock/issues/3075
|
||||
const dl = w.dataLayer;
|
||||
if ( dl instanceof Object && dl.hide instanceof Object && typeof dl.hide.end === 'function' ) {
|
||||
dl.hide.end();
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,36 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const noopfn = function() {
|
||||
};
|
||||
window.cxApi = {
|
||||
chooseVariation: function() {
|
||||
return 0;
|
||||
},
|
||||
getChosenVariation: noopfn,
|
||||
setAllowHash: noopfn,
|
||||
setChosenVariation: noopfn,
|
||||
setCookiePath: noopfn,
|
||||
setDomainName: noopfn
|
||||
};
|
||||
})();
|
|
@ -0,0 +1,118 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const noopfn = function() {
|
||||
};
|
||||
//
|
||||
const Gaq = function() {
|
||||
};
|
||||
Gaq.prototype.Na = noopfn;
|
||||
Gaq.prototype.O = noopfn;
|
||||
Gaq.prototype.Sa = noopfn;
|
||||
Gaq.prototype.Ta = noopfn;
|
||||
Gaq.prototype.Va = noopfn;
|
||||
Gaq.prototype._createAsyncTracker = noopfn;
|
||||
Gaq.prototype._getAsyncTracker = noopfn;
|
||||
Gaq.prototype._getPlugin = noopfn;
|
||||
Gaq.prototype.push = function(a) {
|
||||
if ( typeof a === 'function' ) {
|
||||
a(); return;
|
||||
}
|
||||
if ( Array.isArray(a) === false ) {
|
||||
return;
|
||||
}
|
||||
// https://twitter.com/catovitch/status/776442930345218048
|
||||
// https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiDomainDirectory#_gat.GA_Tracker_._link
|
||||
if ( a[0] === '_link' && typeof a[1] === 'string' ) {
|
||||
window.location.assign(a[1]);
|
||||
}
|
||||
// https://github.com/gorhill/uBlock/issues/2162
|
||||
if ( a[0] === '_set' && a[1] === 'hitCallback' && typeof a[2] === 'function' ) {
|
||||
a[2]();
|
||||
}
|
||||
};
|
||||
//
|
||||
const tracker = (function() {
|
||||
const out = {};
|
||||
const api = [
|
||||
'_addIgnoredOrganic _addIgnoredRef _addItem _addOrganic',
|
||||
'_addTrans _clearIgnoredOrganic _clearIgnoredRef _clearOrganic',
|
||||
'_cookiePathCopy _deleteCustomVar _getName _setAccount',
|
||||
'_getAccount _getClientInfo _getDetectFlash _getDetectTitle',
|
||||
'_getLinkerUrl _getLocalGifPath _getServiceMode _getVersion',
|
||||
'_getVisitorCustomVar _initData _link _linkByPost',
|
||||
'_setAllowAnchor _setAllowHash _setAllowLinker _setCampContentKey',
|
||||
'_setCampMediumKey _setCampNameKey _setCampNOKey _setCampSourceKey',
|
||||
'_setCampTermKey _setCampaignCookieTimeout _setCampaignTrack _setClientInfo',
|
||||
'_setCookiePath _setCookiePersistence _setCookieTimeout _setCustomVar',
|
||||
'_setDetectFlash _setDetectTitle _setDomainName _setLocalGifPath',
|
||||
'_setLocalRemoteServerMode _setLocalServerMode _setReferrerOverride _setRemoteServerMode',
|
||||
'_setSampleRate _setSessionTimeout _setSiteSpeedSampleRate _setSessionCookieTimeout',
|
||||
'_setVar _setVisitorCookieTimeout _trackEvent _trackPageLoadTime',
|
||||
'_trackPageview _trackSocial _trackTiming _trackTrans',
|
||||
'_visitCode'
|
||||
].join(' ').split(/\s+/);
|
||||
let i = api.length;
|
||||
while ( i-- ) {
|
||||
out[api[i]] = noopfn;
|
||||
}
|
||||
out._getLinkerUrl = function(a) {
|
||||
return a;
|
||||
};
|
||||
return out;
|
||||
})();
|
||||
//
|
||||
const Gat = function() {
|
||||
};
|
||||
Gat.prototype._anonymizeIP = noopfn;
|
||||
Gat.prototype._createTracker = noopfn;
|
||||
Gat.prototype._forceSSL = noopfn;
|
||||
Gat.prototype._getPlugin = noopfn;
|
||||
Gat.prototype._getTracker = function() {
|
||||
return tracker;
|
||||
};
|
||||
Gat.prototype._getTrackerByName = function() {
|
||||
return tracker;
|
||||
};
|
||||
Gat.prototype._getTrackers = noopfn;
|
||||
Gat.prototype.aa = noopfn;
|
||||
Gat.prototype.ab = noopfn;
|
||||
Gat.prototype.hb = noopfn;
|
||||
Gat.prototype.la = noopfn;
|
||||
Gat.prototype.oa = noopfn;
|
||||
Gat.prototype.pa = noopfn;
|
||||
Gat.prototype.u = noopfn;
|
||||
const gat = new Gat();
|
||||
window._gat = gat;
|
||||
//
|
||||
const gaq = new Gaq();
|
||||
(function() {
|
||||
const aa = window._gaq || [];
|
||||
if ( Array.isArray(aa) ) {
|
||||
while ( aa[0] ) {
|
||||
gaq.push(aa.shift());
|
||||
}
|
||||
}
|
||||
})();
|
||||
window._gaq = gaq.qf = gaq;
|
||||
})();
|
|
@ -0,0 +1,28 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
window._gaq = window._gaq || {
|
||||
push: function() {
|
||||
}
|
||||
};
|
||||
})();
|
|
@ -0,0 +1,47 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
window.adsbygoogle = window.adsbygoogle || {
|
||||
length: 0,
|
||||
loaded: true,
|
||||
push: function Si() {
|
||||
/*
|
||||
client = client || google_ad_client || google_ad_client;
|
||||
slotname = slotname || google_ad_slot;
|
||||
tag_origin = tag_origin || google_tag_origin
|
||||
*/
|
||||
this.length += 1;
|
||||
}
|
||||
};
|
||||
const phs = document.querySelectorAll('.adsbygoogle');
|
||||
const css = 'height:1px!important;max-height:1px!important;max-width:1px!important;width:1px!important;';
|
||||
for ( let i = 0; i < phs.length; i++ ) {
|
||||
const fr = document.createElement('iframe');
|
||||
fr.id = 'aswift_' + (i+1);
|
||||
fr.style = css;
|
||||
const cfr = document.createElement('iframe');
|
||||
cfr.id = 'google_ads_frame' + i;
|
||||
fr.appendChild(cfr);
|
||||
document.body.appendChild(fr);
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,43 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const noopfn = function() {
|
||||
};
|
||||
const w = window;
|
||||
w.ga = w.ga || noopfn;
|
||||
const dl = w.dataLayer;
|
||||
if ( dl instanceof Object === false ) { return; }
|
||||
if ( dl.hide instanceof Object && typeof dl.hide.end === 'function' ) {
|
||||
dl.hide.end();
|
||||
}
|
||||
if ( typeof dl.push === 'function' ) {
|
||||
dl.push = function(o) {
|
||||
if (
|
||||
o instanceof Object &&
|
||||
typeof o.eventCallback === 'function'
|
||||
) {
|
||||
setTimeout(o.eventCallback, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,149 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
// https://developers.google.com/doubleclick-gpt/reference
|
||||
const noopfn = function() {
|
||||
}.bind();
|
||||
const noopthisfn = function() {
|
||||
return this;
|
||||
};
|
||||
const noopnullfn = function() {
|
||||
return null;
|
||||
};
|
||||
const nooparrayfn = function() {
|
||||
return [];
|
||||
};
|
||||
const noopstrfn = function() {
|
||||
return '';
|
||||
};
|
||||
//
|
||||
const companionAdsService = {
|
||||
addEventListener: noopthisfn,
|
||||
enableSyncLoading: noopfn,
|
||||
setRefreshUnfilledSlots: noopfn
|
||||
};
|
||||
const contentService = {
|
||||
addEventListener: noopthisfn,
|
||||
setContent: noopfn
|
||||
};
|
||||
const PassbackSlot = function() {
|
||||
};
|
||||
let p = PassbackSlot.prototype;
|
||||
p.display = noopfn;
|
||||
p.get = noopnullfn;
|
||||
p.set = noopthisfn;
|
||||
p.setClickUrl = noopthisfn;
|
||||
p.setTagForChildDirectedTreatment = noopthisfn;
|
||||
p.setTargeting = noopthisfn;
|
||||
p.updateTargetingFromMap = noopthisfn;
|
||||
const pubAdsService = {
|
||||
addEventListener: noopthisfn,
|
||||
clear: noopfn,
|
||||
clearCategoryExclusions: noopthisfn,
|
||||
clearTagForChildDirectedTreatment: noopthisfn,
|
||||
clearTargeting: noopthisfn,
|
||||
collapseEmptyDivs: noopfn,
|
||||
defineOutOfPagePassback: function() { return new PassbackSlot(); },
|
||||
definePassback: function() { return new PassbackSlot(); },
|
||||
disableInitialLoad: noopfn,
|
||||
display: noopfn,
|
||||
enableAsyncRendering: noopfn,
|
||||
enableSingleRequest: noopfn,
|
||||
enableSyncRendering: noopfn,
|
||||
enableVideoAds: noopfn,
|
||||
get: noopnullfn,
|
||||
getAttributeKeys: nooparrayfn,
|
||||
getTargeting: noopfn,
|
||||
getTargetingKeys: nooparrayfn,
|
||||
getSlots: nooparrayfn,
|
||||
refresh: noopfn,
|
||||
set: noopthisfn,
|
||||
setCategoryExclusion: noopthisfn,
|
||||
setCentering: noopfn,
|
||||
setCookieOptions: noopthisfn,
|
||||
setForceSafeFrame: noopthisfn,
|
||||
setLocation: noopthisfn,
|
||||
setPublisherProvidedId: noopthisfn,
|
||||
setRequestNonPersonalizedAds: noopthisfn,
|
||||
setSafeFrameConfig: noopthisfn,
|
||||
setTagForChildDirectedTreatment: noopthisfn,
|
||||
setTargeting: noopthisfn,
|
||||
setVideoContent: noopthisfn,
|
||||
updateCorrelator: noopfn
|
||||
};
|
||||
const SizeMappingBuilder = function() {
|
||||
};
|
||||
p = SizeMappingBuilder.prototype;
|
||||
p.addSize = noopthisfn;
|
||||
p.build = noopnullfn;
|
||||
const Slot = function() {
|
||||
};
|
||||
p = Slot.prototype;
|
||||
p.addService = noopthisfn;
|
||||
p.clearCategoryExclusions = noopthisfn;
|
||||
p.clearTargeting = noopthisfn;
|
||||
p.defineSizeMapping = noopthisfn;
|
||||
p.get = noopnullfn;
|
||||
p.getAdUnitPath = nooparrayfn;
|
||||
p.getAttributeKeys = nooparrayfn;
|
||||
p.getCategoryExclusions = nooparrayfn;
|
||||
p.getDomId = noopstrfn;
|
||||
p.getSlotElementId = noopstrfn;
|
||||
p.getSlotId = noopthisfn;
|
||||
p.getTargeting = nooparrayfn;
|
||||
p.getTargetingKeys = nooparrayfn;
|
||||
p.set = noopthisfn;
|
||||
p.setCategoryExclusion = noopthisfn;
|
||||
p.setClickUrl = noopthisfn;
|
||||
p.setCollapseEmptyDiv = noopthisfn;
|
||||
p.setTargeting = noopthisfn;
|
||||
//
|
||||
const gpt = window.googletag || {};
|
||||
const cmd = gpt.cmd || [];
|
||||
gpt.apiReady = true;
|
||||
gpt.cmd = [];
|
||||
gpt.cmd.push = function(a) {
|
||||
try {
|
||||
a();
|
||||
} catch (ex) {
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
gpt.companionAds = function() { return companionAdsService; };
|
||||
gpt.content = function() { return contentService; };
|
||||
gpt.defineOutOfPageSlot = function() { return new Slot(); };
|
||||
gpt.defineSlot = function() { return new Slot(); };
|
||||
gpt.destroySlots = noopfn;
|
||||
gpt.disablePublisherConsole = noopfn;
|
||||
gpt.display = noopfn;
|
||||
gpt.enableServices = noopfn;
|
||||
gpt.getVersion = noopstrfn;
|
||||
gpt.pubads = function() { return pubAdsService; };
|
||||
gpt.pubadsReady = true;
|
||||
gpt.setAdIframeTitle = noopfn;
|
||||
gpt.sizeMapping = function() { return new SizeMappingBuilder(); };
|
||||
window.googletag = gpt;
|
||||
while ( cmd.length !== 0 ) {
|
||||
gpt.cmd.push(cmd.shift());
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,46 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const l = {};
|
||||
const noopfn = function() {
|
||||
};
|
||||
const props = [
|
||||
"$j","Ad","Bd","Cd","Dd","Ed","Fd","Gd","Hd","Id","Jd","Nj","Oc","Pc","Pe",
|
||||
"Qc","Qe","Rc","Re","Ri","Sc","Tc","Uc","Vc","Wc","Wg","Xc","Xg","Yc","Yd",
|
||||
"ad","ae","bd","bf","cd","dd","ed","ef","ek","fd","fg","fh","fk","gd","hd",
|
||||
"ig","ij","jd","kd","ke","ld","md","mi","nd","od","oh","pd","pf","qd","rd",
|
||||
"sd","td","ud","vd","wd","wg","xd","xh","yd","zd",
|
||||
"$d","$e","$k","Ae","Af","Aj","Be","Ce","De","Ee","Ek","Eo","Ep","Fe","Fo",
|
||||
"Ge","Gh","Hk","Ie","Ip","Je","Ke","Kk","Kq","Le","Lh","Lk","Me","Mm","Ne",
|
||||
"Oe","Pe","Qe","Re","Rp","Se","Te","Ue","Ve","Vp","We","Xd","Xe","Yd","Ye",
|
||||
"Zd","Ze","Zf","Zk","ae","af","al","be","bf","bg","ce","cp","df","di","ee",
|
||||
"ef","fe","ff","gf","gm","he","hf","ie","je","jf","ke","kf","kl","le","lf",
|
||||
"lk","mf","mg","mn","nf","oe","of","pe","pf","pg","qe","qf","re","rf","se",
|
||||
"sf","te","tf","ti","ue","uf","ve","vf","we","wf","wg","wi","xe","ye","yf",
|
||||
"yk","yl","ze","zf","zk"
|
||||
];
|
||||
for ( let i = 0; i < props.length; i++ ) {
|
||||
l[props[i]] = noopfn;
|
||||
}
|
||||
window.L = window.J = l;
|
||||
})();
|
|
@ -1,10 +0,0 @@
|
|||
# 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.
|
||||
#
|
||||
# The list below was generated using the Python script located at:
|
||||
# https://github.com/gorhill/uBlock/blob/master/tools/import-war.py
|
||||
#
|
||||
# DO NOT REMOVE THIS LINE >>>>>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
self.adProtect = true;
|
||||
Object.defineProperties(window, {
|
||||
uabpdl: { value: true },
|
||||
uabDetect: { value: true }
|
||||
});
|
||||
})();
|
|
@ -0,0 +1,43 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const noopfn = function() {
|
||||
};
|
||||
window.pbjs = { libLoaded: true };
|
||||
const mb = window.MonkeyBroker || {
|
||||
addAttribute: noopfn,
|
||||
addSlot: function(a) {
|
||||
this.slots[a.slot] = {};
|
||||
},
|
||||
defineSlot: noopfn,
|
||||
fillSlot: noopfn,
|
||||
go: noopfn,
|
||||
inventoryConditionalPlacement: noopfn,
|
||||
registerSizeCallback: noopfn,
|
||||
registerSlotCallback: noopfn,
|
||||
slots: {},
|
||||
version: ''
|
||||
};
|
||||
mb.regSlotsMap = mb.slots;
|
||||
window.MonkeyBroker = mb;
|
||||
})();
|
|
@ -0,0 +1,26 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
window.eval = function() {
|
||||
}.bind(window);
|
||||
})();
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title></title></head>
|
||||
<body></body>
|
||||
</html>
|
|
@ -0,0 +1,3 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
})();
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const noopfn = function() {
|
||||
};
|
||||
const obr = {};
|
||||
const methods = [
|
||||
'callClick', 'callLoadMore', 'callRecs', 'callUserZapping',
|
||||
'callWhatIs', 'cancelRecommendation', 'cancelRecs', 'closeCard',
|
||||
'closeModal', 'closeTbx', 'errorInjectionHandler', 'getCountOfRecs',
|
||||
'getStat', 'imageError', 'manualVideoClicked', 'onOdbReturn',
|
||||
'onVideoClick', 'pagerLoad', 'recClicked', 'refreshSpecificWidget',
|
||||
'refreshWidget', 'reloadWidget', 'researchWidget', 'returnedError',
|
||||
'returnedHtmlData', 'returnedIrdData', 'returnedJsonData', 'scrollLoad',
|
||||
'showDescription', 'showRecInIframe', 'userZappingMessage', 'zappingFormAction'
|
||||
];
|
||||
obr.extern = {
|
||||
video: {
|
||||
getVideoRecs: noopfn,
|
||||
videoClicked: noopfn
|
||||
}
|
||||
};
|
||||
methods.forEach(function(a) {
|
||||
obr.extern[a] = noopfn;
|
||||
});
|
||||
window.OBR = window.OBR || obr;
|
||||
})();
|
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
delete window.PopAds;
|
||||
delete window.popns;
|
||||
Object.defineProperties(window, {
|
||||
PopAds: { value: {} },
|
||||
popns: { value: {} }
|
||||
});
|
||||
})();
|
|
@ -0,0 +1,40 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const magic = String.fromCharCode(Date.now() % 26 + 97) +
|
||||
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
|
||||
const oe = window.onerror;
|
||||
window.onerror = function(msg, src, line, col, error) {
|
||||
if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) { return true; }
|
||||
if ( oe instanceof Function ) {
|
||||
return oe(msg, src, line, col, error);
|
||||
}
|
||||
}.bind();
|
||||
const throwMagic = function() { throw magic; };
|
||||
delete window.PopAds;
|
||||
delete window.popns;
|
||||
Object.defineProperties(window, {
|
||||
PopAds: { set: throwMagic },
|
||||
popns: { set: throwMagic }
|
||||
});
|
||||
})();
|
|
@ -0,0 +1,31 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
window.COMSCORE = {
|
||||
purge: function() {
|
||||
window._comscore = [];
|
||||
},
|
||||
beacon: function() {
|
||||
}
|
||||
};
|
||||
})();
|
|
@ -0,0 +1,99 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const thisScript = document.currentScript;
|
||||
let cValue = '{{2}}';
|
||||
if ( cValue === 'undefined' ) {
|
||||
cValue = undefined;
|
||||
} else if ( cValue === 'false' ) {
|
||||
cValue = false;
|
||||
} else if ( cValue === 'true' ) {
|
||||
cValue = true;
|
||||
} else if ( cValue === 'null' ) {
|
||||
cValue = null;
|
||||
} else if ( cValue === 'noopFunc' ) {
|
||||
cValue = function(){};
|
||||
} else if ( cValue === 'trueFunc' ) {
|
||||
cValue = function(){ return true; };
|
||||
} else if ( cValue === 'falseFunc' ) {
|
||||
cValue = function(){ return false; };
|
||||
} else if ( /^\d+$/.test(cValue) ) {
|
||||
cValue = parseFloat(cValue);
|
||||
if ( isNaN(cValue) ) { return; }
|
||||
if ( Math.abs(cValue) > 0x7FFF ) { return; }
|
||||
} else if ( cValue === "''" ) {
|
||||
cValue = '';
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
let aborted = false;
|
||||
const mustAbort = function(v) {
|
||||
if ( aborted ) { return true; }
|
||||
aborted = v !== undefined && cValue !== undefined && typeof v !== typeof cValue;
|
||||
return aborted;
|
||||
};
|
||||
const makeProxy = function(owner, chain) {
|
||||
const pos = chain.indexOf('.');
|
||||
if ( pos === -1 ) {
|
||||
const original = owner[chain];
|
||||
if ( mustAbort(original) ) { return; }
|
||||
const desc = Object.getOwnPropertyDescriptor(owner, chain);
|
||||
if ( desc === undefined || desc.get === undefined ) {
|
||||
Object.defineProperty(owner, chain, {
|
||||
get: function() {
|
||||
return document.currentScript === thisScript
|
||||
? original
|
||||
: cValue;
|
||||
},
|
||||
set: function(a) {
|
||||
if ( mustAbort(a) ) {
|
||||
cValue = a;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
const prop = chain.slice(0, pos);
|
||||
let v = owner[prop];
|
||||
chain = chain.slice(pos + 1);
|
||||
if ( v !== undefined ) {
|
||||
makeProxy(v, chain);
|
||||
return;
|
||||
}
|
||||
const desc = Object.getOwnPropertyDescriptor(owner, prop);
|
||||
if ( desc && desc.set !== undefined ) { return; }
|
||||
Object.defineProperty(owner, prop, {
|
||||
get: function() {
|
||||
return v;
|
||||
},
|
||||
set: function(a) {
|
||||
v = a;
|
||||
if ( a instanceof Object ) {
|
||||
makeProxy(a, chain);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
makeProxy(window, '{{1}}');
|
||||
})();
|
|
@ -0,0 +1,44 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
let needle = '{{1}}';
|
||||
const delay = parseInt('{{2}}', 10);
|
||||
if ( needle === '' || needle === '{{1}}' ) {
|
||||
needle = '.?';
|
||||
} else if ( needle.startsWith('/') && needle.endsWith('/') ) {
|
||||
needle = needle.slice(1,-1);
|
||||
} else {
|
||||
needle = needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
needle = new RegExp(needle);
|
||||
window.setTimeout = new Proxy(window.setTimeout, {
|
||||
apply: function(target, thisArg, args) {
|
||||
const a = args[0];
|
||||
const b = args[1];
|
||||
if ( (isNaN(delay) || b === delay) && needle.test(a.toString()) ) {
|
||||
args[0] = function(){};
|
||||
}
|
||||
return target.apply(thisArg, args);
|
||||
}
|
||||
});
|
||||
})();
|
|
@ -1,57 +0,0 @@
|
|||
# This is a list of resources (by token) which will be converted to
|
||||
# "web accessible resources", such that uBO will be able to redirect
|
||||
# to these through moz-extension: or chrome-extension: URLs.
|
||||
#
|
||||
# This addresses:
|
||||
# - https://github.com/gorhill/uBlock/issues/3474
|
||||
# - https://github.com/gorhill/uBlock/issues/2823
|
||||
#
|
||||
# uBO attaches a "secret" token internally when redirecting to any
|
||||
# "web accessible resource", such that it is not possible for a web
|
||||
# page to use one of these "web accessible resource" to directly
|
||||
# detect the presence of uBO.
|
||||
#
|
||||
# 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
|
||||
# using a data: URI.
|
||||
#
|
||||
# The list below was gathered manually from scanning the use of the
|
||||
# "redirect=" option in uBO's own filter lists. Eventually a script could
|
||||
# be written to generate the list below.
|
||||
|
||||
1x1-transparent.gif
|
||||
2x2-transparent.png
|
||||
32x32-transparent.png
|
||||
3x2-transparent.png
|
||||
addthis.com/addthis_widget.js
|
||||
amazon-adsystem.com/aax2/amzn_ads.js
|
||||
ampproject.org/v0.js
|
||||
antiAdBlock.js
|
||||
d3pkae9owd2lcf.cloudfront.net/mb105.js
|
||||
disqus.com/embed.js
|
||||
disqus.com/forums/*/embed.js
|
||||
doubleclick.net/instream/ad_status.js
|
||||
fuckadblock.js-3.2.0
|
||||
google-analytics.com/analytics.js
|
||||
google-analytics.com/cx/api.js
|
||||
google-analytics.com/ga.js
|
||||
google-analytics.com/inpage_linkid.js
|
||||
googlesyndication.com/adsbygoogle.js
|
||||
googletagmanager.com/gtm.js
|
||||
googletagservices.com/gpt.js
|
||||
hd-main.js
|
||||
ligatus.com/*/angular-tag.js
|
||||
noopframe
|
||||
noopjs
|
||||
noopmp3-0.1s
|
||||
noopmp4-1s
|
||||
nooptext
|
||||
popads-dummy.js
|
||||
popads.net.js
|
||||
scorecardresearch.com/beacon.js
|
||||
silent-noeval.js
|
||||
static.chartbeat.com/chartbeat.js
|
||||
widgets.outbrain.com/outbrain.js
|
|
@ -0,0 +1,87 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2019-present Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
let good = '{{1}}';
|
||||
if ( good.startsWith('/') && good.endsWith('/') ) {
|
||||
good = good.slice(1, -1);
|
||||
} else {
|
||||
good = good.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
let reGood;
|
||||
try {
|
||||
reGood = new RegExp(good);
|
||||
} catch(ex) {
|
||||
return;
|
||||
}
|
||||
const rtcName = window.RTCPeerConnection
|
||||
? 'RTCPeerConnection'
|
||||
: (window.webkitRTCPeerConnection ? 'webkitRTCPeerConnection' : '');
|
||||
if ( rtcName === '' ) { return; }
|
||||
const log = console.log.bind(console);
|
||||
const neuteredPeerConnections = new WeakSet();
|
||||
const isGoodConfig = function(instance, config) {
|
||||
if ( neuteredPeerConnections.has(instance) ) { return false; }
|
||||
if ( config instanceof Object === false ) { return true; }
|
||||
if ( Array.isArray(config.iceServers) === false ) { return true; }
|
||||
for ( const server of config.iceServers ) {
|
||||
const urls = typeof server.urls === 'string'
|
||||
? [ server.urls ]
|
||||
: server.urls;
|
||||
if ( Array.isArray(urls) ) {
|
||||
for ( const url of urls ) {
|
||||
if ( reGood.test(url) ) { return true; }
|
||||
}
|
||||
}
|
||||
if ( typeof server.username === 'string' ) {
|
||||
if ( reGood.test(server.username) ) { return true; }
|
||||
}
|
||||
if ( typeof server.credential === 'string' ) {
|
||||
if ( reGood.test(server.credential) ) { return true; }
|
||||
}
|
||||
}
|
||||
neuteredPeerConnections.add(instance);
|
||||
return false;
|
||||
};
|
||||
const peerConnectionCtor = window[rtcName];
|
||||
const peerConnectionProto = peerConnectionCtor.prototype;
|
||||
peerConnectionProto.createDataChannel =
|
||||
new Proxy(peerConnectionProto.createDataChannel, {
|
||||
apply: function(target, thisArg, args) {
|
||||
if ( isGoodConfig(target, args[1]) === false ) {
|
||||
log(args[1]);
|
||||
return target.apply(thisArg, args.slice(0, 1));
|
||||
}
|
||||
return target.apply(thisArg, args);
|
||||
},
|
||||
});
|
||||
window[rtcName] =
|
||||
new Proxy(peerConnectionCtor, {
|
||||
construct: function(target, args) {
|
||||
if ( isGoodConfig(target, args[0]) === false ) {
|
||||
log(args[0]);
|
||||
return new target();
|
||||
}
|
||||
return new target(...args);
|
||||
}
|
||||
});
|
||||
})();
|
|
@ -3,24 +3,13 @@
|
|||
# This script assumes a linux environment
|
||||
|
||||
echo "*** uBlock0.chromium: Creating web store package"
|
||||
echo "*** uBlock0.chromium: Copying files"
|
||||
|
||||
DES=dist/build/uBlock0.chromium
|
||||
rm -rf $DES
|
||||
mkdir -p $DES
|
||||
|
||||
bash ./tools/make-assets.sh $DES
|
||||
|
||||
cp -R src/css $DES/
|
||||
cp -R src/img $DES/
|
||||
cp -R src/js $DES/
|
||||
cp -R src/lib $DES/
|
||||
cp -R src/_locales $DES/
|
||||
cp src/*.html $DES/
|
||||
cp platform/chromium/*.js $DES/js/
|
||||
cp platform/chromium/*.html $DES/
|
||||
cp platform/chromium/*.json $DES/
|
||||
cp LICENSE.txt $DES/
|
||||
echo "*** uBlock0.chromium: copying common files"
|
||||
bash ./tools/copy-common-files.sh $DES
|
||||
|
||||
echo "*** uBlock0.chromium: concatenating content scripts"
|
||||
cat $DES/js/vapi-usercss.js > /tmp/contentscript.js
|
||||
|
@ -38,10 +27,6 @@ rm $DES/js/vapi-usercss.pseudo.js
|
|||
# Chrome store-specific
|
||||
cp -R $DES/_locales/nb $DES/_locales/no
|
||||
|
||||
echo "*** uBlock0.chromium: Generating web accessible resources..."
|
||||
cp -R src/web_accessible_resources $DES/
|
||||
python3 tools/import-war.py $DES/
|
||||
|
||||
echo "*** uBlock0.chromium: Generating meta..."
|
||||
python tools/make-chromium-meta.py $DES/
|
||||
|
||||
|
|
|
@ -3,26 +3,16 @@
|
|||
# This script assumes a linux environment
|
||||
|
||||
echo "*** uBlock0.firefox: Creating web store package"
|
||||
echo "*** uBlock0.firefox: Copying files"
|
||||
|
||||
BLDIR=dist/build
|
||||
DES="$BLDIR"/uBlock0.firefox
|
||||
rm -rf $DES
|
||||
mkdir -p $DES
|
||||
|
||||
bash ./tools/make-assets.sh $DES
|
||||
echo "*** uBlock0.firefox: copying common files"
|
||||
bash ./tools/copy-common-files.sh $DES
|
||||
|
||||
cp -R src/css $DES/
|
||||
cp -R src/img $DES/
|
||||
cp -R src/js $DES/
|
||||
cp -R src/lib $DES/
|
||||
cp -R src/_locales $DES/
|
||||
cp -R $DES/_locales/nb $DES/_locales/no
|
||||
cp src/*.html $DES/
|
||||
cp platform/chromium/*.js $DES/js/
|
||||
cp platform/chromium/*.html $DES/
|
||||
cp platform/chromium/*.json $DES/
|
||||
cp LICENSE.txt $DES/
|
||||
|
||||
cp platform/firefox/manifest.json $DES/
|
||||
cp platform/firefox/vapi-usercss.js $DES/js/
|
||||
|
@ -42,10 +32,6 @@ rm $DES/js/vapi-usercss.pseudo.js
|
|||
# Firefox/webext-specific
|
||||
rm $DES/img/icon_128.png
|
||||
|
||||
echo "*** uBlock0.firefox: Generating web accessible resources..."
|
||||
cp -R src/web_accessible_resources $DES/
|
||||
python3 tools/import-war.py $DES/
|
||||
|
||||
echo "*** uBlock0.firefox: Generating meta..."
|
||||
python tools/make-firefox-meta.py $DES/
|
||||
|
||||
|
|
|
@ -3,24 +3,13 @@
|
|||
# This script assumes a linux environment
|
||||
|
||||
echo "*** uBlock0.opera: Creating web store package"
|
||||
echo "*** uBlock0.opera: Copying files"
|
||||
|
||||
DES=dist/build/uBlock0.opera
|
||||
rm -rf $DES
|
||||
mkdir -p $DES
|
||||
|
||||
bash ./tools/make-assets.sh $DES
|
||||
|
||||
cp -R src/css $DES/
|
||||
cp -R src/img $DES/
|
||||
cp -R src/js $DES/
|
||||
cp -R src/lib $DES/
|
||||
cp -R src/_locales $DES/
|
||||
cp src/*.html $DES/
|
||||
cp platform/chromium/*.js $DES/js/
|
||||
cp platform/chromium/*.html $DES/
|
||||
cp platform/chromium/*.json $DES/
|
||||
cp LICENSE.txt $DES/
|
||||
echo "*** uBlock0.opera: copying common files"
|
||||
bash ./tools/copy-common-files.sh $DES
|
||||
|
||||
echo "*** uBlock0.opera: concatenating content scripts"
|
||||
cat $DES/js/vapi-usercss.js > /tmp/contentscript.js
|
||||
|
@ -57,10 +46,6 @@ rm $DES/lib/lz4/*.wat
|
|||
rm $DES/lib/publicsuffixlist/wasm/*.wasm
|
||||
rm $DES/lib/publicsuffixlist/wasm/*.wat
|
||||
|
||||
echo "*** uBlock0.opera: Generating web accessible resources..."
|
||||
cp -R src/web_accessible_resources $DES/
|
||||
python3 tools/import-war.py $DES/
|
||||
|
||||
echo "*** uBlock0.opera: Generating meta..."
|
||||
python tools/make-opera-meta.py $DES/
|
||||
|
||||
|
|
|
@ -3,26 +3,16 @@
|
|||
# This script assumes a linux environment
|
||||
|
||||
echo "*** uBlock0.thunderbird: Creating web store package"
|
||||
echo "*** uBlock0.thunderbird: Copying files"
|
||||
|
||||
BLDIR=dist/build
|
||||
DES="$BLDIR"/uBlock0.thunderbird
|
||||
rm -rf $DES
|
||||
mkdir -p $DES
|
||||
|
||||
bash ./tools/make-assets.sh $DES
|
||||
echo "*** uBlock0.thunderbird: copying common files"
|
||||
bash ./tools/copy-common-files.sh $DES
|
||||
|
||||
cp -R src/css $DES/
|
||||
cp -R src/img $DES/
|
||||
cp -R src/js $DES/
|
||||
cp -R src/lib $DES/
|
||||
cp -R src/_locales $DES/
|
||||
cp -R $DES/_locales/nb $DES/_locales/no
|
||||
cp src/*.html $DES/
|
||||
cp platform/chromium/*.js $DES/js/
|
||||
cp platform/chromium/*.html $DES/
|
||||
cp platform/chromium/*.json $DES/
|
||||
cp LICENSE.txt $DES/
|
||||
|
||||
cp platform/thunderbird/manifest.json $DES/
|
||||
cp platform/firefox/vapi-webrequest.js $DES/js/
|
||||
|
@ -42,10 +32,6 @@ rm $DES/js/vapi-usercss.pseudo.js
|
|||
# Firefox/webext-specific
|
||||
rm $DES/img/icon_128.png
|
||||
|
||||
echo "*** uBlock0.thunderbird: Generating web accessible resources..."
|
||||
cp -R src/web_accessible_resources $DES/
|
||||
python3 tools/import-war.py $DES/
|
||||
|
||||
echo "*** uBlock0.thunderbird: Generating meta..."
|
||||
python tools/make-firefox-meta.py $DES/
|
||||
|
||||
|
|
|
@ -6,25 +6,15 @@
|
|||
set -e
|
||||
|
||||
echo "*** uBlock0.webext: Creating web store package"
|
||||
echo "*** uBlock0.webext: Copying files"
|
||||
|
||||
DES=dist/build/uBlock0.webext
|
||||
rm -rf $DES
|
||||
mkdir -p $DES
|
||||
|
||||
bash ./tools/make-assets.sh $DES
|
||||
echo "*** uBlock0.webext: copying common files"
|
||||
bash ./tools/copy-common-files.sh $DES
|
||||
|
||||
cp -R src/css $DES/
|
||||
cp -R src/img $DES/
|
||||
cp -R src/js $DES/
|
||||
cp -R src/lib $DES/
|
||||
cp -R src/_locales $DES/
|
||||
cp -R $DES/_locales/nb $DES/_locales/no
|
||||
cp src/*.html $DES/
|
||||
cp platform/chromium/*.js $DES/js/
|
||||
cp platform/chromium/*.html $DES/
|
||||
cp platform/chromium/*.json $DES/
|
||||
cp LICENSE.txt $DES/
|
||||
|
||||
cp platform/webext/manifest.json $DES/
|
||||
cp platform/webext/vapi-usercss.js $DES/js/
|
||||
|
@ -49,10 +39,6 @@ rm $DES/js/vapi-usercss.js
|
|||
rm $DES/js/vapi-usercss.real.js
|
||||
rm $DES/js/vapi-usercss.pseudo.js
|
||||
|
||||
echo "*** uBlock0.webext: Generating web accessible resources..."
|
||||
cp -R src/web_accessible_resources $DES/
|
||||
python3 tools/import-war.py $DES/
|
||||
|
||||
echo "*** uBlock0.webext: Generating meta..."
|
||||
python3 tools/make-webext-meta.py $DES/
|
||||
|
||||
|
|
Loading…
Reference in New Issue