├── .github
├── ISSUE_TEMPLATE.TXT
├── PULL_REQUEST_TEMPLATE.TXT
└── pull.yml
├── .gitignore
├── .travis.yml
├── Extension Compiler
├── updates.json
└── version-update.py
├── LICENSE
├── README.MD
├── docs
├── index.css
└── index.html
├── domainExtractor.py
├── domainList.txt
├── list
├── 1-header.txt
├── 2-integration.txt
├── 3-rules.txt
├── 4-generichide.txt
├── 5-whitelist.txt
└── 6-other.txt
├── notes
├── extension-development.md
└── issue-reporter.md
├── screenshot.png
├── src
├── background
│ ├── core.js
│ ├── debug.js
│ └── rules.js
├── common.js
├── content
│ ├── core.js
│ ├── debug.js
│ ├── rules-common.js
│ ├── rules-specific.js
│ ├── rules-sticky.js
│ └── ubo-extra.js
├── icon128.png
├── libdom.js
├── manifest.json
├── platform
│ ├── chromium-vars.js
│ ├── edge-content.js
│ ├── edge-vars.js
│ ├── firefox-background.js
│ ├── firefox-content.js
│ └── firefox-vars.js
├── popup
│ ├── index.css
│ ├── index.html
│ └── index.js
└── resources
│ ├── blank.mp4
│ ├── fw.js
│ ├── ima3.js
│ └── jquery.js
├── tests
├── check-syntax.js
├── promise-fs.js
└── tests-main.js
└── uBlockProtectorList.txt
/.github/ISSUE_TEMPLATE.TXT:
--------------------------------------------------------------------------------
1 |
5 | ### Test link (required):
6 |
9 |
10 |
11 | ### Screenshot of the web page (including address bar and extension icons) (required):
12 |
16 |
17 |
18 | ### Screenshot of the console (press `F12` to bring up the console) (required):
19 |
22 |
23 |
24 | ### Explain what was not right (optional if obvious):
25 |
26 |
27 | ### Reproduction steps (optional if trivial):
28 |
29 |
30 | ### Environment (Required):
31 |
32 | - Operating System and Version:
33 | - Browser and Version:
34 | - Adblocker and Version:
35 | - Nano Defender Version:
36 |
37 |
38 | #### Your filter lists (Required):
39 |
42 |
43 |
44 | #### Your custom filters (Required if you have any):
45 |
46 |
47 | #### Your other extensions (Required if you have any):
48 |
49 |
50 | ### Add everything else that you believe to be useful below (optional):
51 |
52 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.TXT:
--------------------------------------------------------------------------------
1 | ### Explain why is this change needed (required):
2 |
3 |
4 | ### Test link (if applicable):
5 |
6 |
7 | ### Screenshots and reproduction steps (if applicable):
8 |
9 |
10 | ### Issues that are related (if applicable):
11 |
12 |
13 | ### Add everything else that you believe to be useful below (optional):
14 |
15 |
--------------------------------------------------------------------------------
/.github/pull.yml:
--------------------------------------------------------------------------------
1 | version: "1"
2 | rules:
3 | - base: master
4 | upstream: jspenguin2017:master
5 | autoMerge: false
6 | autoMergeHardReset: false
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | git:
2 | depth: 1
3 | language: node_js
4 | node_js: node
5 | cache:
6 | directories:
7 | - node_modules
8 | before_script:
9 | - npm install esprima
10 | script:
11 | - npm ls
12 | - node ./tests/tests-main.js
13 |
--------------------------------------------------------------------------------
/Extension Compiler/updates.json:
--------------------------------------------------------------------------------
1 | {
2 | "addons": {
3 | "{f9cacf2e-cafc-4f0f-b6ad-8e1a01b4b4d0}": {
4 | "updates": [
5 | {
6 | "version": "15.0.0.206",
7 | "applications": { "gecko": { "strict_min_version": "55.0" } },
8 | "update_link": "https://github.com/LiCybora/NanoDefenderFirefox/releases/download/v15.0.0.206/nano_defender_pro-15.0.0.206-an+fx.xpi"
9 | }
10 | ]
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Extension Compiler/version-update.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | moz_id = "{f9cacf2e-cafc-4f0f-b6ad-8e1a01b4b4d0}";
4 |
5 | with open("updates.json", 'r') as v:
6 | data = v.read()
7 | info = json.loads(data)
8 | old_version = info["addons"][moz_id]["updates"][0]["version"]
9 |
10 | with open("../src/manifest.json", 'r') as f:
11 | new_version = json.load(f)["version"]
12 |
13 | data = data.replace(old_version, new_version)
14 |
15 | with open("updates.json", 'w') as v:
16 | v.write(data)
17 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # Important Announcements Regarding Recent Changes
2 |
3 | **Important: As of v15.0.0.206, this port has NO RELATIONSHIP to upstream anymore. Any product released as Nano Defender on everywhere else other than AMO and this repository are not related to me! My account on both AMO and GitHub are LiCybora. Note that the product name is `Nano Defender for Firefox` and `Nano Defender Pro` on AMO and GitHub respectively, not `Nano Defender`!**
4 |
5 | The project is now 100% independent as upstream is archived. Any other product named Nano Defender has no relationship to me.
6 |
7 | For more information, please read [my thread](https://github.com/LiCybora/NanoDefenderFirefox/issues/187) and announcements from upstream [here](https://github.com/NanoAdblocker/NanoCore/issues/362)
8 |
9 | # Nano Defender for Firefox
10 |
11 | An anti-adblock defuser for Nano Adblocker and uBlock Origin on Firefox
12 |
13 | 
14 |
15 | ## About Firefox port
16 |
17 | The source code of this project is shared from [upstream](https://github.com/jspenguin2017/uBlockProtector).
18 |
19 | As of v15.0.0.206, Nano Defender for Firefox is independent from any entites or people. Note that the product name is `Nano Defender for Firefox` and `Nano Defender Pro` on AMO and GitHub respectively, not `Nano Defender`!
20 |
21 | For issues other than filter issues found on Firefox port, it is recommended to report [here](https://github.com/LiCybora/NanoDefenderFirefox/issues).
22 |
23 | ### Notable changes
24 |
25 | #### Disable console log (since v15.0.0.93)
26 |
27 | You may disable console log for this browser session in the popup (see the first row of screenshot). This option will turn on again when you restart browser session. Please note that console filtering with -[Nano] will **NOT** work for Firefox.
28 |
29 | ## Installation
30 |
31 | Nano Defender can only protect either [Nano Adblocker](https://github.com/LiCybora/NanoCoreFirefox) or [uBlock Origin](https://github.com/gorhill/ublock), and will prioritize Nano Adblocker. As of 17 Oct 2020, Nano Adblocker is no more.
32 |
33 | ### [Get Nano Defender Pro (for Waterfox/Firefox 55 or above)](https://github.com/LiCybora/NanoDefenderFirefox/releases/)
34 |
35 | ### [Get Nano Defender for Firefox on AMO (Recommend, ONLY for Firefox 60 or above)](https://addons.mozilla.org/en-US/firefox/addon/nano-defender-firefox/)
36 |
37 | The 'Pro' version will strictly follow the Pro version in upstream, while the 'for Firefox' version may add/replace rules with [Firefox-specific API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/filterResponseData), or [remove the potential dangerous rules](https://extensionworkshop.com/documentation/develop/build-a-secure-extension/).
38 |
39 | **IMPORTANT: DO NOT install both versions.**
40 |
41 | Note: If you are using uBlock Origin, there are a few [extra installation steps](https://ghcdn.rawgit.org/LiCybora/NanoDefenderFirefox/master/docs/index.html#extra-installation-steps-for-ublock-origin) to follow.
42 |
43 | As of uBO 1.30.0, Adblock Warning Removal List is bad listed by uBlock Origin and cannot be added. Just skip it for now. I will remove that instruction once I clone all required resources from upstream and host on my own.
44 |
45 | ### About Pre-quantum fork
46 |
47 | ONLY Waterfox 55 or above, or forks with equivalent gecko version and supporting WebExtension API can install the 'Pro' version.
48 | However, some functions are lacking (such as console switch and response data filtering).
49 |
50 | **No support for other pre-quantum forks without WebExtension API (such as Basilisk, Palemoon).**
51 |
52 | ## Building
53 |
54 | Nano Defender for Firefox is built using
55 | [Nano Build (Modded)](https://github.com/LiCybora/NanoBuild).
56 |
57 | ## Credits
58 |
59 | Nano Defender uses open source code from the following projects (alphabetical):
60 |
61 | [reek/anti-adblock-killer](https://github.com/reek/anti-adblock-killer)
62 |
63 | [primer/octicons](https://github.com/primer/octicons/)
64 |
65 | [uBlockOrigin/uAssets](https://github.com/uBlockOrigin/uAssets)
66 |
67 | [gorhill/uBlock](https://github.com/gorhill/uBlock)
68 |
69 | [gorhill/uBO-Extra](https://github.com/gorhill/uBO-Extra)
70 |
71 | ## Special Thanks
72 |
73 | Nano Defender is developed by **@jspenguin2017** with the help of the following
74 | individuals (alphabetical):
75 |
76 | **@lain566**
77 |
--------------------------------------------------------------------------------
/docs/index.css:
--------------------------------------------------------------------------------
1 | code {
2 | background-color: rgba(255, 255, 255, 0.8);
3 | border-radius: 20px;
4 | font-family: Consolas, monospace;
5 | padding: 0px 8px 0px 8px;
6 | }
7 |
8 | p {
9 | line-height: 1.3em;
10 | }
11 |
12 | p.red {
13 | padding: 5px;
14 | }
15 |
16 | div.scroll {
17 | max-width: 100%;
18 | overflow-x: auto;
19 | }
20 |
21 | p.no-bot {
22 | margin-bottom: 0px;
23 | }
24 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /;
92 | let adsTimerPrompt =
93 | /\w\.innerHTML=''\+window\._molSettings\.skipText.*?"<\/p>"/g;
94 | let adsSkipPrompt = /\w\.innerHTML=window\._molSettings\.skipButtonText/g;
95 | const req = new _XMLHttpRequest();
96 | req.onreadystatechange = () => {
97 | if (req.readyState === 4) {
98 | let payload = req.responseText;
99 | try {
100 | payload = payload.replace(adsTimerOffset, '');
101 | payload = payload.replace(adsSkipPrompt, [
102 | "$('.vast-skip-button.enabled')[0].click()",
103 | "$('#ani_video_html5_api').show()",
104 | "$('#ani_video_html5_api').prop('muted', false)",
105 | ].join(","));
106 | payload = payload.replace(adsTimerPrompt, (match) => {
107 | return "(" + [
108 | match,
109 | "$('#ani_video_html5_api').hide()",
110 | "$('#ani_video_html5_api').prop('muted', true)",
111 | ].join(",") + ")";
112 | });
113 | } catch (err) { }
114 | const script = window.document.createElement("script");
115 | script.textContent = payload;
116 | window.document.body.append(script);
117 | }
118 | };
119 | req.open("GET", src);
120 | req.send();
121 | };
122 |
123 | const _appendChild = window.Element.prototype.appendChild;
124 | window.Element.prototype.appendChild = function (elem) {
125 | if (
126 | elem.tagName === "SCRIPT" &&
127 | elem.src &&
128 | elem.src.startsWith("https://i2.bahamut.com.tw/build/js/animeplayer")
129 | ) {
130 | return void patchPlayer(elem.src);
131 | }
132 | return _appendChild.apply(this, arguments);
133 | };
134 | });
135 | }
136 |
137 | // ------------------------------------------------------------------------------------------------------------- //
138 |
139 | }
140 |
141 | // ----------------------------------------------------------------------------------------------------------------- //
142 |
143 | //@pragma-end-if
144 |
145 | // ----------------------------------------------------------------------------------------------------------------- //
146 |
--------------------------------------------------------------------------------
/src/content/rules-common.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------------- //
2 |
3 | // Nano Defender - An anti-adblock defuser
4 | // Copyright (C) 2016-2019 Nano Defender contributors
5 | //
6 | // This program is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation, either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program. If not, see .
18 |
19 | // ----------------------------------------------------------------------------------------------------------------- //
20 |
21 | // Handle whitelist and initialize generic content solutions. Then apply common content rules
22 | //
23 | // Solutions from Anti-Adblock Killer (by Reek) are modified to fit the content core library
24 | //
25 | // Anti-Adblock Killer Repository (contains original source code and license):
26 | // https://github.com/reek/anti-adblock-killer
27 |
28 | // ----------------------------------------------------------------------------------------------------------------- //
29 |
30 | "use strict";
31 |
32 | // ----------------------------------------------------------------------------------------------------------------- //
33 |
34 | {
35 |
36 | // ------------------------------------------------------------------------------------------------------------- //
37 |
38 | a.init();
39 |
40 | // ------------------------------------------------------------------------------------------------------------- //
41 |
42 | const domCmpWhitelist = [
43 |
44 | // --------------------------------------------------------------------------------------------------------- //
45 |
46 | // Local network
47 | "127.0.0.1",
48 | "local",
49 |
50 | // Reserved TLDs
51 | "example",
52 | "invalid",
53 | "localhost",
54 | "test",
55 |
56 | // --------------------------------------------------------------------------------------------------------- //
57 |
58 | // Baidu
59 | "baidu.com",
60 |
61 | // Google
62 | "google.it.ao",
63 | "google.ne.jp",
64 | "google.off.ai",
65 |
66 | // PayPal
67 | "paypal.com",
68 | "paypal.me",
69 |
70 | // Twitch
71 | "twitch.tv",
72 |
73 | // Wikipedia
74 | "wikipedia.org",
75 |
76 | // YouTube
77 | "youtu.be",
78 | "youtube.com",
79 |
80 | // --------------------------------------------------------------------------------------------------------- //
81 |
82 | // Advanced tools (for performance)
83 | "lab.wolframcloud.com",
84 |
85 | // Image hosts (for performance)
86 | "flickr.com",
87 | "imgbox.com",
88 | "imgur.com",
89 |
90 | // JavaScript playgrounds (for performance)
91 | "ask.com",
92 | "codepen.io",
93 | "jsbin.com",
94 | "jsfiddle.net",
95 | "plnkr.co",
96 | "preloaders.net",
97 | "stackoverflow.com",
98 | "w3schools.com",
99 |
100 | // Media sites (for performance)
101 | "calm.com",
102 | "vimeo.com",
103 | "xemvtv.net",
104 | "yandex.ru",
105 |
106 | // Social networks (for performance)
107 | "bufferapp.com",
108 | "chatango.com",
109 | "facebook.com",
110 | "instagram.com",
111 | "linkedin.com",
112 | "messenger.com",
113 | "pinterest.com",
114 | "reddit.com",
115 | "twitter.com",
116 |
117 | // --------------------------------------------------------------------------------------------------------- //
118 |
119 | // Custom FuckAdBlock
120 | "atresplayer.com",
121 | "aviationweek.com",
122 | "futbin.com",
123 | "juprimaulana.com",
124 | "paraedu.id",
125 | "rmcmv.us",
126 | "yuukithemes.com",
127 |
128 | // False positives from Adfly skipper
129 | "programme-tv.net",
130 |
131 | // False positives from legacy BlockAdBlock defuser
132 | "alternativeto.net",
133 |
134 | // Other false positives
135 | "anandabazar.com",
136 | "animesync.tv",
137 | "aternos.org",
138 | "automobile-propre.com",
139 | "avgle.com",
140 | "babbel.com",
141 | "bild.de",
142 | "browserleaks.com",
143 | "bungie.net",
144 | "buxfer.com",
145 | "ccbluex.net",
146 | "cfnc.org",
147 | "dallasnews.com",
148 | "derstandard.at",
149 | "di.fm",
150 | "download.ipeenk.com",
151 | "duellinksmeta.com",
152 | "egy.best",
153 | "filmweb.pl",
154 | "finobe.com",
155 | "gamersclub.com.br",
156 | "gaobook.review",
157 | "hackintosh.computer",
158 | "imdb.com",
159 | "infostrow.pl",
160 | "jazzradio.com",
161 | "lcpdfr.com",
162 | "lemonde.fr",
163 | "linetv.tw",
164 | "lolalytics.com",
165 | "myworkday.com",
166 | "o2.pl",
167 | "ostrzeszowinfo.pl",
168 | "pasty.link",
169 | "pokyun.tv",
170 | "pornhub.com",
171 | "privacy-port.de",
172 | "reevown.com",
173 | "shinden.pl",
174 | "socketloop.com",
175 | "sport-tv-guide.live",
176 | "store.playstation.com",
177 | "strefadb.pl",
178 | "techradar.com",
179 | "tv3sport.dk",
180 | "tvserial.it",
181 | "viasatsport.se",
182 | "viasport.fi",
183 | "viasport.no",
184 | "vod.pl",
185 | "wilmaa.com",
186 | "workday.com",
187 | "wp.pl",
188 | "wstream.video",
189 |
190 | // Handled by a special private extension
191 | "boost.ink",
192 |
193 | // --------------------------------------------------------------------------------------------------------- //
194 |
195 | ];
196 |
197 | const domIncWhitelist = [
198 |
199 | // --------------------------------------------------------------------------------------------------------- //
200 |
201 | // Local network
202 | "192.168.0",
203 | "192.168.1",
204 |
205 | // --------------------------------------------------------------------------------------------------------- //
206 |
207 | // Google
208 | "google",
209 | "google.co",
210 | "google.com",
211 |
212 | // Yahoo
213 | "yahoo",
214 |
215 | // --------------------------------------------------------------------------------------------------------- //
216 |
217 | // Stores (for performance)
218 | "amazon",
219 | "ebay",
220 |
221 | // --------------------------------------------------------------------------------------------------------- //
222 |
223 | // Other false positives
224 | "9anime",
225 | "egybest",
226 | "italiashare",
227 | "imgdew",
228 | "imgfile",
229 | "imgmaze",
230 | "imgoutlet",
231 | "imgrock",
232 | "imgview",
233 | "kickassanime",
234 | "kiss-anime",
235 | "kissanime",
236 | "kissasian",
237 | "oladblock",
238 | "oload",
239 | "openload",
240 | "viafree",
241 |
242 | // --------------------------------------------------------------------------------------------------------- //
243 |
244 | ];
245 |
246 | // ------------------------------------------------------------------------------------------------------------- //
247 |
248 | if (a.domCmp(domCmpWhitelist, true) || a.domInc(domIncWhitelist, true)) {
249 |
250 | console.log("[Nano] Excluded :: All Generically Applied Solutions");
251 |
252 | } else {
253 |
254 | if (false) {
255 | console.log("[Nano] Excluded :: Common Generic Solutions");
256 | } else {
257 | a.generic();
258 | }
259 |
260 | if (a.domCmp([
261 | // https://github.com/NanoMeow/QuickReports/issues/2641
262 | "topadnetworks.net",
263 | "topshort.net",
264 | // https://github.com/NanoMeow/QuickReports/issues/2950
265 | "freealtsgenerator.es",
266 | "uforum.us",
267 | // https://github.com/NanoMeow/QuickReports/issues/3113
268 | "ctrn.cc",
269 | "cutearn.net",
270 | ], true) || a.domInc([
271 | // https://github.com/uBlockOrigin/uAssets/issues/6553
272 | "cutlinks",
273 | ], true)) {
274 | console.log("[Nano] Excluded :: Adfly Skipper");
275 | } else {
276 | a.generic.Adfly();
277 | }
278 |
279 | if (false) {
280 | console.log("[Nano] Excluded :: Adfly Forced Notification Blocker");
281 | } else {
282 | a.generic.AdflyForcedNotification();
283 | }
284 |
285 | if (false) {
286 | console.log("[Nano] Excluded :: app_vars Defuser");
287 | } else {
288 | a.generic.app_vars();
289 | }
290 |
291 | if (false) {
292 | console.log("[Nano] Excluded :: Cloudflare Apps Defuser");
293 | } else {
294 | a.generic.CloudflareApps();
295 | }
296 |
297 | }
298 |
299 | // ------------------------------------------------------------------------------------------------------------- //
300 |
301 | // Deprecated
302 | if (a.domCmp([
303 | "acquavivalive.it",
304 | "beinsports.com",
305 | "listamais.com.br",
306 | "lolskinlistgenerator.com",
307 | "m.delfi.ee",
308 | "memurlar.net",
309 | "molfettalive.it",
310 | "palemoon.org",
311 | "palolive.it",
312 | "passionea300allora.it",
313 | "sledujserialy.sk",
314 | "stocks.cafe",
315 | "uploadboy.com",
316 | "videohelp.com",
317 | "vidoza.net",
318 | "warforum.cz",
319 | "zeiz.me",
320 | ])) {
321 | a.generic.adsjsV2();
322 | }
323 |
324 | // ------------------------------------------------------------------------------------------------------------- //
325 |
326 | if (false) {
327 | a.uBOExtraExcluded = true;
328 | console.log("[Nano] Excluded :: uBO-Extra");
329 | }
330 |
331 | // ------------------------------------------------------------------------------------------------------------- //
332 |
333 | }
334 |
335 | // ----------------------------------------------------------------------------------------------------------------- //
336 |
337 | // a.filter
338 |
339 | if (a.domCmp([
340 | "darmowe-pornosy.pl",
341 | "exrapidleech.info",
342 | "flashx.to",
343 | "flashx.tv",
344 | "linx.cloud",
345 | "urle.co",
346 | "usapoliticstoday.com",
347 | "vidlox.tv",
348 | ])) {
349 | a.filter("eval");
350 | }
351 |
352 | if (a.domCmp([
353 | "cloudwebcopy.com",
354 | "sc2casts.com",
355 | "webqc.org",
356 | ])) {
357 | a.filter("setTimeout");
358 | }
359 |
360 | if (a.domCmp([
361 | "1movies.tv",
362 | "adshort.co",
363 | "adshort.im",
364 | "adshorte.com",
365 | "arenavision.in",
366 | "atdhe.al",
367 | "atdhe.bz",
368 | "atdhe.li",
369 | "atdhe.me",
370 | "atdhe.mx",
371 | "atdhe.ru",
372 | "atdhe.se",
373 | "atdhe.to",
374 | "atdhe.top",
375 | "backin.net",
376 | "coinb.ink",
377 | "ddlfr.pw",
378 | "doramasflv.net",
379 | "firstrow.co",
380 | "firstrow1us.eu",
381 | "firstrows.biz",
382 | "firstrows.co",
383 | "firstrows.org",
384 | "firstrows.ru",
385 | "firstrows.tv",
386 | "firstrowsportes.com",
387 | "firstrowsportes.tv",
388 | "firstrowus.eu",
389 | "firstsrowsports.eu",
390 | "hahasport.me",
391 | "iiv.pl",
392 | "justfirstrowsports.com",
393 | "katfile.com",
394 | "l2s.io",
395 | "linclik.com",
396 | "linkkawy.com",
397 | "linksh.top",
398 | "myp2p.biz",
399 | "myp2p.com",
400 | "myp2p.ec",
401 | "myp2p.eu",
402 | "myp2p.la",
403 | "myp2p.sx",
404 | "myp2p.tv",
405 | "myp2p.ws",
406 | "sawlive.tv",
407 | "shink.me",
408 | "u2s.io",
409 | "ur.ly",
410 | "urle.co",
411 | "videowood.tv",
412 | "vidoza.net",
413 | "wiziwig.ru",
414 | "wiziwig.sx",
415 | "wiziwig.to",
416 | "wiziwig.tv",
417 | "zlshorte.net",
418 | ])) {
419 | a.filter("open");
420 | }
421 |
422 | if (a.domCmp([
423 | "businesstoday.in",
424 | "dl-protect.com",
425 | "doatoolsita.altervista.org",
426 | "drivearabia.com",
427 | "filecom.net",
428 | "free-movie-home.com",
429 | "generatupremium.biz",
430 | "kooora.com",
431 | "mega-debrid.eu",
432 | "newsinlevels.com",
433 | "pc.online143.com",
434 | "pipocas.tv",
435 | "premiumst0re.blogspot.com",
436 | "putlocker.com",
437 | "sockshare.com",
438 | "str3am.altervista.org",
439 | "str3amtv.altervista.org",
440 | "str3amtv.co.nr",
441 | "str3amtv.co.nr",
442 | "vipracing.biz",
443 | ])) {
444 | a.filter("alert");
445 | }
446 |
447 | // ----------------------------------------------------------------------------------------------------------------- //
448 |
449 | // a.readOnly
450 |
451 | if (a.domCmp([
452 | "financialexpress.com",
453 | "indianexpress.com",
454 | "jansatta.com",
455 | "srt.am",
456 | "uskip.me",
457 | ])) {
458 | a.readOnly("RunAds", true);
459 | }
460 |
461 | if (a.domCmp([
462 | "catcatyfaucet.xyz",
463 | "jagranjunction.com",
464 | "nekopoi.bid",
465 | ])) {
466 | a.readOnly("isAdsDisplayed", true);
467 | }
468 |
469 | if (a.domCmp([
470 | "stream.nbcsports.com",
471 | "swissadspaysethfaucet.com",
472 | "swissadspaysfaucet.com",
473 | ])) {
474 | a.readOnly("adBlockEnabled", false);
475 | }
476 |
477 | if (a.domCmp([
478 | "link.tl",
479 | ])) {
480 | a.readOnly("adblocker", false);
481 | }
482 |
483 | if (a.domCmp([
484 | "megogo.net",
485 | ])) {
486 | a.readOnly("adBlock", false);
487 | }
488 |
489 | if (a.domCmp([
490 | "4tests.com",
491 | "8bbit.com",
492 | "alcodistillers.ru",
493 | "angrybirdsnest.com",
494 | "freizeitpartnerweb.de",
495 | "nekopoi.bid",
496 | "outdoorpartner.net",
497 | "translatica.pl",
498 | "urlaubspartner.net",
499 | ])) {
500 | a.readOnly("adblock", false);
501 | }
502 |
503 | if (a.domCmp([
504 | "code.ptcong.com",
505 | "hanime.tv",
506 | "mega-estrenos.com",
507 | "mexashare.com",
508 | "popunderjs.com",
509 | "shortin.ga",
510 | ])) {
511 | a.readOnly("BetterJsPop", "window.Object.freeze({})");
512 | }
513 |
514 | if (a.domCmp([
515 | "he2eini7ka.com",
516 | "youwatch.to",
517 | ])) {
518 | a.readOnly("jsPopunder", () => { });
519 | }
520 |
521 | if (a.domCmp([
522 | "ahzahg6ohb.com",
523 | "ajihezo.info",
524 | "bojem3a.info",
525 | "chefti.info",
526 | "chouhaa.info",
527 | "exashare.com",
528 | "he2eini7ka.com",
529 | "yahmaib3ai.com",
530 | "youwatch.org",
531 | "youwatch.to",
532 | ])) {
533 | a.readOnly("adsShowPopup1", 1);
534 | }
535 |
536 | if (a.domCmp([
537 | "game-debate.com",
538 | "naruto-mx.net",
539 | "onepiece-mx.net",
540 | "scan-mx.com",
541 | ])) {
542 | a.readOnly("ad_block_test", () => { });
543 | }
544 |
545 | if (a.domCmp([
546 | "freebitcoins.nx.tc",
547 | "getbitcoins.nx.tc",
548 | ])) {
549 | a.readOnly("ad_block_test", () => false);
550 | }
551 |
552 | if (a.domCmp([
553 | "1movies.tv",
554 | "xmovies8.es",
555 | ])) {
556 | a.readOnly("check_adblock", true);
557 | }
558 |
559 | if (a.domCmp([
560 | "fourchette-et-bikini.fr",
561 | "meteocity.com",
562 | ])) {
563 | a.readOnly("adProtect", 1);
564 | }
565 |
566 | if (a.domCmp([
567 | "homerun.re",
568 | "securenetsystems.net",
569 | "strikeout.co",
570 | "strikeout.me",
571 | "vipapp.me",
572 | "vipbox.biz",
573 | "vipbox.co",
574 | "vipbox.eu",
575 | "vipbox.nu",
576 | "vipbox.so",
577 | "vipbox.sx",
578 | "vipbox.tv",
579 | "vipboxsa.co",
580 | "vipboxtv.co",
581 | "vipleague.ch",
582 | "vipleague.co",
583 | "vipleague.is",
584 | "vipleague.me",
585 | "vipleague.mobi",
586 | "vipleague.se",
587 | "vipleague.sx",
588 | "vipleague.tv",
589 | "vipleague.ws",
590 | ])) {
591 | a.readOnly("iExist", true);
592 | }
593 |
594 | // ----------------------------------------------------------------------------------------------------------------- //
595 |
596 | // a.noAccess
597 |
598 | if (a.domCmp([
599 | "adshort.co",
600 | "adshorte.com",
601 | "animeforce.org",
602 | "coinb.ink",
603 | "debridnet.com",
604 | "imgrock.info",
605 | "linksh.top",
606 | "srt.am",
607 | ])) {
608 | a.noAccess("_pop");
609 | }
610 |
611 | if (a.domCmp([
612 | "linx.cloud",
613 | ])) {
614 | a.noAccess("popns");
615 | }
616 |
617 | if (a.domCmp([
618 | "adlinkme.com",
619 | "arenabg.ch",
620 | "jzrputtbut.net",
621 | "maango.info",
622 | "psarips.com",
623 | "solidfiles.com",
624 | "streamcloud.eu",
625 | "torrentfunk.com",
626 | "vidfile.net",
627 | ])) {
628 | a.noAccess("open");
629 | }
630 |
631 | // ----------------------------------------------------------------------------------------------------------------- //
632 |
633 | // a.bait
634 |
635 | if (a.domCmp([
636 | "leveldown.fr",
637 | "primeshare.tv",
638 | ])) {
639 | a.bait("div", "#adblock");
640 | }
641 |
642 | if (a.domCmp([
643 | "720pmkv.com",
644 | "psarips.com",
645 | ])) {
646 | a.bait("div", "#advert");
647 | }
648 |
649 | if (a.domCmp([
650 | "bitcoiner.net",
651 | "d3brid4y0u.info",
652 | "dashcatch.xyz",
653 | "dogecatch.website",
654 | "dramapassion.com",
655 | "easybillets.com",
656 | "fileice.net",
657 | "freeallmusic.info",
658 | "litecoiner.net",
659 | "nosteam.ro",
660 | "online.ua",
661 | "openrunner.com",
662 | "osoarcade.com",
663 | "putlocker.com",
664 | "shortify.pw",
665 | "sockshare.com",
666 | "spox.fr",
667 | "tgo-tv.com",
668 | "tv3.co.nz",
669 | "yooclick.com",
670 | "yovoyages.com",
671 | ])) {
672 | a.bait("div", "#tester");
673 | }
674 |
675 | if (a.domCmp([
676 | "alein.org",
677 | ])) {
678 | a.bait("div", "#tester", true);
679 | }
680 |
681 | if (a.domCmp([
682 | "filecom.net",
683 | "globeslot.com",
684 | "mwfiles.net",
685 | "skippyfile.com",
686 | "up-flow.org",
687 | "upshare.org",
688 | ])) {
689 | a.bait("div", "#add");
690 | }
691 |
692 | if (a.domCmp([
693 | "bluesatoshi.com",
694 | "oneadfaucet.com",
695 | "razercrypt.com",
696 | "satoshiempire.com",
697 | ])) {
698 | a.bait("div", "#test");
699 | }
700 |
701 | if (a.domCmp([
702 | "bitcoinaliens.com",
703 | "door2windows.com",
704 | ])) {
705 | a.bait("ins", ".adsbygoogle");
706 | }
707 |
708 | if (a.domCmp([
709 | "hellsmedia.com",
710 | "leaguesecretary.com",
711 | "teknogods.com",
712 | ])) {
713 | a.bait("div", "#adpbtest");
714 | }
715 |
716 | if (a.domCmp([
717 | "freesportsbet.com",
718 | "sportsplays.com",
719 | ])) {
720 | a.bait("div", "#ad-tester");
721 | }
722 |
723 | if (a.domCmp([
724 | "bitcoiner.net",
725 | "litecoiner.net",
726 | ])) {
727 | a.bait("div", "#ad-top");
728 | }
729 |
730 | // ----------------------------------------------------------------------------------------------------------------- //
731 |
--------------------------------------------------------------------------------
/src/content/rules-sticky.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Content rules for sticky websites.
3 | */
4 | "use strict";
5 |
6 | if (a.domCmp(["debridnet.com"])) {
7 | const re = /\.height\(\)/g;
8 | a.beforeScript((script) => {
9 | if (script.textContent) {
10 | script.textContent = script.textContent.replace(re, " && false && 0");
11 | }
12 | });
13 | a.timewarp("setTimeout", a.matchMethod.RegExp, /^\d+000$/, 0.2);
14 | for (let i = 0; i < 15; i++) {
15 | const s = document.createElement("script");
16 | document.documentElement.append(s);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/content/ubo-extra.js:
--------------------------------------------------------------------------------
1 | (() => {
2 | if (a.uBOExtraExcluded) {
3 | return;
4 | }
5 |
6 |
7 |
8 | /*******************************************************************************
9 |
10 | uBO-Extra - A companion extension to uBlock Origin: to gain ability to
11 | foil early hostile anti-user mechanisms working around
12 | content blockers.
13 | Copyright (C) 2016-2018 Raymond Hill
14 |
15 | This program is free software: you can redistribute it and/or modify
16 | it under the terms of the GNU General Public License as published by
17 | the Free Software Foundation, either version 3 of the License, or
18 | (at your option) any later version.
19 |
20 | This program is distributed in the hope that it will be useful,
21 | but WITHOUT ANY WARRANTY; without even the implied warranty of
22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 | GNU General Public License for more details.
24 |
25 | You should have received a copy of the GNU General Public License
26 | along with this program. If not, see {http://www.gnu.org/licenses/}.
27 |
28 | Home: https://github.com/gorhill/uBO-WebSocket
29 | */
30 |
31 | 'use strict';
32 |
33 | /* global HTMLDocument, XMLDocument */
34 |
35 | /*******************************************************************************
36 |
37 | All scriptlets to inject: the scriptlets to inject are to foil or work
38 | around hostile anti-user mechanism used by some web sites.
39 |
40 | **/
41 |
42 | var scriptlets = [],
43 | hostname = window.location.hostname,
44 | contentScriptSecret =
45 | String.fromCharCode(Date.now() % 26 + 97) +
46 | Math.floor(Math.random() * 982451653 + 982451653).toString(36);
47 |
48 | /*******************************************************************************
49 |
50 | Don't run on non-HTML documents.
51 |
52 | **/
53 |
54 | var abort = (function() {
55 | var doc = document;
56 | if ( doc instanceof HTMLDocument === false ) {
57 | if (
58 | doc instanceof XMLDocument === false ||
59 | doc.createElement('div') instanceof HTMLDivElement === false
60 | ) {
61 | return true;
62 | }
63 | }
64 | if ( (doc.contentType || '').lastIndexOf('image/', 0) === 0 ) {
65 | return true;
66 | }
67 | return false;
68 | })();
69 |
70 | /*******************************************************************************
71 |
72 | Fetch hostname from ancestors if none available (we could be executed from
73 | inside an anonymous frame).
74 |
75 | **/
76 |
77 | if ( !abort ) {
78 | if ( hostname === '' ) {
79 | hostname = (function() {
80 | var win = window, hn = '', max = 10;
81 | try {
82 | for (;;) {
83 | hn = win.location.hostname;
84 | if ( hn !== '' ) { return hn; }
85 | if ( win.parent === win ) { break; }
86 | win = win.parent;
87 | if ( !win ) { break; }
88 | if ( (max -= 1) === 0 ) { break; }
89 | }
90 | } catch(ex) {
91 | }
92 | return hn;
93 | })();
94 | }
95 | // Don't inject if document is from local network.
96 | abort = /^192\.168\.\d+\.\d+$/.test(hostname);
97 | }
98 |
99 | /*******************************************************************************
100 |
101 | Instart Logic defuser
102 |
103 | **/
104 |
105 | (function() {
106 | if ( abort ) { return; }
107 |
108 | var scriptlet = function() {
109 | var magic = String.fromCharCode(Date.now() % 26 + 97) +
110 | Math.floor(Math.random() * 982451653 + 982451653).toString(36),
111 | targets = [
112 | 'atob',
113 | 'console.error',
114 | 'INSTART',
115 | 'INSTART_TARGET_NAME',
116 | 'navigator.userAgent',
117 | 'performance',
118 | 'require'
119 | ],
120 | reScriptText = /\b(?:Instart-|I10C|I11C|IXC_|INSTART)/,
121 | reScriptSrc = /\babd.*?\/instart.js|\?i10c\./,
122 | thisScript = document.currentScript;
123 | var validate = function() {
124 | var script = document.currentScript;
125 | if ( script instanceof HTMLScriptElement === false ) { return; }
126 | if ( script === thisScript ) { return; }
127 | if ( script.src === '' ) {
128 | if ( reScriptText.test(script.textContent) ) {
129 | throw new ReferenceError(magic);
130 | }
131 | } else if ( reScriptSrc.test(script.src) ) {
132 | throw new ReferenceError(magic);
133 | }
134 | };
135 | var makeGetterSetter = function(owner, prop) {
136 | var value = owner[prop];
137 | return {
138 | get: function() {
139 | validate();
140 | return value;
141 | },
142 | set: function(a) {
143 | validate();
144 | value = a;
145 | }
146 | };
147 | };
148 | var i = targets.length,
149 | owner, target, chain, prop;
150 | while ( i-- ) {
151 | owner = window;
152 | target = targets[i];
153 | chain = target.split('.');
154 | for (;;) {
155 | prop = chain.shift();
156 | if ( chain.length === 0 ) { break; }
157 | owner = owner[prop];
158 | }
159 | Object.defineProperty(owner, prop, makeGetterSetter(owner, prop));
160 | }
161 | var oe = window.onerror;
162 | window.onerror = function(msg) {
163 | if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
164 | return true;
165 | }
166 | if ( oe instanceof Function ) {
167 | return oe.apply(this, arguments);
168 | }
169 | }.bind();
170 | };
171 |
172 | scriptlets.push({
173 | scriptlet: scriptlet,
174 | targets: [
175 | 'afterellen.com',
176 | 'americanphotomag.com',
177 | 'atvrider.com',
178 | 'baggersmag.com',
179 | 'baltimoresun.com',
180 | 'boatingmag.com',
181 | 'boston.com',
182 | 'cafemom.com',
183 | 'calgaryherald.com',
184 | 'calgarysun.com',
185 | 'capitalgazette.com',
186 | 'carrollcountytimes.com',
187 | 'cattime.com',
188 | 'cbssports.com',
189 | 'chicagotribune.com',
190 | 'chowhound.com',
191 | 'chron.com',
192 | 'chroniclelive.co.uk',
193 | 'citypaper.com',
194 | 'comingsoon.net',
195 | 'computershopper.com',
196 | 'courant.com',
197 | 'craveonline.com',
198 | 'cruisingworld.com',
199 | 'csgoutpost.com',
200 | 'ctnow.com',
201 | 'cycleworld.com',
202 | 'dailydot.com',
203 | 'dailypress.com',
204 | 'dayzdb.com',
205 | 'deathandtaxesmag.com',
206 | 'delmartimes.net',
207 | 'destinationweddingmag.com',
208 | 'dirtrider.com',
209 | 'diversitybestpractices.com',
210 | 'dogtime.com',
211 | 'dotaoutpost.com',
212 | 'download.cnet.com',
213 | 'edmontonjournal.com',
214 | 'edmontonsun.com',
215 | 'edmunds.com',
216 | 'emedicinehealth.com',
217 | 'esohead.com',
218 | 'everquest.allakhazam.com',
219 | 'extremetech.com',
220 | 'fieldandstream.com',
221 | 'financialpost.com',
222 | 'floridatravellife.com',
223 | 'flyingmag.com',
224 | 'focus.de',
225 | 'foxsports.com.au',
226 | 'gamepedia.com',
227 | 'gamerevolution.com',
228 | 'gamespot.com',
229 | 'geek.com',
230 | 'goal.com',
231 | 'gofugyourself.com',
232 | 'growthspotter.com',
233 | 'hearthhead.com',
234 | 'hockeysfuture.com',
235 | 'hotbikeweb.com',
236 | 'hoylosangeles.com',
237 | 'ibtimes.com',
238 | 'infinitiev.com',
239 | 'islands.com',
240 | 'lajollalight.com',
241 | 'laptopmag.com',
242 | 'latintimes.com',
243 | 'leaderpost.com',
244 | 'legacy.com',
245 | 'lifewire.com',
246 | 'livescience.com',
247 | 'lolking.net',
248 | 'mcall.com',
249 | 'mamaslatinas.com',
250 | 'marlinmag.com',
251 | 'medicaldaily.com',
252 | 'medicinenet.com',
253 | 'metacritic.com',
254 | 'metrolyrics.com',
255 | 'mmo-champion.com',
256 | 'momtastic.com',
257 | 'montrealgazette.com',
258 | 'motorcyclecruiser.com',
259 | 'motorcyclistonline.com',
260 | 'motortrend.com',
261 | 'msn.com',
262 | 'musicfeeds.com.au',
263 | 'mustangandfords.com',
264 | 'mysanantonio.com',
265 | 'nasdaq.com',
266 | 'nationalpost.com',
267 | 'newsarama.com',
268 | 'newsweek.com',
269 | 'orlandosentinel.com',
270 | 'ottawacitizen.com',
271 | 'ottawasun.com',
272 | 'outdoorlife.com',
273 | 'pcmag.com',
274 | 'playstationlifestyle.net',
275 | 'popphoto.com',
276 | 'popsci.com',
277 | 'ranchosantafereview.com',
278 | 'range365.com',
279 | 'ranker.com',
280 | 'ratemyprofessors.com',
281 | 'realclearpolitics.com',
282 | 'realitytea.com',
283 | 'redeyechicago.com',
284 | 'salon.com',
285 | 'saltwatersportsman.com',
286 | 'sandiegouniontribune.com',
287 | 'saveur.com',
288 | 'scubadiving.com',
289 | 'scubadivingintro.com',
290 | 'seattlepi.com',
291 | 'sfgate.com',
292 | 'sherdog.com',
293 | 'slate.com',
294 | 'slickdeals.net',
295 | 'southflorida.com',
296 | 'space.com',
297 | 'spin.com',
298 | 'sporcle.com',
299 | 'sportdiver.com',
300 | 'sportfishingmag.com',
301 | 'sportingnews.com',
302 | 'sportrider.com',
303 | 'spox.com',
304 | 'stereogum.com',
305 | 'streetchopperweb.com',
306 | 'sun-sentinel.com',
307 | 'superherohype.com',
308 | 'superstreetbike.com',
309 | 'tenplay.com.au',
310 | 'tf2outpost.com',
311 | 'thebalance.com',
312 | 'thefashionspot.com',
313 | 'theprovince.com',
314 | 'thespruce.com',
315 | 'thestarphoenix.com',
316 | 'thoughtcatalog.com',
317 | 'thoughtco.com',
318 | 'timeanddate.com',
319 | 'timesunion.com',
320 | 'tomsguide.com',
321 | 'tomsguide.fr',
322 | 'tomshardware.co.uk',
323 | 'tomshardware.com',
324 | 'tomshardware.de',
325 | 'tomshardware.fr',
326 | 'torontosun.com',
327 | 'totalbeauty.com',
328 | 'trustedreviews.com',
329 | 'tv.com',
330 | 'tvguide.com',
331 | 'tvtropes.org',
332 | 'twincities.com',
333 | 'utvdriver.com',
334 | 'vancouversun.com',
335 | 'vg.no',
336 | 'vibe.com',
337 | 'wakeboardingmag.com',
338 | 'washingtonpost.com',
339 | 'waterskimag.com',
340 | 'wetteronline.de',
341 | 'wibc.com',
342 | 'wikia.com',
343 | 'windowscentral.com',
344 | 'windsorstar.com',
345 | 'winnipegsun.com',
346 | 'workingmother.com',
347 | 'wowhead.com',
348 | 'wrestlezone.com',
349 | 'xda-developers.com',
350 | 'yachtingmagazine.com',
351 | 'zam.com',
352 | ]
353 | });
354 | })();
355 |
356 | /*******************************************************************************
357 |
358 | Instart Logic buster: v2
359 |
360 | https://github.com/uBlockOrigin/uAssets/issues/227#issuecomment-268409666
361 |
362 | **/
363 |
364 | (function() {
365 | if ( abort ) { return; }
366 |
367 | var scriptlet = function() {
368 | var magic = String.fromCharCode(Date.now() % 26 + 97) +
369 | Math.floor(Math.random() * 982451653 + 982451653).toString(36);
370 | var makeNanovisorProxy = function() {
371 | return new Proxy({}, {
372 | get: function(target, name) {
373 | switch ( name ) {
374 | case 'HtmlStreaming':
375 | return {
376 | InsertTags: function(a, b) {
377 | document.write(b); // jshint ignore:line
378 | },
379 | InterceptNode: function() {
380 | },
381 | PatchBegin: function() {
382 | },
383 | PatchEnd: function() {
384 | },
385 | PatchInit: function() {
386 | },
387 | ReloadWithNoHtmlStreaming: function() {
388 | window.location.reload(true);
389 | },
390 | RemoveTags: function() {
391 | },
392 | UpdateAttributes: function() {
393 | }
394 | };
395 | default:
396 | return target[name];
397 | }
398 | },
399 | set: function(target, name, value) {
400 | switch ( name ) {
401 | case 'CanRun':
402 | target.CanRun = function() {
403 | return false;
404 | };
405 | break;
406 | default:
407 | target[name] = value;
408 | }
409 | }
410 | });
411 | };
412 | var instartInit;
413 | window.I10C = window.I11C = makeNanovisorProxy();
414 | window.INSTART = new Proxy({}, {
415 | get: function(target, name) {
416 | switch ( name ) {
417 | case 'Init':
418 | return function(a) {
419 | if (
420 | a instanceof Object &&
421 | typeof a.nanovisorGlobalNameSpace === 'string' &&
422 | a.nanovisorGlobalNameSpace !== ''
423 | ) {
424 | window[a.nanovisorGlobalNameSpace] = makeNanovisorProxy();
425 | }
426 | a.enableHtmlStreaming = false;
427 | a.enableQSCallDiffComputationConfig = false;
428 | a.enableQuerySelectorMonitoring = false;
429 | a.serveNanovisorSameDomain = false;
430 | a.virtualDomains = 0;
431 | a.virtualizeDomains = [];
432 | instartInit(a);
433 | };
434 | default:
435 | if ( target[name] === undefined ) {
436 | throw new Error(magic);
437 | }
438 | return target[name];
439 | }
440 | },
441 | set: function(target, name, value) {
442 | switch ( name ) {
443 | case 'Init':
444 | instartInit = value;
445 | break;
446 | default:
447 | target[name] = value;
448 | }
449 | }
450 | });
451 | var oe = window.error;
452 | window.onerror = function(msg, src, line, col, error) {
453 | if ( msg.indexOf(magic) !== -1 ) {
454 | return true;
455 | }
456 | if ( oe instanceof Function ) {
457 | return oe(msg, src, line, col, error);
458 | }
459 | }.bind();
460 | };
461 |
462 | scriptlets.push({
463 | scriptlet: scriptlet,
464 | targets: [
465 | 'calgaryherald.com',
466 | 'edmontonjournal.com',
467 | 'financialpost.com',
468 | 'leaderpost.com',
469 | 'montrealgazette.com',
470 | 'nationalpost.com',
471 | 'ottawacitizen.com',
472 | 'theprovince.com',
473 | 'thestarphoenix.com',
474 | 'windsorstar.com',
475 | ]
476 | });
477 | })();
478 |
479 | /*******************************************************************************
480 |
481 | Instart Logic console detection defuser.
482 |
483 | To allow using the dev tools to investigate IL's code:
484 | - Un-comment out the block of code
485 | - Add the site you wish to investigate in the `targets` array.
486 |
487 | **/
488 |
489 |
490 | (function() {
491 | if ( abort ) { return; }
492 |
493 | var scriptlet = function() {
494 | var realConsole = console,
495 | realLog = console.log;
496 | console.log = function () {
497 | for ( var i = 0; i < arguments.length; i++ ) {
498 | if ( arguments[i] instanceof HTMLElement ) { return; }
499 | }
500 | return realLog.apply(realConsole, arguments);
501 | }.bind(console);
502 | Object.defineProperty(console.log, 'name', { value: 'log' });
503 | };
504 |
505 | scriptlets.push({
506 | scriptlet: scriptlet,
507 | targets: [
508 | 'laptopmag.com'
509 | ]
510 | });
511 | })();
512 |
513 | /*******************************************************************************
514 |
515 | Upmanager
516 |
517 | https://github.com/uBlockOrigin/uAssets/issues/251#issuecomment-276257642
518 |
519 | **/
520 |
521 | (function() {
522 | if ( abort ) { return; }
523 |
524 | var scriptlet = function() {
525 | var magic = String.fromCharCode(Date.now() % 26 + 97) +
526 | Math.floor(Math.random() * 982451653 + 982451653).toString(36);
527 | var oe = window.error;
528 | window.onerror = function(msg, src, line, col, error) {
529 | if ( msg.indexOf(magic) !== -1 ) { return true; }
530 | if ( oe instanceof Function ) {
531 | return oe(msg, src, line, col, error);
532 | }
533 | }.bind();
534 | Object.defineProperty(window, 'upManager', {
535 | set: function() {
536 | throw new Error(magic);
537 | }
538 | });
539 | };
540 |
541 | scriptlets.push({
542 | scriptlet: scriptlet,
543 | targets: [
544 | '101greatgoals.com',
545 | '4chan.org',
546 | 'allthetests.com',
547 | 'biology-online.org',
548 | 'destructoid.com',
549 | 'eurweb.com',
550 | 'fullmatchesandshows.com',
551 | 'grammarist.com',
552 | 'jerusalemonline.com',
553 | 'lucianne.com',
554 | 'phonesreview.co.uk',
555 | 'thefreethoughtproject.com',
556 | 'veteranstoday.com',
557 | 'walla.co.il',
558 | 'yad2.co.il',
559 | ]
560 | });
561 | })();
562 |
563 | /*******************************************************************************
564 |
565 | Collate and add scriptlets to document.
566 |
567 | **/
568 |
569 | (function() {
570 | if ( scriptlets.length === 0 ) { return; }
571 |
572 | var restrFromString = function(s) {
573 | return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
574 | };
575 |
576 | var reFromArray = function(aa) {
577 | return new RegExp('(^|\\.)(' + aa.map(restrFromString).join('|') + ')$');
578 | };
579 |
580 | var scriptText = [], entry, re;
581 |
582 | while ( (entry = scriptlets.shift()) ) {
583 | if ( Array.isArray(entry.targets) ) {
584 | re = reFromArray(entry.targets);
585 | if ( re.test(hostname) === false ) { continue; }
586 | } else if ( Array.isArray(entry.exceptions) ) {
587 | re = reFromArray(entry.exceptions);
588 | if ( re.test(hostname) ) { continue; }
589 | }
590 | scriptText.push('(' + entry.scriptlet.toString() + ')("' + contentScriptSecret + '");');
591 | }
592 |
593 | if ( scriptText.length === 0 ) { return; }
594 |
595 | var elem = document.createElement('script');
596 | elem.appendChild(document.createTextNode(scriptText.join('\n')));
597 | try {
598 | (document.head || document.documentElement).appendChild(elem);
599 | } catch(ex) {
600 | }
601 | // Remove the script tag once executed (leave a clean DOM behind).
602 | elem.textContent = '';
603 | if ( elem.parentNode ) {
604 | elem.parentNode.removeChild(elem);
605 | }
606 | })();
607 |
608 |
609 |
610 | })();
611 |
--------------------------------------------------------------------------------
/src/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiCybora/NanoDefenderFirefox/2006d69afdefbbb2dcd1b2dca31bb2a516efc4d1/src/icon128.png
--------------------------------------------------------------------------------
/src/libdom.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A lightweight DOM manipulation library, will be expanded as needed.
3 | * Behaves quite differently than jQuery.
4 | */
5 | "use strict";
6 |
7 |
8 | /**
9 | * Shortcut for new $.Selection(input).
10 | * @function
11 | * @param {string} input - The query selector.
12 | * @return {$.Selection} The selection object.
13 | */
14 | var $ = input => new $.Selection(input);
15 |
16 | /**
17 | * Selection class.
18 | * Unless otherwise specified, all methods return the keyword this.
19 | * @class
20 | */
21 | $.Selection = class {
22 | /**
23 | * Constructor.
24 | * @constructor
25 | * @param {string} selector - The query selector.
26 | * @param {Array.} [override=undefined] - If this parameter
27 | * is present, current selection will be set to it and the query selector
28 | * will be ignored.
29 | */
30 | constructor(selector, override) {
31 | /**
32 | * The selected elements.
33 | * @member {Array.}
34 | */
35 | this.selection = override ? override : Array.from(document.querySelectorAll(selector));
36 | /**
37 | * The amount of selected elements.
38 | * @member {integer}
39 | */
40 | this.length = this.selection.length;
41 | }
42 |
43 |
44 | /**
45 | * Set or update CSS of all selected elements.
46 | * @method
47 | * @param {string} key - The key of the style, use "maxHeight" instead of
48 | * "max-height", similar for other keys with dashes in them.
49 | * @param {string} val - The value to set.
50 | */
51 | css(key, val) {
52 | for (let s of this.selection) {
53 | s.style[key] = val;
54 | }
55 | return this;
56 | }
57 | /**
58 | * Show all selected elements.
59 | * @method
60 | * @param {string} [state="block"] - The state to apply, defaults to
61 | * "block".
62 | */
63 | show(state = "block") {
64 | return this.css("display", state);
65 | }
66 | /**
67 | * Hide all selected elements. Current display mode will not be saved.
68 | * Things may break if you try to show them again.
69 | * @method
70 | */
71 | hide() {
72 | return this.css("display", "none");
73 | }
74 | /**
75 | * Remove all selected elements from DOM.
76 | * @method
77 | */
78 | remove() {
79 | for (let s of this.selection) {
80 | s.remove();
81 | }
82 | return this;
83 | }
84 | /**
85 | * Add classes to all selected elements.
86 | * @method
87 | * @param {string} ...args - Classes to add.
88 | */
89 | addClass(...args) {
90 | for (let s of this.selection) {
91 | s.classList.add(...args);
92 | }
93 | return this;
94 | }
95 | /**
96 | * Remove classes from all selected elements.
97 | * @method
98 | * @param {string} [...args=[]] - Classes to remove, omit to remove all.
99 | */
100 | rmClass(...args) {
101 | if (args.length) {
102 | for (let s of this.selection) {
103 | s.classList.remove(...args);
104 | }
105 | } else {
106 | for (let s of this.selection) {
107 | s.className = "";
108 | }
109 | }
110 | return this;
111 | }
112 |
113 |
114 | /**
115 | * Copy current selection, this is useful when you do not want selection
116 | * methods to update current selection.
117 | * @method
118 | * @return {$.Selection} The new Selection object.
119 | */
120 | copy() {
121 | return new $.Selection(null, this.selection.slice());
122 | }
123 | /**
124 | * Update current selection, only keep the selected element with given
125 | * index.
126 | * Clear current selection if no selected element has that index.
127 | * @method
128 | * @param {integer} i - The index, give a negative number to count from
129 | * end.
130 | */
131 | eq(i) {
132 | if (this.selection.length) {
133 | if (i < 0) {
134 | i += this.selection.length;
135 | }
136 | if (i >= 0 && i < this.selection.length) {
137 | this.selection = [this.selection[i]];
138 | this.length = 1;
139 | } else {
140 | this.selection = [];
141 | this.length = 0;
142 | }
143 | }
144 | return this;
145 | }
146 | /**
147 | * Update current selection, only keep the first selected element.
148 | * @method
149 | */
150 | first() {
151 | return this.eq(0);
152 | }
153 | /**
154 | * Update current selection, only keep the last selected element.
155 | * @method
156 | */
157 | last() {
158 | return this.eq(-1);
159 | }
160 | /**
161 | * Update current selection, set it to children of each selected elements
162 | * that match the new selector.
163 | * @method
164 | * @param {string} selector - The new query selector.
165 | */
166 | find(selector) {
167 | let newSelection = [];
168 | for (const s of this.selection) {
169 | const elems = s.querySelectorAll(selector);
170 | // newSelection = newSelection.concat(elems); also works, but this
171 | // creates a new array every time, so it may not be faster
172 | //
173 | // Note that the number of arguments is capped at around 30,000
174 | // depending on the browser, but there should not be that many
175 | // elements in the document
176 | newSelection.push(...elems);
177 | }
178 | this.selection = newSelection;
179 | this.length = newSelection.length;
180 | return this;
181 | }
182 | /**
183 | * Update current selection, set it to immediate children of each selected
184 | * elements that match the new selector.
185 | * @method
186 | * @param {string} selector - The new query selector.
187 | */
188 | children(selector) {
189 | return this.find(":scope > " + selector);
190 | }
191 | /**
192 | * Update current selection, set it to the parent of each selected
193 | * elements if exist.
194 | * Elements that do not have a parent will not be updated.
195 | * @method
196 | */
197 | parent() {
198 | for (let i = 0; i < this.selection.length; i++) {
199 | const elem = this.selection[i].parentNode;
200 | if (elem) {
201 | this.selection[i] = elem;
202 | }
203 | }
204 | return this;
205 | }
206 | /**
207 | * Update current selection, only keep elements that have children
208 | * matching a given selector.
209 | * @method
210 | * @param {string} selector - The query selector.
211 | * @param {boolean} [match=true] - Set to false to only keep elements
212 | * that do not have children matching the selector.
213 | */
214 | filter(selector, match = true) {
215 | let newSelection = [];
216 | for (const s of this.selection) {
217 | if (match === Boolean(s.querySelector(selector))) {
218 | newSelection.push(s);
219 | }
220 | }
221 | this.selection = newSelection;
222 | this.length = newSelection.length;
223 | return this;
224 | }
225 | /**
226 | * Update current selection, only keep elements that have the matcher
227 | * string in their textContent.
228 | * @method
229 | * @param {string} matcher - The matcher string.
230 | */
231 | includes(matcher) {
232 | let newSelection = [];
233 | for (const s of this.selection) {
234 | if (s.textContent.includes(matcher)) {
235 | newSelection.push(s);
236 | }
237 | }
238 | this.selection = newSelection;
239 | this.length = newSelection.length;
240 | return this;
241 | }
242 | /**
243 | * Update current selection, only keep elements that have the matcher
244 | * string as the beginning of their textContent.
245 | * @method
246 | * @param {string} matcher - The matcher string.
247 | */
248 | startsWith(matcher) {
249 | let newSelection = [];
250 | for (const s of this.selection) {
251 | if (s.textContent.startsWith(matcher)) {
252 | newSelection.push(s);
253 | }
254 | }
255 | this.selection = newSelection;
256 | this.length = newSelection.length;
257 | return this;
258 | }
259 | /**
260 | * Update current selection, only keep elements that have the matcher
261 | * string as the ending of their textContent.
262 | * @method
263 | * @param {string} matcher - The matcher string.
264 | */
265 | endsWith(matcher) {
266 | let newSelection = [];
267 | for (const s of this.selection) {
268 | if (s.textContent.endsWith(matcher)) {
269 | newSelection.push(s);
270 | }
271 | }
272 | this.selection = newSelection;
273 | this.length = newSelection.length;
274 | return this;
275 | }
276 | /**
277 | * Update current selection, only keep elements that have the matcher
278 | * string as their textContent.
279 | * @method
280 | * @param {string} matcher - The matcher string.
281 | */
282 | textIs(matcher) {
283 | let newSelection = [];
284 | for (const s of this.selection) {
285 | if (matcher === s.textContent) {
286 | newSelection.push(s);
287 | }
288 | }
289 | this.selection = newSelection;
290 | this.length = newSelection.length;
291 | return this;
292 | }
293 |
294 |
295 | /**
296 | * Add an event listener to all selected elements.
297 | * @param {string} ...args - Listener details
298 | * @param {Event} e - The appropriate event object.
299 | */
300 | on(...args) {
301 | for (let s of this.selection) {
302 | s.addEventListener(...args);
303 | }
304 | return this;
305 | }
306 | /**
307 | * Trigger a click event to all selected elements.
308 | * @method
309 | */
310 | click() {
311 | for (let s of this.selection) {
312 | s.click();
313 | }
314 | return this;
315 | }
316 |
317 |
318 | /**
319 | * Get or set textContent. Affects only the first element on get mode,
320 | * but affects all selected elements in set mode.
321 | * @method
322 | * @param {string} [text=undefined] - The text to set, omit to get.
323 | * @return {string|this} String in get mode, the keyword this in set mode.
324 | * An empty string will be returned if the textContent cannot be
325 | * retrieved.
326 | */
327 | text(text) {
328 | if (text === undefined) {
329 | return this.selection.length ? this.selection[0].textContent : "";
330 | } else {
331 | for (let s of this.selection) {
332 | s.textContent = text;
333 | }
334 | return this;
335 | }
336 | }
337 | /**
338 | * Get or set innerHTML. Affects only the first element on get mode, but
339 | * affects all selected elements in set mode.
340 | * @method
341 | * @param {DOMString} [html=undefined] - The DOM string to set, omit to
342 | * get.
343 | * @return {DOMString|this} DOM string in get mode, the keyword this in
344 | * set mode. An empty string will be returned if the innerHTML cannot
345 | * be retrieved.
346 | */
347 | html(html) {
348 | if (html === undefined) {
349 | return this.selection.length ? this.selection[0].innerHTML : "";
350 | } else {
351 | for (let s of this.selection) {
352 | s.innerHTML = html;
353 | }
354 | return this;
355 | }
356 | }
357 | /**
358 | * Get or set data. Affects only the first element on get mode, but
359 | * affects all selected elements in set mode.
360 | * @method
361 | * @param {string} name - The name of the data entry.
362 | * @param {string} [val=undefined] - The value to set, omit to get.
363 | * @return {Any|this} The data in get mode, the keyword this in set mode.
364 | * Undefined will be returned if the data cannot be retrieved.
365 | */
366 | data(name, val) {
367 | if (val === undefined) {
368 | return this.selection.length ? this.selection[0].dataset[name] : undefined;
369 | } else {
370 | for (let s of this.selection) {
371 | s.dataset[name] = val;
372 | }
373 | return this;
374 | }
375 | }
376 | /**
377 | * Get or set attribute. Affect only the first element on get mode, but
378 | * affect all selected elements in set mode.
379 | * @method
380 | * @param {string} name - The name of the attribute.
381 | * @param {string} [val=undefined] - The value to set, omit to get.
382 | * @return {Any|this} The attribute in get mode, the keyword this in set
383 | * mode. Undefined will be returned if the attribute cannot be retrieved.
384 | */
385 | attr(name, val) {
386 | if (val === undefined) {
387 | return this.selection.length ? this.selection[0].getAttribute(name) : undefined;
388 | } else {
389 | for (let s of this.selection) {
390 | s.setAttribute(name, val);
391 | }
392 | return this;
393 | }
394 | }
395 | /**
396 | * Delete an attribute.
397 | * @method
398 | * @param {string} name - The name of the attribute.
399 | */
400 | rmAttr(name) {
401 | for (let s of this.selection) {
402 | s.removeAttribute(name);
403 | }
404 | return this;
405 | }
406 | /**
407 | * Get or set property. Affect only the first element on get mode, but
408 | * affect all selected elements in set mode.
409 | * @method
410 | * @param {string} name - The name of the property.
411 | * @param {string} [val=undefined] - The value to set, omit to get.
412 | * @return {Any|this} The property in get mode, the keyword this in set
413 | * mode. Undefined will be returned if the property cannot be retrieved.
414 | */
415 | prop(name, val) {
416 | if (val === undefined) {
417 | return this.selection.length ? this.selection[0][name] : undefined;
418 | } else {
419 | for (let s of this.selection) {
420 | s[name] = val;
421 | }
422 | return this;
423 | }
424 | }
425 |
426 |
427 | /**
428 | * Insert HTML before the beginning of each selected elements if possible.
429 | * @method
430 | * @param {DOMString} input - The DOM string to insert.
431 | */
432 | before(input) {
433 | for (let s of this.selection) {
434 | // Must have parent node in this insert mode
435 | if (s.parentNode) {
436 | s.insertAdjacentHTML("beforebegin", input);
437 | }
438 | }
439 | return this;
440 | }
441 | /**
442 | * Insert HTML after the beginning of each selected elements.
443 | * @method
444 | * @param {DOMString} input - The DOM string to insert.
445 | */
446 | prepend(input) {
447 | for (let s of this.selection) {
448 | s.insertAdjacentHTML("afterbegin", input);
449 | }
450 | return this;
451 | }
452 | /**
453 | * Insert HTML before the end of each selected elements.
454 | * @method
455 | * @param {DOMString} input - The DOM string to insert.
456 | */
457 | append(input) {
458 | for (let s of this.selection) {
459 | s.insertAdjacentHTML("beforeend", input);
460 | }
461 | return this;
462 | }
463 | /**
464 | * Insert HTML after the end of each selected elements if possible.
465 | * @method
466 | * @param {DOMString} input - The DOM string to insert.
467 | */
468 | after(input) {
469 | for (let s of this.selection) {
470 | // Must have parent node in this insert mode
471 | if (s.parentNode) {
472 | s.insertAdjacentHTML("afterend", input);
473 | }
474 | }
475 | return this;
476 | }
477 |
478 |
479 | /**
480 | * Get offsetWidth of the first selected element.
481 | * @method
482 | * @return {integer} The offsetWidth, or -1 if the offsetWidth cannot be
483 | * retrieved.
484 | */
485 | width() {
486 | return this.selection.length ? this.selection[0].offsetWidth : -1;
487 | }
488 | /**
489 | * Get offsetHeight of the first selected element.
490 | * @method
491 | * @return {integer} The offsetHeight, or -1 if the offsetHeight cannot be
492 | * retrieved.
493 | */
494 | height() {
495 | return this.selection.length ? this.selection[0].offsetHeight : -1;
496 | }
497 | /**
498 | * Loop though each selected element.
499 | * @method
500 | * @param {Function} func - The handler.
501 | * @param {DOMElement} elem - The current DOM element.
502 | */
503 | each(func) {
504 | for (let s of this.selection) {
505 | func(s);
506 | }
507 | return this;
508 | }
509 | };
510 |
511 |
512 | /**
513 | * Send a XMLHttpRequest.
514 | * @function
515 | * @param {Object} details - Details about this request.
516 | * @param {string} method - The method of the request, usually "GET" or
517 | * "POST".
518 | * @param {string} url - The URL of the request.
519 | * @param {Object|undefined} [headers=undefined] - The headers of the
520 | * request.
521 | * @param {string|null} [payload=null] - The payload of the request.
522 | * @param {Function} onload - The load event handler.
523 | * @param {string} response - The response text.
524 | * @param {Function} onerror - The error event handler.
525 | */
526 | $.request = (details, onload, onerror) => {
527 | let req = new XMLHttpRequest();
528 |
529 | req.onreadystatechange = () => {
530 | if (req.readyState === XMLHttpRequest.DONE) {
531 | if (req.status === 200) {
532 | onload(req.responseText);
533 | } else {
534 | onerror();
535 | }
536 | }
537 | };
538 |
539 | req.open(details.method, details.url);
540 |
541 | if (details.headers) {
542 | for (const key in details.headers) {
543 | if (details.headers.hasOwnProperty(key)) {
544 | req.setRequestHeader(key, details.headers[key]);
545 | }
546 | }
547 | }
548 |
549 | req.send(details.payload || null);
550 | };
551 |
--------------------------------------------------------------------------------
/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "Nano Defender Contributors",
3 | "background": {
4 | "scripts": [
5 | "common.js",
6 | "platform/chromium-vars.js",
7 | "background/core.js",
8 | "background/rules.js",
9 | "background/debug.js"
10 | ]
11 | },
12 | "browser_action": {
13 | "default_icon": {
14 | "128": "icon128.png"
15 | },
16 | "default_popup": "popup/index.html",
17 | "default_title": "Nano Defender Debug"
18 | },
19 | "content_scripts": [
20 | {
21 | "all_frames": true,
22 | "js": [
23 | "common.js",
24 | "libdom.js",
25 | "content/core.js",
26 | "content/rules-common.js",
27 | "content/rules-specific.js",
28 | "content/rules-sticky.js",
29 | "content/debug.js",
30 | "content/ubo-extra.js"
31 | ],
32 | "match_about_blank": true,
33 | "matches": [
34 | "http://*/*",
35 | "https://*/*"
36 | ],
37 | "run_at": "document_start"
38 | }
39 | ],
40 | "description": "Companion extension for Nano Adblocker",
41 | "homepage_url": "https://jspenguin2017.github.io/uBlockProtector/",
42 | "icons": {
43 | "128": "icon128.png"
44 | },
45 | "incognito": "split",
46 | "manifest_version": 2,
47 | "minimum_chrome_version": "69.0",
48 | "name": "Nano Defender Debug",
49 | "permissions": [
50 | "http://*/*",
51 | "https://*/*",
52 | "tabs",
53 | "webNavigation",
54 | "webRequest",
55 | "webRequestBlocking"
56 | ],
57 | "version": "15.0.0.206",
58 | "web_accessible_resources": [
59 | "resources/*"
60 | ]
61 | }
62 |
--------------------------------------------------------------------------------
/src/platform/chromium-vars.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------------- //
2 |
3 | // Nano Defender - An anti-adblock defuser
4 | // Copyright (C) 2016-2019 Nano Defender contributors
5 | //
6 | // This program is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation, either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program. If not, see .
18 |
19 | // ----------------------------------------------------------------------------------------------------------------- //
20 |
21 | // Platform constants for Chromium
22 |
23 | // ----------------------------------------------------------------------------------------------------------------- //
24 |
25 | "use strict";
26 |
27 | // ----------------------------------------------------------------------------------------------------------------- //
28 |
29 | a.NanoAdblockerExtensionID = "gabbbocakeomblphkmmnoamkioajlkfo";
30 |
31 | if (navigator.userAgent.includes(" Edg/"))
32 | a.NanoAdblockerExtensionID = "epbkapkgcmdmfpogenoebpdeibmfinpf";
33 |
34 | // ----------------------------------------------------------------------------------------------------------------- //
35 |
--------------------------------------------------------------------------------
/src/platform/edge-content.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------------- //
2 |
3 | // Nano Defender - An anti-adblock defuser
4 | // Copyright (C) 2016-2019 Nano Defender contributors
5 | //
6 | // This program is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation, either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program. If not, see .
18 |
19 | // ----------------------------------------------------------------------------------------------------------------- //
20 |
21 | // Special content script for legacy Edge
22 |
23 | // ----------------------------------------------------------------------------------------------------------------- //
24 |
25 | "use strict";
26 |
27 | // ----------------------------------------------------------------------------------------------------------------- //
28 |
29 | if (a.domCmp(["windowscentral.com"])) {
30 | a.noAccess("adonisHash");
31 | a.beforeScript((script) => {
32 | if (script.textContent && script.textContent.includes("adBlocker")) {
33 | script.remove();
34 | }
35 | });
36 | }
37 |
38 | // ----------------------------------------------------------------------------------------------------------------- //
39 |
--------------------------------------------------------------------------------
/src/platform/edge-vars.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------------- //
2 |
3 | // Nano Defender - An anti-adblock defuser
4 | // Copyright (C) 2016-2019 Nano Defender contributors
5 | //
6 | // This program is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation, either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program. If not, see .
18 |
19 | // ----------------------------------------------------------------------------------------------------------------- //
20 |
21 | // Platform constants for legacy Edge
22 |
23 | // ----------------------------------------------------------------------------------------------------------------- //
24 |
25 | "use strict";
26 |
27 | // ----------------------------------------------------------------------------------------------------------------- //
28 |
29 | a.NanoAdblockerExtensionID = "EdgeExtension_23837jspenguin2017NanoAdblocker_aegazecm1370c";
30 |
31 | // ----------------------------------------------------------------------------------------------------------------- //
32 |
--------------------------------------------------------------------------------
/src/platform/firefox-background.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------------- //
2 |
3 | // Nano Defender - An anti-adblock defuser
4 | // Copyright (C) 2016-2019 Nano Defender contributors
5 | //
6 | // This program is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation, either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program. If not, see .
18 |
19 | // ----------------------------------------------------------------------------------------------------------------- //
20 |
21 | // Special background script for Firefox
22 |
23 | // ----------------------------------------------------------------------------------------------------------------- //
24 |
25 | "use strict";
26 |
27 | // ----------------------------------------------------------------------------------------------------------------- //
28 |
29 | //@pragma-if-debug
30 |
31 | // Debug rules
32 |
33 | if (a.debugMode) {
34 |
35 | {
36 | // https://github.com/uBlockOrigin/uAssets/issues/772
37 |
38 | a.dynamicServer(
39 | [
40 | "*://*.uplynk.com/preplay/*",
41 | ],
42 | [
43 | "xmlhttprequest",
44 | ],
45 | (details) => {
46 | let payload = "";
47 |
48 | const filter = browser.webRequest.filterResponseData(details.requestId);
49 | const decoder = new TextDecoder("utf-8");
50 | const encoder = new TextEncoder();
51 |
52 | filter.ondata = (e) => {
53 | payload += decoder.decode(e.data, { stream: true });
54 | };
55 | filter.onstop = () => {
56 | try {
57 | payload = JSON.parse(payload);
58 | } catch (err) {
59 | filter.write(encoder.encode(payload));
60 | filter.disconnect();
61 | return;
62 | }
63 |
64 | // Debug log
65 | console.log(payload.ads);
66 |
67 | payload.ads = {
68 | breakOffsets: [],
69 | breaks: [],
70 | placeholderOffsets: [],
71 | };
72 |
73 | filter.write(encoder.encode(JSON.stringify(payload)));
74 | filter.disconnect();
75 | };
76 | },
77 | [
78 | "fox.com",
79 | ],
80 | true,
81 | );
82 | }
83 |
84 | }
85 |
86 | //@pragma-end-if
87 |
88 | // ----------------------------------------------------------------------------------------------------------------- //
89 |
--------------------------------------------------------------------------------
/src/platform/firefox-content.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------------- //
2 |
3 | // Nano Defender - An anti-adblock defuser
4 | // Copyright (C) 2016-2019 Nano Defender contributors
5 | //
6 | // This program is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation, either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program. If not, see .
18 |
19 | // ----------------------------------------------------------------------------------------------------------------- //
20 |
21 | // Special content script for Firefox
22 |
23 | // ----------------------------------------------------------------------------------------------------------------- //
24 |
25 | "use strict";
26 |
27 | // ----------------------------------------------------------------------------------------------------------------- //
28 |
29 | // Simply removing the node does not prevent execution of the script
30 |
31 | {
32 | const _remove = Element.prototype.remove;
33 | const remove = function () {
34 | if (this.tagName === "SCRIPT") {
35 | this.textContent = "";
36 | }
37 | _remove.call(this);
38 | };
39 | Element.prototype.remove = remove;
40 | }
41 |
42 | // ----------------------------------------------------------------------------------------------------------------- //
43 |
--------------------------------------------------------------------------------
/src/platform/firefox-vars.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------------- //
2 |
3 | // Nano Defender - An anti-adblock defuser
4 | // Copyright (C) 2016-2019 Nano Defender contributors
5 | //
6 | // This program is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU General Public License as published by
8 | // the Free Software Foundation, either version 3 of the License, or
9 | // (at your option) any later version.
10 | //
11 | // This program is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | // GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License
17 | // along with this program. If not, see .
18 |
19 | // ----------------------------------------------------------------------------------------------------------------- //
20 |
21 | // Platform constants for Firefox
22 |
23 | // ----------------------------------------------------------------------------------------------------------------- //
24 |
25 | "use strict";
26 |
27 | /**
28 | * The extension ID of Nano Adblocker.
29 | * @const {string}
30 | */
31 | a.NanoAdblockerExtensionID = "{0f929014-5ed2-4527-8b8d-86a9c889b129}";
32 |
--------------------------------------------------------------------------------
/src/popup/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0px;
3 | min-width: 250px;
4 | width: auto;
5 | font-family: sans-serif;
6 | background-color: #FFFFFF;
7 | user-select: none;
8 | }
9 |
10 | .title {
11 | background-color: #444444;
12 | color: #FFFFFF;
13 | font-size: 12px;
14 | text-align: center;
15 | padding: 5px;
16 | }
17 |
18 | .title > p {
19 | margin: 0px;
20 | }
21 |
22 | .wrapper {
23 | padding: 6px;
24 | }
25 |
26 | .wrapper:hover {
27 | background-color: #EEEEEE;
28 | }
29 |
30 | .wrapper > svg {
31 | margin-right: 3px;
32 | position: relative;
33 | top: 1px;
34 | width: 16px;
35 | }
36 |
37 | .wrapper > span {
38 | font-size: 14px;
39 | position: relative;
40 | top: -2px;
41 | }
42 |
43 | .separator.dashed {
44 | border-bottom: 1px dashed #CCCCCC;
45 | }
46 |
47 | .separator.solid {
48 | border-bottom: 1px solid #444444;
49 | }
50 |
--------------------------------------------------------------------------------
/src/popup/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Nano Defender Popup Panel
11 |
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
Home Page
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
Announcements
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
Troubleshooting
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
FAQ
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
Known Issues
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
Report an Issue
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
Source Code
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
License
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
Credits
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/src/popup/index.js:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 |
3 | Nano Defender - An anti-adblock defuser
4 | Copyright (C) 2016-2018 Nano Defender contributors
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 |
19 | *******************************************************************************
20 |
21 | Popup panel script.
22 |
23 | ******************************************************************************/
24 |
25 | "use strict";
26 |
27 | /*****************************************************************************/
28 |
29 | /**
30 | * Homepage links.
31 | * @const {Map}
32 | */
33 | const home = [
34 | "",
35 | "https://jspenguin2017.github.io/uBlockProtector/",
36 | "https://github.com/jspenguin2017/uBlockProtector",
37 | chrome.runtime.getURL("/reporter/index.html"),
38 | ];
39 |
40 | /*****************************************************************************/
41 |
42 | {
43 | const manifest = chrome.runtime.getManifest();
44 | $(".title > p").text(manifest.name + " " + manifest.version);
45 | }
46 |
47 | /*****************************************************************************/
48 |
49 | chrome.tabs.query({
50 | active: true,
51 | currentWindow: true,
52 | }, (tabs) => {
53 | if (chrome.runtime.lastError || tabs.length === 0)
54 | return;
55 |
56 | home[3] = home[3] + "?" + tabs[0].id;
57 | });
58 |
59 | /*****************************************************************************/
60 |
61 | $(".wrapper").on("click", function () {
62 | const url = home[this.dataset.home] + this.dataset.href;
63 | chrome.tabs.create({ url: url });
64 | });
65 |
66 | /*****************************************************************************/
67 |
--------------------------------------------------------------------------------
/src/resources/blank.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiCybora/NanoDefenderFirefox/2006d69afdefbbb2dcd1b2dca31bb2a516efc4d1/src/resources/blank.mp4
--------------------------------------------------------------------------------
/src/resources/fw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Moat FreeWheel JSPEM surrogate.
3 | */
4 | ; (() => {
5 | "use strict";
6 |
7 | try {
8 | window.console.error("[Nano] Surrogate Injected :: FreeWheel SDK");
9 | } catch (err) { }
10 |
11 | window.MoatFreeWheelJSPEM = class {
12 | init() { }
13 | dispose() { }
14 | };
15 | })();
16 |
--------------------------------------------------------------------------------
/src/resources/ima3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Interactive Media Ads Software Development Kit surrogate.
3 | * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis
4 | */
5 | ; (() => {
6 | "use strict";
7 |
8 | try {
9 | window.console.error("[Nano] Surrogate Injected :: IMA SDK");
10 | } catch (err) { }
11 |
12 | let warnCount = 0;
13 |
14 | window.google = window.google || {};
15 |
16 | // Interfaces are not implemented
17 | window.google.ima = {
18 | AdDisplayContainer: class {
19 | // constructor(container, video, click) { }
20 | initialize() { }
21 | destroy() { }
22 | },
23 |
24 | AdError: class {
25 | constructor(message, code, type) {
26 | this._message = message;
27 | this._code = code;
28 | this._type = type;
29 | }
30 | getErrorCode() {
31 | return this._code;
32 | }
33 | getInnerError() {
34 | return null;
35 | }
36 | getMessage() {
37 | return this._message;
38 | }
39 | getType() {
40 | return this._type;
41 | }
42 | getVastErrorCode() {
43 | return window.google.ima.AdError.ErrorCode.UNKNOWN_ERROR;
44 | }
45 | toString() {
46 | return "AdError " + this._code + ": " + this._message + ".";
47 | }
48 | },
49 |
50 | AdErrorEvent: class extends ErrorEvent {
51 | constructor(error, context) {
52 | super(error);
53 | this._errObj = error;
54 | this._context = context;
55 | }
56 | getError() {
57 | return this._errObj;
58 | }
59 | getUserRequestContext() {
60 | return this._context;
61 | }
62 | },
63 |
64 | AdEvent: class extends Event {
65 | constructor(type, ad, adData) {
66 | super(type);
67 | this._ad = ad;
68 | this._adData = adData;
69 | }
70 | getAd() {
71 | return this._ad;
72 | }
73 | getAdData() {
74 | return this._adData;
75 | }
76 | },
77 |
78 | AdsLoader: class {
79 | constructor() {
80 | this._onError = [];
81 | this._onErrorScope = [];
82 | this._error = new window.google.ima.AdErrorEvent(
83 | new window.google.ima.AdError(
84 | "No ads available",
85 | window.google.ima.AdError.ErrorCode.VAST_NO_ADS_AFTER_WRAPPER,
86 | window.google.ima.AdError.Type.AD_LOAD,
87 | ),
88 | {},
89 | );
90 | }
91 | addEventListener(event, handler, capture, scope) {
92 | // The real SDK should also always return error
93 | if (event === window.google.ima.AdErrorEvent.Type.AD_ERROR) {
94 | this._onError.push(handler);
95 | this._onErrorScope.push(scope);
96 | } else if (warnCount < 10) {
97 | warnCount++;
98 | try {
99 | window.console.warn("[Nano] IMA Event Ignored :: " + event);
100 | } catch (err) { }
101 | }
102 | }
103 | removeEventListener(event, handler) {
104 | // Capture and scope are not checked
105 | if (event === window.google.ima.AdErrorEvent.Type.AD_ERROR) {
106 | for (let i = 0; i < this._onError.length; i++) {
107 | // This should be good enough
108 | if (this._onError[i] === handler) {
109 | this._onError.splice(i, 1);
110 | this._onErrorScope.splice(i, 1);
111 | i--;
112 | }
113 | }
114 | }
115 | // Ignore otherwise
116 | }
117 | _dispatchError() {
118 | for (let i = 0; i < this._onError.length; i++) {
119 | if (this._onErrorScope[i]) {
120 | this._onError[i].call(this._onErrorScope[i], this._error);
121 | } else {
122 | this._onError[i](this._error);
123 | }
124 | }
125 | }
126 |
127 | contentComplete() { }
128 | destroy() { }
129 | getSettings() {
130 | return window.google.ima.settings;
131 | }
132 | requestAds() {
133 | window.setTimeout(this._dispatchError.bind(this), 10);
134 | }
135 | },
136 |
137 | AdsManagerLoadedEvent: class extends Event {
138 | constructor() {
139 | // Not implemented
140 | throw new window.Error("[Nano] Not Implemented :: Neutralized AdsManager");
141 | }
142 | },
143 |
144 | AdsRenderingSettings: class {
145 | // Not implemented
146 | // constructor() { }
147 | },
148 |
149 | AdsRequest: class {
150 | // Partially implemented
151 | // constructor() { }
152 | setAdWillAutoPlay() { }
153 | setAdWillPlayMuted() { }
154 | },
155 |
156 | CompanionAdSelectionSettings: class {
157 | // Not implemented
158 | // constructor() { }
159 | },
160 |
161 | ImaSdkSettings: class {
162 | // Partially implemented
163 | // constructor() { }
164 | getCompanionBackfill() {
165 | return window.google.ima.ImaSdkSettings.CompanionBackfillMode.ALWAYS;
166 | }
167 | getDisableCustomPlaybackForIOS10Plus() {
168 | return false;
169 | }
170 | getDisableFlashAds() {
171 | return true;
172 | }
173 | getLocale() {
174 | return "en-CA";
175 | }
176 | getNumRedirects() {
177 | return 1;
178 | }
179 | getPlayerType() {
180 | return "Unknown";
181 | }
182 | getPlayerVersion() {
183 | return "1.0.0";
184 | }
185 | getPpid() {
186 | return "2GjCgoECAP0IbU";
187 | }
188 |
189 | setAutoPlayAdBreaks() { }
190 | setCompanionBackfill() { }
191 | setDisableCustomPlaybackForIOS10Plus() { }
192 | setDisableFlashAds() { }
193 | setLocale() { }
194 | setNumRedirects() { }
195 | setPlayerType() { }
196 | setPlayerVersion() { }
197 | setPpid() { }
198 | setVpaidAllowed() { }
199 | setVpaidMode() { }
200 | },
201 |
202 | UiElements: {
203 | COUNTDOWN: "countdown",
204 | },
205 |
206 | ViewMode: {
207 | FULLSCREEN: "fullscreen",
208 | NORMAL: "normal",
209 | },
210 |
211 | VERSION: "3.173.4",
212 | };
213 |
214 | window.google.ima.AdError.ErrorCode = {
215 | VIDEO_PLAY_ERROR: 400,
216 | FAILED_TO_REQUEST_ADS: 1005,
217 | REQUIRED_LISTENERS_NOT_ADDED: 900,
218 | VAST_LOAD_TIMEOUT: 301,
219 | VAST_NO_ADS_AFTER_WRAPPER: 303,
220 | VAST_MEDIA_LOAD_TIMEOUT: 402,
221 | VAST_TOO_MANY_REDIRECTS: 302,
222 | VAST_ASSET_MISMATCH: 403,
223 | VAST_LINEAR_ASSET_MISMATCH: 403,
224 | VAST_NONLINEAR_ASSET_MISMATCH: 503,
225 | VAST_ASSET_NOT_FOUND: 1007,
226 | VAST_UNSUPPORTED_VERSION: 102,
227 | VAST_SCHEMA_VALIDATION_ERROR: 101,
228 | VAST_TRAFFICKING_ERROR: 200,
229 | VAST_UNEXPECTED_LINEARITY: 201,
230 | VAST_UNEXPECTED_DURATION_ERROR: 202,
231 | VAST_WRAPPER_ERROR: 300,
232 | NONLINEAR_DIMENSIONS_ERROR: 501,
233 | COMPANION_REQUIRED_ERROR: 602,
234 | VAST_EMPTY_RESPONSE: 1009,
235 | UNSUPPORTED_LOCALE: 1011,
236 | INVALID_ADX_EXTENSION: 1105,
237 | INVALID_ARGUMENTS: 1101,
238 | UNKNOWN_AD_RESPONSE: 1010,
239 | UNKNOWN_ERROR: 900,
240 | OVERLAY_AD_PLAYING_FAILED: 500,
241 | VIDEO_ELEMENT_USED: -1,
242 | VIDEO_ELEMENT_REQUIRED: -1,
243 | VAST_MEDIA_ERROR: -1,
244 | ADSLOT_NOT_VISIBLE: -1,
245 | OVERLAY_AD_LOADING_FAILED: -1,
246 | VAST_MALFORMED_RESPONSE: -1,
247 | COMPANION_AD_LOADING_FAILED: -1,
248 | };
249 |
250 | window.google.ima.AdError.Type = {
251 | AD_LOAD: "adLoadError",
252 | AD_PLAY: "adPlayError",
253 | };
254 |
255 | window.google.ima.AdErrorEvent.Type = {
256 | AD_ERROR: "adError",
257 | };
258 |
259 | window.google.ima.AdEvent.Type = {
260 | CONTENT_RESUME_REQUESTED: "contentResumeRequested",
261 | CONTENT_PAUSE_REQUESTED: "contentPauseRequested",
262 | CLICK: "click",
263 | DURATION_CHANGE: "durationChange",
264 | EXPANDED_CHANGED: "expandedChanged",
265 | STARTED: "start",
266 | IMPRESSION: "impression",
267 | PAUSED: "pause",
268 | RESUMED: "resume",
269 | FIRST_QUARTILE: "firstquartile",
270 | MIDPOINT: "midpoint",
271 | THIRD_QUARTILE: "thirdquartile",
272 | COMPLETE: "complete",
273 | USER_CLOSE: "userClose",
274 | LINEAR_CHANGED: "linearChanged",
275 | LOADED: "loaded",
276 | AD_CAN_PLAY: "adCanPlay",
277 | AD_METADATA: "adMetadata",
278 | AD_BREAK_READY: "adBreakReady",
279 | INTERACTION: "interaction",
280 | ALL_ADS_COMPLETED: "allAdsCompleted",
281 | SKIPPED: "skip",
282 | SKIPPABLE_STATE_CHANGED: "skippableStateChanged",
283 | LOG: "log",
284 | VIEWABLE_IMPRESSION: "viewable_impression",
285 | VOLUME_CHANGED: "volumeChange",
286 | VOLUME_MUTED: "mute",
287 | };
288 |
289 | window.google.ima.AdsManagerLoadedEvent.Type = {
290 | ADS_MANAGER_LOADED: "adsManagerLoaded",
291 | };
292 |
293 | window.google.ima.CompanionAdSelectionSettings.CreativeType = {
294 | ALL: "All",
295 | FLASH: "Flash",
296 | IMAGE: "Image",
297 | };
298 |
299 | window.google.ima.CompanionAdSelectionSettings.ResourceType = {
300 | ALL: "All",
301 | HTML: "Html",
302 | IFRAME: "IFrame",
303 | STATIC: "Static",
304 | };
305 |
306 | window.google.ima.CompanionAdSelectionSettings.SizeCriteria = {
307 | IGNORE: "IgnoreSize",
308 | SELECT_EXACT_MATCH: "SelectExactMatch",
309 | SELECT_NEAR_MATCH: "SelectNearMatch",
310 | };
311 |
312 | window.google.ima.ImaSdkSettings.CompanionBackfillMode = {
313 | ALWAYS: "always",
314 | ON_MASTER_AD: "on_master_ad",
315 | };
316 |
317 | window.google.ima.ImaSdkSettings.VpaidMode = {
318 | DISABLED: 0,
319 | ENABLED: 1,
320 | INSECURE: 2,
321 | };
322 |
323 | window.google.ima.settings = new window.google.ima.ImaSdkSettings();
324 | })();
325 |
--------------------------------------------------------------------------------
/src/resources/jquery.js:
--------------------------------------------------------------------------------
1 | /**
2 | * jQuery Anti-adblock plugin defuser.
3 | */
4 | ; (() => {
5 | "use strict";
6 |
7 | try {
8 | window.console.error("[Nano] Generic Solution Triggered :: jQuery Plugin");
9 | } catch (err) { }
10 |
11 | try {
12 | window.$.adblock = false;
13 | } catch (err) { }
14 | try {
15 | window.jQuery.adblock = false;
16 | } catch (err) { }
17 | })();
18 |
--------------------------------------------------------------------------------
/tests/check-syntax.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Check for syntax error.
3 | */
4 | "use strict";
5 |
6 | /**
7 | * Load modules.
8 | * @const {Module}
9 | */
10 | const assert = require("assert");
11 | const esprima = require("esprima");
12 | const fs = require("./promise-fs.js");
13 |
14 | /**
15 | * Validate syntax of a JavaScript file.
16 | * @async @function
17 | * @param {string} file - The path to the file to check.
18 | */
19 | const validateJS = async (file) => {
20 | const data = await fs.readFile(file, "utf8");
21 | esprima.parse(data);
22 | };
23 | /**
24 | * Validate syntax of a JSON file.
25 | * @async @function
26 | * @param {string} file - The path to the file to check.
27 | */
28 | const validateJSON = async (file) => {
29 | const data = await fs.readFile(file, "utf8");
30 | JSON.parse(data);
31 | };
32 |
33 | /**
34 | * Check syntax recursively for one directory.
35 | * @async @function
36 | * @param {string} directory - The path to the directory to check.
37 | */
38 | exports.validateDirectory = async (directory) => {
39 | const files = await fs.readdir(directory);
40 |
41 | let tasks = [];
42 | for (const file of files) {
43 | tasks.push(fs.lstat(directory + "/" + file));
44 | }
45 | tasks = await Promise.all(tasks);
46 | assert(files.length === tasks.length);
47 |
48 | let validateTasks = [];
49 | for (let i = 0; i < files.length; i++) {
50 | assert(!tasks[i].isSymbolicLink());
51 |
52 | if (tasks[i].isDirectory()) {
53 | // One directory at a time to make sure things will not get
54 | // overloaded
55 | await exports.validateDirectory(directory + "/" + files[i]);
56 | continue;
57 | }
58 |
59 | assert(tasks[i].isFile());
60 | if (files[i].endsWith(".js")) {
61 | validateTasks.push(validateJS(directory + "/" + files[i]));
62 | } else if (files[i].endsWith(".json")) {
63 | validateTasks.push(validateJSON(directory + "/" + files[i]));
64 | }
65 | }
66 | await Promise.all(validateTasks);
67 | };
68 |
--------------------------------------------------------------------------------
/tests/promise-fs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Promisified file system module.
3 | *
4 | * Watches for "--trace-fs" command line argument, if exists
5 | * file system calls are logged.
6 | */
7 | "use strict";
8 |
9 |
10 | /**
11 | * Load modules.
12 | * @const {Module}
13 | */
14 | const fs = require("fs");
15 | const util = require("util");
16 |
17 | /**
18 | * The new file system namespace, functions are added as needed.
19 | * @const {Namespace}
20 | */
21 | const newfs = {
22 | appendFile: util.promisify(fs.appendFile),
23 | copyFile: util.promisify(fs.copyFile),
24 | createReadStream: fs.createReadStream,
25 | createWriteStream: fs.createWriteStream,
26 | lstat: util.promisify(fs.lstat),
27 | mkdir: util.promisify(fs.mkdir),
28 | readdir: util.promisify(fs.readdir),
29 | readFile: util.promisify(fs.readFile),
30 | writeFile: util.promisify(fs.writeFile),
31 | };
32 |
33 | /**
34 | * Print variables, truncate long strings.
35 | * @function
36 | * @param {Any} ...args - Variables to print.
37 | */
38 | const varDump = (...args) => {
39 | let out = [];
40 | for (const arg of args) {
41 | if (typeof arg === "string" && arg.length > 200) {
42 | out.push("");
43 | } else {
44 | out.push(arg);
45 | }
46 | }
47 | console.log(...out);
48 | };
49 | /**
50 | * Make a file system access tracer.
51 | * @function
52 | * @param {string} name - The function to intercept.
53 | * @return {Function} The tracer.
54 | */
55 | const makeTracer = (name) => {
56 | return (...args) => {
57 | varDump("fs." + name, ...args);
58 | return newfs[name](...args);
59 | };
60 | };
61 |
62 |
63 | if (process.argv.includes("--trace-fs")) {
64 | module.exports = {};
65 | for (const key in newfs) {
66 | if (newfs.hasOwnProperty(key)) {
67 | module.exports[key] = makeTracer(key);
68 | }
69 | }
70 | } else {
71 | module.exports = newfs;
72 | }
73 |
--------------------------------------------------------------------------------
/tests/tests-main.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Tests entry point.
3 | */
4 | "use strict";
5 |
6 |
7 | /**
8 | * Load modules.
9 | * @const {Module}
10 | */
11 | const assert = require("assert");
12 | const checkSyntax = require("./check-syntax.js");
13 |
14 |
15 | process.on("unhandledRejection", (e) => {
16 | throw e;
17 | });
18 |
19 | assert(/[\\/]uBlockProtector$/.test(process.cwd()));
20 |
21 | (async () => {
22 | await checkSyntax.validateDirectory("./src");
23 | })();
24 |
--------------------------------------------------------------------------------