├── .github ├── ISSUE_TEMPLATE.TXT ├── PULL_REQUEST_TEMPLATE.TXT └── workflows │ └── lock.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.MD ├── docs ├── index.css └── index.html ├── 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 ├── 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 ├── reporter │ ├── index.css │ ├── index.html │ ├── index.js │ └── paper.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/workflows/lock.yml: -------------------------------------------------------------------------------- 1 | name: 'Lock Old Threads' 2 | 3 | on: 4 | schedule: 5 | - cron: '0 */6 * * *' 6 | 7 | jobs: 8 | lock: 9 | runs-on: ubuntu-latest 10 | timeout-minutes: 120 11 | steps: 12 | - uses: dessant/lock-threads@v2 13 | with: 14 | github-token: ${{ github.token }} 15 | issue-lock-inactive-days: '14' 16 | issue-lock-labels: 'Archived' 17 | issue-lock-reason: '' 18 | pr-lock-inactive-days: '28' 19 | pr-lock-labels: 'Archived' 20 | pr-lock-reason: '' 21 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # Important Announcements Regarding Recent Changes 2 | 3 | Please read important announcements here: https://github.com/NanoAdblocker/NanoCore/issues/362 4 | 5 | # Nano Defender [![Build Status](https://travis-ci.org/jspenguin2017/uBlockProtector.svg?branch=master)](https://travis-ci.org/jspenguin2017/uBlockProtector) 6 | 7 | An anti-adblock defuser for Nano Adblocker and uBlock Origin 8 | 9 | ![Popup Panel Screenshot](https://i.imgur.com/4TEDUm7.png) 10 | 11 | ### [Get it Now](http://jspenguin2017.github.io/uBlockProtector/) 12 | 13 | *Formerly uBlock Protector. Repository name will not be updated as it would 14 | break too many links.* 15 | 16 | ## Building 17 | 18 | Nano Defender is built using 19 | [Nano Build](https://github.com/NanoAdblocker/NanoBuild). 20 | 21 | ## Credits 22 | 23 | Nano Defender uses open source code from the following projects (alphabetical): 24 | 25 | [reek/anti-adblock-killer](https://github.com/reek/anti-adblock-killer) 26 | 27 | [primer/octicons](https://github.com/primer/octicons/) 28 | 29 | [uBlockOrigin/uAssets](https://github.com/uBlockOrigin/uAssets) 30 | 31 | [gorhill/uBlock](https://github.com/gorhill/uBlock) 32 | 33 | [gorhill/uBO-Extra](https://github.com/gorhill/uBO-Extra) 34 | 35 | ## Special Thanks 36 | 37 | Nano Defender is developed by **@jspenguin2017** with the help of the following 38 | individuals (alphabetical): 39 | 40 | **@lain566** 41 | -------------------------------------------------------------------------------- /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 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Nano Defender 13 | 14 | 15 | 16 | 17 | 18 |
19 |

Nano Defender

20 | 21 |

An anti-adblock defuser for Nano Adblocker and uBlock Origin

22 |
23 | 24 |

Warning: Do not install from unofficial sources! Any websites that are not linked below are considered to be unofficial.

25 |
26 | 27 |
28 |

Important Announcements Regarding Recent Changes

29 | 30 |

Please read important announcements here: https://github.com/NanoAdblocker/NanoCore/issues/362

31 |
32 |
33 | 34 |
35 |

Installation

36 | 37 |

Nano Defender can only protect either Nano Adblocker or uBlock Origin, and will prioritize Nano Adblocker.

38 |
39 | 40 |

Get Nano Defender Pro for Edge

41 |

Get Nano Defender for Chrome or Chromium This listing is no longer under my control

42 |
43 | 44 |

If you are using uBlock Origin, there are a few extra installation steps to follow.

45 |
46 | 47 |

Note: The Pro version has about 15% more rules (by file size), it can also be downloaded from GitHub Releases (for advanced users only).

48 |
49 | 50 |
51 |

Official Ports

52 | 53 |

Maintainers wanted for other browsers, open an issue to let me know.

54 |
55 | 56 |

Get Nano Defender for Firefox (Maintained by @LiCybora)

57 |
58 | 59 |

If you are using uBlock Origin, there are a few extra installation steps to follow.

60 |
61 | 62 |

Note: Nano Defender will not attempt to prevent websites from knowing that you are using Firefox Private Browsing or Firefox Tracking Protection, it is up to Firefox to make those features undetectable.

63 |
64 | 65 |
66 |

Announcements

67 | 68 |

October 3, 2020

69 |

Please read important announcements here: https://github.com/NanoAdblocker/NanoCore/issues/362

70 | 71 |

January 21, 2020

72 |

Since major browsers will be removing Flash player completely by the end of 2020, websites that have anti-adblock after requesting Flash support will no longer be fixed.

73 | 74 |

January 8, 2020

75 |

Google recently changed their policies and some rules (about 15% by file size) can no longer be published to WebStore. Edge users are currently not affected.

76 |

Going forward, Nano Defender will have a Standard version and a Pro version, where the Pro version has all of the rules. Do not install both versions at the same time.

77 |

The Pro version can be downloaded from the Edge Addons store or GitHub Releases.

78 |
79 |
80 | 81 |
82 |

Troubleshooting

83 | 84 |

Be sure to review the filters policy to know what are considered to be issues and what are not.

85 |
86 | 87 |

Do you have proper regional filters activated?

88 |

Are your filters up to date?

89 |

Is Nano Defender installed and up to date?

90 |

Have you tried clearing your cookies?

91 |

Have you tried clearing your cache and LocalStorage?

92 |

Are you using another extension that may cause conflicts?

93 |

Are you using another filter list that may cause conflicts?

94 |

Did you change any settings that may cause your adblocker to misbehave?

95 |

If you are using uBlock Origin, did you properly follow the extra installation steps?

96 |
97 | 98 |

Are you using more than one adblocker? Nano Defender can only protect one adblocker and will prioritize Nano Adblocker.

99 |

Is the built-in adblocker of your browser enabled? Nano Defender cannot protect those adblockers.

100 |

Are you using Anti-Adblock Killer, AAK-Cont, or uBO-Extra? Nano Defender does similar things as they do which can lead to conflicts.

101 |
102 | 103 |

Note: I have received a few reports about the ABP X Files filter list causing issues, try disabling that filter list if you run into them.

104 |
105 | 106 |
107 |

Common questions and issues

108 | 109 |

Will there be a configurable whitelist for Nano Defender?

110 |

Not until I have a reliable way to synchronously send configuration data to content scripts. This is a limitation of browser APIs.

111 |
112 | 113 |

Can console messages be turned off?

114 |

No, I need to see the console output on your end to quickly find the cause of your issues, that is why I ask for a screenshot of the console when you open an issue.

115 |

In production mode, all the console messages will begin with [Nano], so you can easily filter them out with -[Nano].

116 |
117 | 118 |

Can mining wall be bypassed?

119 |

No, that is not possible if the implementation on the server side is correct.

120 |

Adblockers block mining scripts by default and I will not add exceptions if the mining process is started automatically.

121 |

Whitelist the page if you want the resources locked behind the wall.

122 |
123 | 124 |

Nano Defender is causing (further) breakage.

125 |

Report it and I will try to take care of it within 2 days. Keep in mind that this only apply to breakage caused by Nano Defender, other breakages may not be fixed this fast.

126 |
127 | 128 |

A website freezes with Nano Defender enabled.

129 |

Some websites will intentionally freeze (with an infinite loop for example) once they detect Nano Defender, it could also be caused by a bug in Nano Defender.

130 |

Either way, report it and I will try to take care of it within 2 days. Keep in mind that this only apply to freezings caused by Nano Defender, other freezings may not be fixed this fast.

131 |

In Chrome or Chromium, you can use task manager to terminate the tab that froze, go to Menu -> More tools -> Task manager, select the tab that froze, then click End process.

132 |
133 | 134 |

A website is still detecting my adblocker.

135 |

Nano Defender is not magical. A lot of websites need to be fixed on a case by case basis. Report it and I will have a look. Depending on the website, it can take some time.

136 |
137 | 138 |

A website is perceptibly slower with Nano Defender enabled.

139 |

Report it and I will have a look.

140 |
141 | 142 |
143 |

Known issues

144 | 145 | 146 | 147 |

148 | 149 | 6abc.com, 150 | 7plus.com.au, 151 | abc11.com, 152 | abc13.com, 153 | abc7.com, 154 | abc7chicago.com, 155 | abc7ny.com, 156 | brighteon.com, 157 | citytv.com, 158 | cwtv.com, 159 | discovery.com, 160 | fox.com, 161 | investigationdiscovery.com, 162 | kissfm.es, 163 | nettavisen.no, 164 | nbc.com, 165 | play.los40.com, 166 | sciencechannel.com, 167 | thecwtv.com, 168 | threenow.co.nz, 169 | tlc.com, 170 | viceland.com, 171 | watch.hgtv.com 172 | 173 |

174 |

Server-side ads injection, video ads not blocked.

175 |

Account Required Geo Lock (New Zealand) Geo Lock (United States of America)

176 |

177 | Test link 1 178 | Test link 2 179 | Test link 3 180 |

181 |

182 | Issue 1 183 |

184 |
185 | 186 |

187 | 188 | hulu.com 189 | 190 |

191 |

Video player sometimes shows a screen that asks the user what type of ads he wants. Choose to watch trailer if available; actual ads are usually skipped after choosing.

192 |

Video ads are replaced by 1 second blank video but they would still cause a slight interruption.

193 |

Account Required Geo Lock (United States of America) VPN Detected

194 |

195 | Test link 1 196 | Test link 2 197 |

198 |

199 | Issue 1 200 | Issue 2 201 |

202 |
203 | 204 |

205 | 206 | maddertranslates.com 207 | 208 |

209 |

Work in progress, but things are taking longer than expected due to various reasons.

210 |

See issues linked below for more details.

211 |

212 | Issue 1 213 |

214 |
215 | 216 | 217 | 218 |

219 | 220 | channel4.com 221 | 222 |

223 |

Video ads not blocked.

224 |

Geo Lock (United Kingdom) Low Priority (Flash)

225 |

226 | Test link 1 227 | Test link 2 228 |

229 |

230 | Issue 1 231 | Issue 2 232 |

233 |
234 | 235 | 236 | 237 |

238 | 239 | adageindia.in, 240 | bombaytimes.com, 241 | businessinsider.in, 242 | gadgetsnow.com, 243 | gizmodo.in, 244 | iamgujarat.com, 245 | idiva.com, 246 | in.techradar.com, 247 | indiatimes.com, 248 | lifehacker.co.in, 249 | mensxp.com, 250 | samayam.com, 251 | timesofindia.com 252 | 253 |

254 |

Ads take up to 1 second to hide, also the solution is quite inefficient.

255 |

256 | Test link 1 257 | Test link 2 258 |

259 |

260 | Issue 1 261 | Issue 2 262 |

263 |
264 | 265 | 266 | 267 |

268 | 269 | 9anime.is, 270 | anonymousemail.me, 271 | avgle.com [NSFW], 272 | games2rule.com, 273 | javher.com [NSFW], 274 | kissanime.ru, 275 | kissmanga.com, 276 | quora.com, 277 | wowescape.com 278 | 279 |

280 |

Solutions are patched as soon as they come out.

281 |

282 | Test link 1 283 | Test link 2 284 | [NSFW] Test link 3 285 |

286 |

287 | Issue 1 288 | Issue 2 289 | [NSFW] Issue 3 290 | [NSFW] Issue 4 291 | Issue 5 292 |

293 |
294 | 295 |

296 | 297 | boost.ink 298 | 299 |

300 |

Solutions are patched as soon as they come out.

301 |

A special private extension available to a few trusted individuals has fixes for these websites.

302 |
303 | 304 |

305 | 306 | cc.com, 307 | youtube.com 308 | 309 |

310 |

Ads and sponsored contents are not removed when they are baked into the video stream.

311 |

Unlike server-side ads injection, the video player does not know when the ads and sponsored contents play, so it would be near impossible to accurately detect and remove them.

312 |
313 | 314 |

Check open issues in the following issues trackers for other known issues

315 | 318 |

Quick Reports Issues Tracker

319 |

Nano Filters Issues Tracker

320 |

uAssets Issues Tracker

321 |
322 | 323 |
324 |

Reporting an issue

325 | 326 |

You must always check known issues before opening new ones.

327 |
328 | 329 |

For missed ads and tracking scripts, report to EasyList.

330 |

For cookie notices, report to Fanboy.

331 |

For any other filter issues, report to NanoFilters.

332 |

For bugs, suggestions, and questions, report to NanoCore.

333 |
334 | 335 |

You must always fill the issue template when opening issues.

336 |

Too much work? Give Quick Issue Reporter a try! It will automatically handle the tedious parts of the template for you. Click the extension icon of Nano Defender to find it.

337 |
338 | 339 |
340 |

Extra installation steps for uBlock Origin

341 | 342 |

Step 1. Subscribe to Adblock Warning Removal List.

343 |

Step 2. Subscribe to Nano Defender Integration filter list.

344 |

Step 3. Go to uBlock Origin dashboard, select Settings tab, check I am an advanced user, click the gears icon that shows up, replace unset after userResourcesLocation by:

345 |

https://gitcdn.xyz/repo/NanoAdblocker/NanoFilters/master/NanoFilters/NanoResources.txt

346 |

Warning: The resources file is not a filter list, do not load it as a filter list or things will break.

347 |

Step 4. Subscribe to Nano filters.

348 |
349 | 350 | 357 | 358 | 359 | -------------------------------------------------------------------------------- /list/1-header.txt: -------------------------------------------------------------------------------- 1 | # Nano Defender Integration 2 | # This filter list is intended to be used with Nano Defender 3 | # Visit my home page for more information: https://jspenguin2017.github.io/uBlockProtector/ 4 | # This file is a compiled binary, any modification will be overwritten on the next build -------------------------------------------------------------------------------- /list/2-integration.txt: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------------- # 2 | 3 | # These are filters for integration with Nano Defender, all whitelists in this section are handled by Nano Defender 4 | 5 | # ------------------------------------------------------------------------------------------------------------------- # 6 | 7 | # Special 8 | 9 | # Callback API placeholder, must be blocked, this file does not actually exist 10 | |https://legacy.hugoxu.com/uBlockProtector/Solutions/Blocked.php$important 11 | 12 | # Resource placeholder, these files do not actually exist 13 | |https://legacy.hugoxu.com/uBlockProtector/Solutions/ 14 | 15 | # ------------------------------------------------------------------------------------------------------------------- # 16 | 17 | # Generic 18 | 19 | @@|https://*.moatads.com/*/MoatFreeWheelJSPEM.js*$script 20 | @@|https://ads.korri.fr/index.js|$script 21 | @@|http://*.medianetworkinternational.com/js/advertisement.js*$script 22 | 23 | # ------------------------------------------------------------------------------------------------------------------- # 24 | 25 | # Specific 26 | 27 | # https://github.com/NanoMeow/QuickReports/issues/528 28 | # https://github.com/uBlockOrigin/uAssets/issues/4293 29 | @@||vd.l.qq.com/proxyhttp$xhr,domain=sports.qq.com|v.qq.com 30 | 31 | # https://github.com/uBlockOrigin/uAssets/issues/4290 32 | ani.gamer.com.tw##body > div:has(a[href="https://goo.gl/PmkwWS"]) 33 | 34 | # ------------------------------------------------------------------------------------------------------------------- # 35 | 36 | # Broken 37 | 38 | # IMA SDK surrogate integration 39 | # @@|https://imasdk.googleapis.com/js/sdkloader/ima3.js*$script,domain=~fox.com|~log.com.tr|~motorsport.tv|~pandora.com|~popcornflix.com|~streamable.com|~tv2.dk 40 | # @@|http://imasdk.googleapis.com/js/sdkloader/ima3.js*$script,domain=~fox.com|~log.com.tr|~motorsport.tv|~pandora.com|~popcornflix.com|~streamable.com|~tv2.dk 41 | # Their poster logic is broken, but the error is somehow suppressed by the original IMA SDK 42 | # ||cbsnews.com/news/*/[object%20object]$image,redirect=1x1-transparent.gif 43 | # ||cbsnews.com/news/*/undefined$image,redirect=1x1-transparent.gif 44 | 45 | # ------------------------------------------------------------------------------------------------------------------- # 46 | -------------------------------------------------------------------------------- /list/3-rules.txt: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------------- # 2 | 3 | # Miners 4 | 5 | /coinhive.js 6 | /coinhive.min.js 7 | /c-hive.js 8 | /c-hive.min.js 9 | /cryptonight.wasm 10 | /cn.wasm 11 | 12 | # ------------------------------------------------------------------------------------------------------------------- # 13 | 14 | # Missed ads 15 | 16 | ||googlesyndication.com^$important,domain=short.am|clubedohardware.com.br 17 | ||doubleclick.net^$important,domain=aetv.com|history.com|mylifetime.com 18 | 19 | ||damoh.*$media 20 | 21 | ||zergnet.com^$script,third-party 22 | 23 | # https://github.com/jspenguin2017/uBlockProtector/issues/251 24 | ||a.optnmnstr.com^$third-party 25 | ||a.optnmstr.com^$third-party 26 | 27 | # https://github.com/jspenguin2017/uBlockProtector/issues/346 28 | ||adiode.com^$third-party 29 | 30 | # NSFW 31 | ||zmovs.com^$csp=sandbox allow-forms allow-presentation allow-scripts allow-top-navigation allow-orientation-lock allow-pointer-lock allow-same-origin 32 | zmovs.com##.tc-col-sm-offset-7.hidden-xs 33 | zmovs.com##.closeBtn 34 | zmovs.com##.inplayer_banners 35 | 36 | ||amazonaws.com^$domain=dailymotion.com 37 | 38 | # https://github.com/uBlockOrigin/uAssets/issues/442 39 | @@||louccrossc.com^$domain=tf1.fr,badfilter 40 | @@||foilpolyth.com^$domain=tf1.fr,badfilter 41 | ||foilpolyth.com^$xmlhttprequest,redirect=nooptext,important,domain=tf1.fr 42 | ||louccrossc.com^$xmlhttprequest,redirect=nooptext,important,domain=tf1.fr 43 | 44 | # ------------------------------------------------------------------------------------------------------------------- # 45 | 46 | # Common Solutions 47 | 48 | ###adblockBanner 49 | ###like-us-adblock-modal 50 | ##.admania_adblock_detector 51 | ##.o-AdhesionNotifier 52 | ##.popup-premium__apla 53 | 54 | /adblock-detector/* 55 | /adblock-popup. 56 | ||fastly.net/ads/$image,redirect=2x2-transparent.png 57 | ||fastly.net/ads/$script,redirect=noopjs 58 | ||fastly.net/ads/$xmlhttprequest,redirect=nooptext 59 | ||doubleclick.net/instream/ad_status.js$script,redirect=doubleclick.net/instream/ad_status.js 60 | 61 | # https://github.com/jspenguin2017/uBlockProtector/issues/254 62 | ||lukkr.com/website/pf.js 63 | 64 | # https://github.com/jspenguin2017/uBlockProtector/issues/978 65 | ||sixscissors.com^$third-party,domain=~itavisen.no 66 | 67 | # Adblock Identifier 68 | # Can cause crash, need to test each case 69 | /jquery.adi.css 70 | /jquery.adi.js$domain=123link.top 71 | 72 | # Admiral 73 | ||pelcro.com^$third-party 74 | 75 | # BlockAdBlock 76 | sectorsatoshi-amarillo.website,sectorsatoshi-azul.website,sectorsatoshi-blanco.website,sectorsatoshi-celeste.website,sectorsatoshi-gris.website,sectorsatoshi-naranja.website##+js(bab-defuser.js) 77 | sectorsatoshi-negro.website,sectorsatoshi-rosa.website,sectorsatoshi-verde.website,sectorsatoshi-violeta.website##+js(bab-defuser.js) 78 | futbolchile.net,freeomovie.com,appdrop.net,skmedix.pl,yalujailbreak.net,cloudwebcopy.com,milaulas.com,tout-bon.com,sznpaste.net,linkdrop.net,themeslide.com##+js(bab-defuser.js) 79 | android-zone.ws,cmacapps.com,l2network.eu,animes-mangas-ddl.net,fuckingsession.com,klartext-ne.de,forumcoin.win,androidemulator.in,forumcoin.win,arenavision.ru,gulshankumar.net##+js(bab-defuser.js) 80 | arenavision.in,arenavision.us,discudemy.com,practicetestgeeks.com,iptvbin.com,imojado.org,xossip.com,adyou.me,funcinema.ga,ddlfr.pw,freecoursesonline.us##+js(bab-defuser.js) 81 | 82 | # AdBlock Detector 83 | themarker.com,nachrichten.at##+js(abort-on-property-read.js, adblockDetector) 84 | 85 | # Social Locker 86 | megawarez.org,tipeo.net,compucalitv.com,intercambiosvirtuales.pro,tecmaxsoft.com,descargatelocorp.com,hackstore.net##div.onp-sl-content:style(display: block !important;) 87 | megawarez.org,tipeo.net,compucalitv.com,intercambiosvirtuales.pro,tecmaxsoft.com,descargatelocorp.com,hackstore.net##div.onp-sl-social-locker 88 | anonymousemail.me##div.onp-sociallocker-content:style(display: block !important;) 89 | anonymousemail.me##div.onp-sociallocker 90 | descargatelocorp.com##div[id^="informer"]:style(display: block !important; opacity: 1 !important; max-height: none !important;) 91 | descargatelocorp.com##div[class*="cool_ramka"] 92 | 93 | # ------------------------------------------------------------------------------------------------------------------- # 94 | 95 | # Specific solutions 96 | 97 | ! === cloudfront.net 98 | ||cloudfront.net^$domain=adbull.me|shink.in|dbzsuper.tv|croco.site|adshorte.com|pasteca.sh|cloudyfiles.org|cuturlink.com|wateranik.com|eagerse.com|estrenos10.com|palimas.tv|srt.am 99 | ! === wp.pl and related domains 100 | ||adv.wp.pl/$media,redirect=noopmp3-0.1s,important 101 | ||static-pilot.wp.pl/static/assets/js/ads.js$xmlhttprequest,redirect=noopjs 102 | ||adv.wp.pl/*/inline-videostar.js$xmlhttprequest,redirect=noopjs,important,domain=pilot.wp.pl 103 | ||adv.wp.pl/adverts*.js$xmlhttprequest,redirect=noopjs,important,domain=pilot.wp.pl 104 | ! === NSFW! zone-anime.net 105 | filez.tv###adblockinfo 106 | ! === video.gazeta.pl 107 | @@||video.gazeta.pl/cdn/ads/ad/banner/_adsense_/_adserver/_adview_.ad.json$xmlhttprequest,first-party 108 | ! === latimes.com 109 | ||tribdss.com/meter/assets$script,domain=www.latimes.com 110 | ! === thewindowsclub.com 111 | *$xmlhttprequest,domain=thewindowsclub.com 112 | @@||disquscdn.com^$script,domain=thewindowsclub.com 113 | @@|https://disqus.com/next/config.js$domain=thewindowsclub.com 114 | ! === NSFW! 8muses.com 115 | ||8muses.com^$inline-script 116 | @@||8muses.com/comix/picture^$inline-script 117 | ! === allmusic.com 118 | ||allmusic.com^$inline-script 119 | ! === xmovies8.org, moviezr.org 120 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/90 121 | xmovies8.org,moviezr.org##+js(abort-on-property-read.js, $.getScript) 122 | ! === tune.pk 123 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/92 124 | tune.pk###annoy-wrapper 125 | ! === NSFW! 29443kmq.video, dato.porn 126 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/93 127 | 29443kmq.video,dato.porn###a 128 | dato.porn##+js(abort-on-property-read.js, open) 129 | dato.porn##+js(noeval-if.js, var r3H4=window;for(var v4 in r3H4)) 130 | ! === engineeringtoolbox.com 131 | engineeringtoolbox.com##.adblo 132 | engineeringtoolbox.com##.contentDocumentAd 133 | ! === ps4news.com 134 | ps4news.com##+js(noeval.js) 135 | ps4news.com##body > *[id^="blockblock"]:style(visibility: visible !important; display: block !important;) 136 | ps4news.com##table[id^='blockblock'] 137 | ! === 7636ca6cb9fc.com 138 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/99 139 | ||7636ca6cb9fc.com^ 140 | ! === okazje.co 141 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/114 142 | okazje.co###AdBlockDetected 143 | ! === answers.com 144 | answers.com##.end_of_slideshow 145 | ! === gamereactor.dk and related domains 146 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/124 147 | ||openx.gamereactor.*/multi.php$script,important 148 | ! === animmex.* 149 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/125 150 | ||finalservers.net^$inline-script 151 | finalservers.net###babasbmsgx 152 | finalservers.net##+js(abort-on-property-read.js, _gunggo) 153 | animmex.*###M148617ScriptRootC75329 154 | animmex.*##a[href^="https://forum.animmex.com/viewtopic.php"] 155 | ! === gry.pl 156 | ||flakyfeast.com^$domain=gry.pl 157 | ! === youtube.com 158 | youtube.com###companion 159 | ! === pogdesign.co.uk 160 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/149 161 | pogdesign.co.uk##.replace 162 | ! === ally.sh, al.ly 163 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/148 164 | ||p207208.clksite.com^$subdocument,redirect=noopframe,domain=ally.sh|al.ly 165 | ally.sh,al.ly##+js(popads.net.js) 166 | ! === hackintosh.zone, hackintosh.computer 167 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/35 168 | ||hackintosh.*/donate/donate.php 169 | ! === aftonbladet.se 170 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/163 171 | ||ooul.tv/contrib/se-aftonbladet/aab/aftonbladet_plugin.js$script,redirect=noopjs,domain=aftonbladet.se 172 | ||ooul.tv/nocache/se-aftonbladet/aab/aftonbladet_config.js$script,redirect=noopjs,domain=aftonbladet.se 173 | ! === filechoco.net, keezmovies.com, raptu.com, afreesms.com 174 | filechoco.net,keezmovies.com,raptu.com,afreesms.com##+js(noeval.js) 175 | ! === iframes of goodanime.co 176 | playbb.me#@#div[style^="width:"] 177 | easyvideo.me#@#div[style^="width:"] 178 | videowing.me#@#div[style^="width:"] 179 | videozoo.me#@#div[style^="width:"] 180 | ! === games.softgames.de 181 | ||games.softgames.de/assets/showads.js$script,redirect=noopjs 182 | ||softgames.de/sg-mc.js*$script,redirect=noopjs 183 | ! === exrapidleech.info 184 | ||bidvertiser.com$important,domain=exrapidleech.info 185 | ! === mmo-champion.com 186 | ||broadcastbed.com^$domain=mmo-champion.com 187 | ! === bracknellnews.co.uk 188 | bracknellnews.co.uk##+js(abort-on-property-write.js, _sp_) 189 | ! === u2s.io, l2s.io, linkhits.us 190 | u2s.io,l2s.io,linkhits.us#@#.myTestAd 191 | @@||solvemedia.com^$domain=u2s.io|l2s.io 192 | ||5g9quwq.com^$third-party 193 | ! === pwn.pl, vendiscuss.net, rufootballtv.org 194 | pwn.pl,vendiscuss.net,rufootballtv.org##+js(abort-on-property-read.js, adblock) 195 | ! === clubic.com 196 | ||tiptonvillepylesville.com^$domain=clubic.com 197 | ! === animeid.io and similar domains 198 | animeid.io,jkanime.co,gogoanime.ch,chiaanime.co,animeflv.co##+js(setTimeout-defuser.js, #player) 199 | ! === comicallyincorrect.com 200 | @@||comicincorrect.wpengine.netdna-cdn.com/wp-content/uploads/ 201 | ! === savetodrive.net 202 | savetodrive.net##+js(setTimeout-defuser.js, ad) 203 | ! === rarbgmirror.com, swfchan.net, swfchan.com, zippyshare.com, leech.ae, vizer.tv 204 | rarbgmirror.com,swfchan.net,swfchan.com,zippyshare.com,leech.ae,vizer.tv##+js(abort-on-property-read.js, open) 205 | ! === pipocas.tv 206 | ||googlesyndication.com^$script,redirect=noopjs,domain=pipocas.tv 207 | ! === steamcustomizer.com 208 | steamcustomizer.com###sadcat 209 | steamcustomizer.com##.notice.support-notice 210 | @@||steamcustomizer.com/cache/skin/ad/$image,first-party 211 | ! === iframes of shqiptvlive.net 212 | shqiperiatv.com,albtvhd.com,tvshqiphd.com,www.balkanweb.com,cdn.livestream.com,livestream.artmotion.al,shqip-tv.info##body > *[id^="blockblock"]:style(visibility: visible !important; display: block !important;) 213 | shqiperiatv.com,albtvhd.com,tvshqiphd.com,www.balkanweb.com,cdn.livestream.com,livestream.artmotion.al,shqip-tv.info##table[id^='blockblock'] 214 | ! === wordsense.eu 215 | wordsense.eu##+js(setTimeout-defuser.js, ad, 2000) 216 | ! === transparentcalifornia.com 217 | /magnific-popup.js/*$domain=transparentcalifornia.com 218 | ! === javsex.net 219 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/244 220 | @@||yamvideo.com/pop1/jwplayer.js$domain=javsex.net 221 | ! === nowvideo.ec, nowvideo.li, ewingoset.info 222 | ! === https://gitlab.com/xuhaiyang1234/NanoAdblockerSecretIssues/issues/2 223 | ||nowvideo.ec^$inline-script 224 | ||nowvideo.li^$inline-script 225 | ||ewingoset.info^$inline-script 226 | ! === nana10.co.il 227 | ||cloudvideoplatform.com/advert.jpg$image,redirect=1x1-transparent.gif,domain=nana10.co.il 228 | ! === newyorker.com 229 | newyorker.com##iframe[src*="/wp-content/assets/"] 230 | ! === politiken.dk 231 | @@||politiken.dk/*ad*$script,first-party 232 | ! === wholecloud.net 233 | ||wholecloud.net^$inline-script 234 | ! === link.tl 235 | link.tl##.adblockBox 236 | link.tl##.adblockOverlay 237 | ! === themelot.net 238 | *$third-party,script,domain=themelot.net 239 | ! === batchnime.net 240 | batchnime.net##+js(abort-on-property-read.js, killAdBlock) 241 | ! === uplod.ws 242 | uplod.ws##+js(abort-on-property-read.js, $.ready) 243 | ! === ilgazzettino.it 244 | ||utils.cedsdigital.it/checkSubscription/checkSubscription.js 245 | ! === windowsreport.com 246 | windowsreport.com##+js(silent-noeval.js) 247 | ! === haxmaps.com, haxrec.com, haxcolors.com 248 | haxmaps.com,haxrec.com,haxcolors.com##+js(setTimeout-defuser.js, /.*/, 10000) 249 | ! === animesync.tv 250 | animesync.tv##.modal-adblock 251 | ! === expansion.com 252 | ||active.cache.el-mundo.net/js/*_expansion.js$domain=expansion.com 253 | ! === watchfree.to 254 | watchfree.to##+js(abort-on-property-read.js, UAParser) 255 | ! === firstonetv.eu, firstone.tv 256 | firstonetv.eu,firstone.tv##+js(noeval-if.js, Please disable your Adblocker) 257 | ! === vooxe.com 258 | vooxe.com###blockedAddons 259 | ! === gentecheesisterealmente.com 260 | gentecheesisterealmente.com##+js(abort-on-property-read.js, admaniastchk) 261 | ! === litv.tv 262 | ||litv.tv/promo/ 263 | litv.tv##.fp-pausebn 264 | ||$third-party,script,domain=litv.tv 265 | ! === dailyuploads.net 266 | dailyuploads.net##+js(abort-on-property-read.js, popns) 267 | dailyuploads.net##+js(abort-on-property-read.js, adbClick) 268 | ! === buickforums.com 269 | ||madisonross.com/adblock.html$subdocument 270 | ! === sznpaste.net 271 | sznpaste.net##+js(abort-on-property-write.js, _pop) 272 | ! === linkdrop.net 273 | @@||ajax.googleapis.com/ajax/libs/jquery/$script,domain=linkdrop.net 274 | ! === leechgear.net 275 | leechgear.net###block_on 276 | ! === wiwo.de 277 | wiwo.de,handelsblatt.com##+js(abort-on-property-read.js, AdController) 278 | ! === tvregionalna24.pl 279 | tvregionalna24.pl##.diablo-placeholder 280 | ! === kitguru.net 281 | kitguru.net#@#div > a[class] > img[src] 282 | kitguru.net##.gofollow 283 | ! === vidnow.to 284 | vidnow.to###adplayer 285 | ! === gigaleecher.com 286 | ||gigaleecher.com/templates/plugmod/giga.js$script 287 | ! === diariodenavarra.es 288 | diariodenavarra.es###abMsgWrap 289 | ! === NSFW! darmowe-pornosy.pl, polskie-aktorki-porno.pl 290 | darmowe-pornosy.pl,polskie-aktorki-porno.pl#@#.myTestAd 291 | ! === themarker.com 292 | themarker.com###ad-block-wrapper 293 | ! === vidlox.tv 294 | @@*$csp,domain=vidlox.tv 295 | ! === zeusnews.it 296 | ||zeusnews.it/antiadb.js 297 | ! === ipornia.hdzog.com 298 | @@||static.ipornia.com^$image,domain=ipornia.hdzog.com 299 | hdzog.com##.msg-adblock.msg 300 | ! === webcheats.com.br 301 | webcheats.com.br##+js(abort-on-property-read.js, can_run_ads) 302 | webcheats.com.br###bg_trasp 303 | ! === totomi.co 304 | totomi.co##+js(setInterval-defuser.js, /display/.test) 305 | ! === naisho.asia 306 | naisho.asia##+js(abort-on-property-write.js, adBlock) 307 | ! === westeros.org 308 | ||sovrnlabs.net^$domain=westeros.org 309 | ! === NSFW! sankakucomplex.com 310 | sankakucomplex.com##+js(abort-on-property-read.js, BetterJsPop) 311 | ! === short.am 312 | @@||short.am^$generichide,badfilter 313 | ! === wdbloog.com 314 | wdbloog.com###unblocker 315 | ! === dingit.tv, jan-magazine.nl, glamour.nl, quest.nl 316 | dingit.tv,jan-magazine.nl,glamour.nl,quest.nl#@#.adsbox 317 | ||dingit.tv/js/dingit-player/js/html5/videojs.ads.js$script,redirect=noopjs 318 | ! === vz.lt 319 | /countsJS.php$domain=vz.lt 320 | ! === xess.pro 321 | ||xess.pro/js/popup.js 322 | ! === iprima.cz 323 | iprima.cz##.play-wrapper.player-wrapper > .you-shall-not-pass 324 | iprima.cz##.play-wrapper.player-wrapper + .you-shall-not-pass 325 | iprima.cz###AdTrackVideoPlayer 326 | ! === hayan.tv 327 | ||hayan.tv/gibberish-aes.js^ 328 | ! === nbcsports.com 329 | ||hdliveextra-a.akamaihd.net/*/ads.js$script,redirect=noopjs 330 | ! === openculture.com 331 | ||openculture.com/wp-content/uploads/$script 332 | ! === goalsarena.org 333 | @@||config.playwire.com^$domain=goalsarena.org 334 | ! === tecmundo.com.br 335 | tecmundo.com.br##.gallery-ads 336 | ! === der-postillon.com 337 | der-postillon.com###steady-adblock-overlay-container 338 | ! === kinja.com and related domains 339 | ||kinja.com/sp/ 340 | ||deadspin.com/sp/ 341 | ||splinternews.com/sp/ 342 | ||gizmodo.com/sp/ 343 | ||jalopnik.com/sp/ 344 | ||jezebel.com/sp/ 345 | ||kotaku.com/sp/ 346 | ||mms.kotaku.com^$script,xmlhttprequest 347 | ||lifehacker.com/sp/ 348 | ||theroot.com/sp/ 349 | ! === adshorte.com 350 | ||dailymotion.com^$domain=adshorte.com 351 | ! === paksociety.com, f-hd.net 352 | paksociety.com,f-hd.net##.blocked 353 | ! === cleveland.com 354 | ||fastly.net/mms-client.js$domain=cleveland.com 355 | ||fastly.net/messaging.js$domain=cleveland.com 356 | ! === couponcabin.com 357 | couponcabin.com###adblocker-reminder 358 | ! === tubeninja.net 359 | @@||tubeninja.net/ads.js$first-party 360 | ! === tlz.de 361 | tlz.de##.ab-shader 362 | ! === 1tv.ru 363 | ||v.adfox.ru^$xmlhttprequest,redirect=nooptext,domain=1tv.ru 364 | ! === 1tiny.net 365 | 1tiny.net##+js(abort-on-property-read.js, jQuery.ready) 366 | ! === thevideo.me 367 | thevideo.me##.notification-adblock 368 | ! === fas.li 369 | ||fas.li/js/p.js 370 | ! === smashingmagazine.com 371 | smashingmagazine.com###blocked 372 | ! === kustvaartforum.com 373 | ||kustvaartforum.com/block.js 374 | ! === latin.it 375 | @@||latin.it/banner.php$first-party 376 | ! === stocks.cafe 377 | ||stocks.cafe/amazon/google$subdocument 378 | ! === geo.de 379 | ||laterpay.net^$domain=geo.de 380 | ! === techforever.net 381 | techforever.net##+js(setTimeout-defuser.js, canABP) 382 | ! === seekingalpha.com 383 | @@||seekingalpha.com^$script,badfilter 384 | ||seekingalpha.com/ads_data.js$script,redirect=noopjs 385 | ! === btcinbtc.com and related domains 386 | /checkme.js$domain=btcinbtc.com|hamsab.net|20hk.com|my115.net|bitcoball.com|seek-inn.com|at-spot.com 387 | ! === explosm.net 388 | @@||proper.io/embed/$subdocument,domain=explosm.net 389 | ! === mspfa.com 390 | mspfa.com###nopepsi 391 | ! === klisza.org 392 | ||klisza.org/wp-content/plugins/popups/ 393 | klisza.org##.spu-box 394 | ! === womenshealthmag.com 395 | @@||womenshealthmag.com^$script,first-party 396 | ! === mitele.es 397 | ||mitele.es/vendor/adjs.js$xmlhttprequest,redirect=noopjs 398 | ||mitele.es/vendor/fuckadblock.js$xmlhttprequest,redirect=noopjs 399 | ||player.ooyala.com/*/ad-plugin/$important,script,badfilter 400 | ||player.ooyala.com/*/ad-plugin/$important,script,domain=~mitele.es 401 | ||player.ooyala.com/*/ad-plugin/$important,script,domain=mitele.es,redirect=noopjs 402 | ! === virgilio.it 403 | virgilio.it##+js(abort-on-property-read.js, VVIDEO.adBlock) 404 | ! === auroravid.to 405 | ||auroravid.to^$inline-script 406 | ! === amarujala.com 407 | amarujala.com##+js(abort-on-property-read.js, call_adblocker) 408 | ! === oddreaders.com 409 | ||oddreaders.com/wp-content/plugins/sociallocker-next-premium/ 410 | ! === sportspyder.com 411 | sportspyder.com##+js(setTimeout-defuser.js, BlockerChecker) 412 | ||sportspyder.com/assets/application-$script,badfilter 413 | ! === tvnow.de 414 | tvnow.de##.no-flash-box:has-text(Adblocker) 415 | ! === kiss.com.tw 416 | kiss.com.tw#@##ads 417 | ! === igeeksblog.com 418 | igeeksblog.com###quads-ad1_widget 419 | ! === linclik.com 420 | *$script,third-party,domain=linclik.com 421 | ! === espresso.repubblica.it 422 | ||espresso.repubblica.it/pw/pw2-espressosfoglio.js 423 | ! === net.hr 424 | net.hr#@#.reklama 425 | net.hr#@#.reklama1 426 | ! === televisa.com, lasestrellas.tv 427 | /adblock/*$domain=televisa.com|lasestrellas.tv 428 | ! === watson.ch 429 | watson.ch##.adget.frog_block_alert 430 | ! === stol.it 431 | stol.it###block-message 432 | ! === sledujufilmy.cz 433 | sledujufilmy.cz##.bottom-advert 434 | sledujufilmy.cz##.ads-position 435 | sledujufilmy.cz##.riding-banner 436 | ! === mycloud.to 437 | mycloud.to###jwa 438 | ! === mmorpgitalia.it 439 | mmorpgitalia.it##.noticeContainer:has-text(ADBLOCK) 440 | ! === insurancenewsnet.com, advisornews.com 441 | insurancenewsnet.com,advisornews.com##+js(abort-on-property-read.js, adblock_detect) 442 | ! === mmovie.it 443 | mmovie.it###advleft 444 | ! === zeperfs.com 445 | zeperfs.com##+js(noeval-if.js, AdBlock) 446 | ! === userupload.net,firstonetv.net 447 | userupload.net,firstonetv.net##+js(noeval-if.js, Adblock) 448 | ! === mashable.com, niezalezna.pl 449 | mashable.com,niezalezna.pl##+js(noeval-if.js, adblock) 450 | ! === iptvultra.com 451 | iptvultra.com##+js(setTimeout-defuser.js, div.table_download) 452 | ! === pcgames-download.com 453 | ||pcgames-download.com/wp-content/plugins/noadb-leftthenicemessage/ 454 | ! === grazia-magazin.de 455 | grazia-magazin.de##.subNaviNotification:has-text(Adblocker) 456 | ! === dreamfancy.org, trhileci.com 457 | ||metin2bot.net/kontrol/adb.js 458 | ! === afdah.to 459 | @@||afdah.to/show-ad$first-party 460 | ! === vertamedia.com 461 | @@||vertamedia.com/assets/img/adimage.png$first-party 462 | ! === rallye-magazin.de 463 | rallye-magazin.de###billboardattention 464 | ! === schwarzwaelder-bote.de 465 | schwarzwaelder-bote.de###blocker-note 466 | ! === wer-weiss-was.de 467 | wer-weiss-was.de###hint 468 | ! === peugeot-metropolis.de 469 | peugeot-metropolis.de###displaywise 470 | ! === topagrar.com 471 | ||topagrar.com/_themes/topagrar-responsive/_js/ads.js$script,redirect=noopjs 472 | ! === tagesspiegel.de 473 | /tgs.teaser-ad.js$domain=tagesspiegel.de 474 | ! === t3n.de 475 | t3n.de#@##adsbox 476 | ! === yiv.com 477 | yiv.com###LeftAdDiv 478 | yiv.com###RightAdDiv 479 | ! === agar.io 480 | agar.io###advertisement 481 | ! === dolldivine.com 482 | ||dolldivine.com/images/fairy-preview.jpg 483 | ! === peugeot-metropolis.de 484 | peugeot-metropolis.de##+js(abort-current-inline-script.js, $, #gandalfads) 485 | ! === warforum.cz 486 | warforum.cz###popwrapper 487 | ! === kisscartoon.io and related domains 488 | ||ad.kisscartoon.*^$important 489 | ! === randaris-anime.net 490 | randaris-anime.net##.advert1 491 | randaris-anime.net##.adblock-box 492 | ! === androidsage.com 493 | androidsage.com##+js(abort-on-property-read.js, blckad) 494 | ! === bento.de, pcgamer.com 495 | bento.de,pcgamer.com##+js(abort-on-property-read.js, _sp_.mms) 496 | ! === cwseed.com 497 | cwseed.com##+js(abort-on-property-read.js, wc.url) 498 | ! === wasabisyrup.com 499 | ||wasabisyrup.com/template/plugin02.js 500 | ! === prevention.com, avoiderrors.net, gulmeklazim.com 501 | ! === https://github.com/jspenguin2017/uBlockProtector/issues/589 502 | prevention.com,avoiderrors.net,gulmeklazim.com##+js(setTimeout-defuser.js, adblock) 503 | ! === getfree-bitcoin.com 504 | getfree-bitcoin.com##+js(setTimeout-defuser.js, Adblock) 505 | getfree-bitcoin.com##.left-advertisement 506 | getfree-bitcoin.com##a[href^="//mellowads.com/"] 507 | ! === estrenos10.com 508 | estrenos10.com##+js(setTimeout-defuser.js, AdBlock) 509 | ! === programinadresi.com 510 | programinadresi.com##+js(setTimeout-defuser.js, adBlock) 511 | ! === kshowes.net 512 | kshowes.net##+js(abort-current-inline-script.js, setTimeout, Im.offsetHeight<=0) 513 | kshowes.net###hide:style(display: block !important;) 514 | kshowes.net##input.buttonlink#contador 515 | ! === moat.com 516 | moat.com##+js(setTimeout-defuser.js, adbCheckBlocker) 517 | imleagues.com##+js(setTimeout-defuser.js, show_ads.js) 518 | ! === indiatimes.com 519 | indiatimes.com###append_overlay_photo_ads 520 | ! === nontonanime.org 521 | nontonanime.org##nav.navbar + div.banner > a[href^="https://goo.gl/"] 522 | ||eurifsiooyof.bid^$script,third-party 523 | ! === lavozdealmeria.es 524 | ||lavozdealmeria.es/js/addblock.js 525 | ! === all-in.de 526 | all-in.de###a_info 527 | ! === greenocktelegraph.co.uk 528 | greenocktelegraph.co.uk##.dfp-top-ad-container 529 | ! === ouo.press, ouo.io 530 | ||ouo.press/js/pop.t.js 531 | *$script,third-party,domain=ouo.press|ouo.io 532 | ! === linkkawy.com 533 | linkkawy.com###exestylepopupdiv 534 | ! === homebank.free.fr 535 | homebank.free.fr###disablemessage 536 | ! === getrelax.club 537 | getrelax.club##.loaded-popup-wrapper 538 | ! === mycinema.pro 539 | mycinema.pro##.adsbygoogle 540 | ! === okkazeo.com 541 | okkazeo.com###ads 542 | ! === digitalinformationworld.com 543 | digitalinformationworld.com##+js(abort-on-property-read.js, adsbygoogle) 544 | ! === moat.com 545 | @@||moat.com/creatives/advertiser/$first-party 546 | @@||moat.com/api/entity_report/advertiser/$first-party 547 | ! === mangashost.net,mangashost.com 548 | mangashost.net,mangashost.com##+js(setTimeout-defuser.js, ads160left) 549 | ! === cnn.com 550 | ||mms.cnn.com^$script 551 | ! === attorz.com 552 | attorz.com##+js(abort-on-property-write.js, isAdBlocked) 553 | attorz.com###lineage104_pic 554 | ! === resourcepacks24.de 555 | resourcepacks24.de##+js(setTimeout-defuser.js, google_jobrunner) 556 | ! === literaturcafe.de 557 | literaturcafe.de##+js(setTimeout-defuser.js, blockStatus) 558 | ! === deckshop.pro 559 | deckshop.pro###friendlyReminder 560 | ! === citytv.com 561 | citytv.com##.widget_ad-widget 562 | citytv.com##.adv_wrap 563 | citytv.com##.adv_leaderboard 564 | citytv.com##.ad_bigbox 565 | ! === maisgasolina.com 566 | maisgasolina.com##+js(setTimeout-defuser.js, window.google_jobrunner) 567 | ! === vaughnlive.tv 568 | @@||vaughnlive.tv/ad/banner/_adsense_/_adserver/_adview_.ad.json$xmlhttprequest,first-party 569 | ! === insuranceage.co.uk 570 | ||adpass.co.uk^ 571 | ! === strefadb.pl 572 | strefadb.pl###videoad 573 | ! === ultimate-catch.eu 574 | ultimate-catch.eu##.special-message-wrapper 575 | ! === alemdarleech.com 576 | alemdarleech.com##+js(abort-on-property-read.js, koddostu_com_adblock_yok) 577 | ! === communitech.ca 578 | communitech.ca#@#a[href*="/?aff="] 579 | ! === vidfile.net 580 | vidfile.net##.rek 581 | ! === strikeout.co 582 | ||cdn.cdnserv.pw/js/cnads.js$script,redirect=noopjs,domain=strikeout.co 583 | ! === crash-aerien.news 584 | crash-aerien.news##+js(abort-on-property-read.js, noPub) 585 | ! === gratisprogramas.co, gratisjuegos.co, gratispeliculas.xyz 586 | gratisprogramas.co,gratisjuegos.co,gratispeliculas.xyz##div[id^="hide"]:style(display: block !important;) 587 | gratisprogramas.co,gratisjuegos.co,gratispeliculas.xyz##input[id^="contar"] 588 | ! === freestocks.org 589 | freestocks.org##.popup 590 | ! === NSFW! pornhub.com 591 | pornhub.com##+js(abort-on-property-read.js, userABMessage) 592 | ! === rus.delfi.ee 593 | rus.delfi.ee###ab--notification-ribbon 594 | ! === imgur.com 595 | imgur.com##.footerlink-report-ads 596 | ! === simply-debrid.com 597 | simply-debrid.com##.adsbygoogle 598 | simply-debrid.com###google_ads:style(height: 1px !important; visibility: hidden !important;) 599 | ! === slader.com 600 | slader.com##+js(abort-on-property-read.js, sladerAbm) 601 | slader.com##section.solutions-list.loading:style(height: auto !important;) 602 | slader.com##.ads.ads-to-hide 603 | ! === jsfiddle.net 604 | jsfiddle.net###keep-us-running 605 | ! === animeheaven.eu 606 | @@||animeheaven.eu^$script,first-party 607 | ! === gej-porno.pl, animezone.pl, newpct.com 608 | gej-porno.pl#@#.myTestAd 609 | gej-porno.pl,animezone.pl,newpct.com##a[href^="//"] 610 | ! === m.delfi.ee 611 | m.delfi.ee##.md-banner-placement 612 | ! === jacquieetmicheltv.net 613 | jacquieetmicheltv.net##+js(abort-on-property-read.js, is_adblocked) 614 | ! === haberler.com 615 | haberler.com##.playButton 616 | ! === livesport.ws 617 | livesport.ws##+js(abort-on-property-read.js, document.avp_ready) 618 | ! === backin.net 619 | backin.net##+js(setTimeout-defuser.js, /myadz|adblock/) 620 | ! === stealive.club 621 | ||stealive.club/js/ht.js 622 | ! === mejorescanales.com 623 | mejorescanales.com##+js(abort-on-property-read.js, jQuery.adblock) 624 | ! === gr8forte.org 625 | gr8forte.org###alert-block 626 | gr8forte.org##+js(abort-on-property-read.js, clickNS) 627 | ! === diariosur.es 628 | ||static.vocento.com/adbd/ 629 | ! === flashx.tv, flashx.to 630 | flashx.tv,flashx.to##+js(abort-on-property-read.js, open) 631 | ||flashx.tv/checkembed.php 632 | ||static.flashx.tv/js/flashx.js$script 633 | ||static.flashx.tv/img/player.png$image 634 | ! === dailyuploads.net 635 | dailyuploads.net###adblockinfo 636 | ! === programminginsider.com 637 | programminginsider.com##+js(addEventListener-defuser.js, load, ad-blocker) 638 | programminginsider.com##.g1-top:style(display: block !important;) 639 | ! === allnorilsk.ru 640 | ||allnorilsk.ru/js/adb.js 641 | ! === discudemy.com 642 | discudemy.com##.closeAdBlock 643 | ! === okdiario.com 644 | ||okdiario.com/*/check-blocker.js 645 | ! === radioloyalty.com 646 | radioloyalty.com###bottomDisplayAd 647 | radioloyalty.com###mainDisplayAd 648 | ! === moviesroom.pl 649 | moviesroom.pl###advert-notice 650 | ! === playview.io 651 | playview.io##.ads_player 652 | @@||playview.io/*/showads.js$xmlhttprequest,first-party 653 | ! === dogecatch.website, dashcatch.xyz 654 | dogecatch.website,dashcatch.xyz###fuck-adb-not-enabled 655 | ! === depositfiles.com 656 | depositfiles.com##.adblock_alert 657 | ! === locopelis.com 658 | locopelis.com##.div-banner-popup-event 659 | locopelis.com##+js(abort-on-property-write.js, adbClick) 660 | ! === nba.com 661 | /assets/js/sourcepoint/*$script,domain=nba.com 662 | ! === nbc.com 663 | nbc.com##+js(abort-on-property-read.js, mps._ab) 664 | ! === eurogamer.de 665 | eurogamer.de##+js(abort-on-property-read.js, _sp_.msg.displayMessage) 666 | ! === deportesmax.info 667 | deportesmax.info###wmpu 668 | ! === msfn.org 669 | msfn.org##.displayGlobalMessage:has-text(ad-blocking) 670 | ! === theguardian.com 671 | theguardian.com##div.site-message:has(a[href^="https://membership.theguardian.com/"]) 672 | theguardian.com##.contributions__epic 673 | ! === krassotaa.com 674 | krassotaa.com###haider 675 | ! === onvasortir.com 676 | onvasortir.com##+js(abort-on-property-read.js, adBlockDetected) 677 | ! === kryminalnapolska.pl 678 | kryminalnapolska.pl##+js(abort-on-property-read.js, ai_adb_detected) 679 | ! === doublemesh.com 680 | doublemesh.com##+js(setTimeout-defuser.js, ads) 681 | ! === crockolinks.com 682 | crockolinks.com##+js(addEventListener-defuser.js, mousedown) 683 | ! === NSFW! fakeporn.tv 684 | fakeporn.tv##+js(setTimeout-defuser.js, innerText) 685 | fakeporn.tv##+js(abort-on-property-write.js, prPuShown) 686 | ! === bigbtc.win 687 | bigbtc.win##+js(abort-on-property-read.js, ad_block_test) 688 | ! === github.com 689 | @@/adguard.$domain=github.com 690 | ! === askleo.com 691 | askleo.com##[class^="askleo_adblock1"] 692 | ! === mope.io 693 | ||mope.io/img/blocked.png$image,first-party 694 | ! === geektyper.com 695 | geektyper.com###itemz 696 | ! === demotywatory.pl 697 | ||demotywatory.pl/res/js/advertisement.js$script,important 698 | ! === twinsagadb.com 699 | twinsagadb.com##.top-content 700 | ! === redtube.com 701 | redtube.com###video_right_col > .clearfix 702 | redtube.com##div[class][style]:has(> a.removeAdLink) 703 | redtube.com##div[class][style]:has(> div[class][style] > a.removeAdLink) 704 | @@||rdtcdn.com^$script,domain=redtube.com 705 | ! === bild.de 706 | ||acdn.adnxs.com/*/adplayer.css$stylesheet,redirect=noopcss,domain=bild.de 707 | ! === blockads.fivefilters.org 708 | ||blockads.fivefilters.org$inline-script 709 | blockads.fivefilters.org###no-blocking:style(display: block !important;) 710 | 711 | # ------------------------------------------------------------------------------------------------------------------- # 712 | -------------------------------------------------------------------------------- /list/4-generichide.txt: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------------- # 2 | 3 | @@||20min.ch^$generichide 4 | @@||24opole.pl^$generichide 5 | @@||7sim.net^$generichide 6 | @@||aftonbladet.se^$generichide 7 | @@||al.ly^$generichide 8 | @@||ally.sh^$generichide 9 | @@||ani.gamer.com.tw^$generichide 10 | @@||atresplayer.com^$generichide 11 | @@||behindwoods.com^$generichide 12 | @@||cbs.com^$generichide 13 | @@||citytv.com^$generichide 14 | @@||comicallyincorrect.com^$generichide 15 | @@||ff14angler.com^$generichide 16 | @@||flooxer.com^$generichide 17 | @@||freedomoutpost.com^$generichide 18 | @@||gala.de^$generichide 19 | @@||gamestar.de^$generichide 20 | @@||getrelax.club^$generichide 21 | @@||globalbesthosting.com^$generichide 22 | @@||greenocktelegraph.co.uk^$generichide 23 | @@||hells-hack.com^$generichide 24 | @@||imleagues.com^$generichide 25 | @@||leech.ae^$generichide 26 | @@||libertyunyielding.com^$generichide 27 | @@||linksh.top^$generichide 28 | @@||lolstat.gg^$generichide 29 | @@||main-echo.de^$generichide 30 | @@||mitele.es^$generichide 31 | @@||mycinema.pro^$generichide 32 | @@||playstation.com^$generichide 33 | @@||randaris-anime.net^$generichide 34 | @@||simply-debrid.com^$generichide 35 | @@||stream.nbcsports.com^$generichide 36 | @@||streamplay.gdn^$generichide 37 | @@||symbolab.com^$generichide 38 | @@||tv.yahoo.com^$generichide 39 | @@||tvsportslive.stream^$generichide 40 | @@||viz.com^$generichide 41 | @@||wp.pl^$generichide 42 | @@||yiv.com^$generichide 43 | 44 | # ------------------------------------------------------------------------------------------------------------------- # 45 | -------------------------------------------------------------------------------- /list/5-whitelist.txt: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------------- # 2 | 3 | # These exceptions will not allow ads to show 4 | 5 | # ------------------------------------------------------------------------------------------------------------------- # 6 | 7 | # https://github.com/jspenguin2017/uBlockProtector/issues/155 8 | @@||imasdk.googleapis.com/js/sdkloader/outstream.js$script,domain=ovar.io 9 | 10 | # https://github.com/jspenguin2017/uBlockProtector/issues/338 11 | @@||edgedatg.com^$script,domain=abc.go.com 12 | 13 | # ------------------------------------------------------------------------------------------------------------------- # 14 | 15 | @@||flashx1.tv/js/showad*.js$script 16 | @@||flashx1.tv/sidead.js$script 17 | @@||flashx1.tv/jquery2.js$script 18 | @@||flashx.tv/counter.cgi$script 19 | @@||flashx.to/counter.cgi$script 20 | @@||zencdn.net^$script,domain=flashx.tv 21 | @@/showad_.js$script,domain=flashx.to 22 | 23 | @@/crossdomain.xml$domain=channel4.com 24 | @@||ak.http.anno.channel4.com^$domain=channel4.com 25 | @@||cf.http.anno.channel4.com^$domain=channel4.com 26 | 27 | @@||playapi.mtgx.tv/v3/adinfo?$xmlhttprequest,domain=tvplay.skaties.lv|play.tv3.lt|tv3play.tv3.ee|play.nova.bg 28 | 29 | @@||acortar.net/rollups/aes.js$domain=dclinks.info 30 | 31 | @@||akamaihd.net^$xmlhttprequest,script,domain=mitele.es 32 | 33 | @@||fwmrm.net^$domain=viasatsport.se 34 | ||freewheel-mtgx-tv.akamaized.net^$media,domain=viasatsport.se 35 | ||fwmrm.net^$image,important,domain=viasatsport.se 36 | ||fwmrm.net/ad/*$xmlhttprequest,important,redirect=nooptext,domain=viasatsport.se 37 | 38 | @@||moatads.com/*/moatwrapper.js$script,domain=viz.com 39 | 40 | # ------------------------------------------------------------------------------------------------------------------- # 41 | -------------------------------------------------------------------------------- /notes/extension-development.md: -------------------------------------------------------------------------------- 1 | # Notes for Chromium extension development 2 | 3 | ## Generic notes 4 | 5 | Official manifest documentation page: 6 | https://developer.chrome.com/extensions/manifest 7 | 8 | Official API documentation page: 9 | https://developer.chrome.com/extensions/api_index 10 | 11 | Chromium documentation is generated, which means it sometimes includes weird 12 | things. Here are some extra notes that might be helpful. 13 | 14 | ### Notes for manifest fields 15 | 16 | * `automation`: Experimental, https://developer.chrome.com/extensions/automation 17 | * `background_page`: This field is probably here for legacy reasons, use 18 | `background` with field `page` instead 19 | * `content_capabilities`: Internal use for Chromium developers only, 20 | https://bugs.chromium.org/p/chromium/issues/detail?id=573504 21 | * `converted_from_user_script`: Internally used by Chromium, used to mark an 22 | extension as Userscript, I think it is legacy now 23 | * `current_locale`: Internally used by Chromium, used to detect locale changes 24 | so it can update extension UI 25 | * `input_components`: Used by extensions that acts as Input Method Editor, I 26 | think it only works on Chromium OS, 27 | https://bugs.chromium.org/p/chromium/issues/detail?id=340961#c12 28 | * `oauth2`: OAuth2 related, I think it is legacy now, `chrome.identity` is 29 | probably better, https://developer.chrome.com/extensions/identity 30 | https://stackoverflow.com/questions/35199571/chrome-extension-with-oauth2 31 | * `platforms`: Used by Native Clients to separate download packages, 32 | https://stackoverflow.com/questions/30397450/what-is-platforms-for-in-manifest-json 33 | * `signature`: After 1 hour of research, I found precisely 0 documenation on 34 | it, I guess it has something to do with extension packaging, probably filled 35 | internally by Chromium packaging tool, 36 | https://developer.chrome.com/extensions/packaging 37 | * `spellcheck`: Add spellcheck dictionary, not sure if it is still experimental, 38 | https://stackoverflow.com/questions/21270403/custom-spelling-in-google-chrome 39 | * `system_indicator`: Add tray icons, it is being removed, 40 | https://bugs.chromium.org/p/chromium/issues/detail?id=142450 41 | 42 | ### Notes for permissions 43 | 44 | * `displaySource`: Experimental, documentation page returns 404 not found, 45 | https://bugs.chromium.org/p/chromium/issues/detail?id=702686 46 | * `idltest`: Internal use for Chromium developers only, documentation page 47 | returns 404 not found, 48 | https://bugs.chromium.org/p/chromium/issues/detail?id=644010 49 | 50 | ## Specific notes for Nano Defender 51 | 52 | ### Requested permissions 53 | 54 | * `tabs`: To enforce UserCSS rules 55 | * `webNavigation`: To know the URL of each tab and frame in order to properly 56 | enforce redirection rules 57 | * `webRequest`: To enforce redirection rules 58 | * `webRequestBlocking`: Some `webRequest` handling need to be synchronous 59 | * `http://*/*`, `https://*/*`: To enforce generic content script rules (along 60 | with other rules) 61 | 62 | ### Permissions that might be useful 63 | 64 | * `cookies`: Could be useful when monitoring changes to a cookie is needed, but 65 | this is asynchronous, could be hard to use 66 | -------------------------------------------------------------------------------- /notes/issue-reporter.md: -------------------------------------------------------------------------------- 1 | # Privacy Policy for Quick Issue Reporter 2 | 3 | This Privacy Policy (the "Policy") only applies to the latest unmodified 4 | production build of the Quick Issue Reporter (the "Tool") published and 5 | distributed by `@jspenguin2017` (the "Author"). 6 | 7 | The Tool allows you to quickly report issues related to Nano Adblocker and Nano 8 | Defender (the "Projects") you encounter when browsing the Internet. 9 | 10 | The Tool will only collect your data when you actively use it, and will not 11 | connect to remote servers before the "Send" button is clicked. 12 | 13 | By using the Tool, you consent to: 14 | - The most recent version of the Policy, 15 | - The [privacy policy of GeoJS](https://www.geojs.io/privacy/), 16 | - The [privacy policy of MaxMind](https://www.maxmind.com/en/privacy-policy), 17 | - The 18 | [privacy policy of GitHub](https://help.github.com/en/articles/github-privacy-statement), 19 | and 20 | - The [privacy policy of GitLab](https://about.gitlab.com/privacy/) 21 | 22 | ### Data Collection and Usage 23 | 24 | 1. Your IP address 25 | - We may use GeoJS and/or MaxMind to process your IP address 26 | - You can use a VPN, but make sure that the issue you are reporting can be 27 | reproduced while using your VPN 28 | - The country (if not available, the continent and/or the ISP) that your IP 29 | address belongs to may be shared publicly 30 | 2. User agent string of your browser 31 | - Do not try to mask or change it; if the maintainers are unable to 32 | reproduce the issue, your report will be ignored 33 | 3. Version string of the Projects that you are using 34 | 4. The URL of the page where the Tool is opened 35 | - You are responsible in ensuring that you are not opening the Tool on a 36 | page where the URL is sensitive 37 | 5. The form that you have filled 38 | - If you supplied a test account in the form, that account will not be 39 | shared publicly (it may still be shared with a selected group of 40 | people) 41 | - Please note that although the Author will only select people he trusts 42 | to be part of the group, there is no guarantee of any sort 43 | - The Author takes no responsibility for the actions of other people in 44 | the group 45 | - You are responsible in ensuring information you entered into this form 46 | is not sensitive in nature and test accounts that you supplied contain 47 | only test data 48 | - Please refrain from submitting personally identifiable information 49 | 50 | Collected data will be used to improve the Projects, as well as related 51 | projects such as uAssets. Collected data may be shared with a selected group of 52 | people or publicly unless otherwise indicated above. 53 | 54 | ### Data Deletion 55 | 56 | By using the Tool, you are contributing to open source projects, and you may 57 | not take back your contributions at a later date. 58 | 59 | ### Security Practices 60 | 61 | The server acting as temporary storage is controlled by the Author and has 62 | systems in place to prevent unauthorized access: 63 | - Two Factor Authentication on Amazon Web Services root account 64 | - Public key authentication for Secure Shell access 65 | - Firewall with only necessary ports open 66 | - Automatic HTTPS upgrade for production endpoints 67 | 68 | Moderated reports are stored in GitHub and/or GitLab issues trackers. 69 | 70 | Please note that although the Author is committed in keeping his server secure, 71 | there is no guarantee of any sort. Like many other open source projects, the 72 | Tool is delivered as-is and comes with absolutely no warranty. 73 | 74 | ### Alternative Solutions 75 | 76 | You can report issues to respective issues trackers manually. 77 | 78 | ### Future Versions 79 | 80 | The Policy may be modified at any time, with or without notice. 81 | -------------------------------------------------------------------------------- /src/background/core.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 | // Core library for background rules 22 | 23 | // ----------------------------------------------------------------------------------------------------------------- // 24 | 25 | "use strict"; 26 | 27 | // ----------------------------------------------------------------------------------------------------------------- // 28 | 29 | a.init = () => { 30 | 31 | // ------------------------------------------------------------------------------------------------------------- // 32 | 33 | // Internal messaging 34 | 35 | chrome.runtime.onMessage.addListener((msg, sender, res) => { 36 | if (msg instanceof Object === false || sender instanceof Object === false || typeof res !== "function") 37 | return; 38 | 39 | if (typeof msg.cmd !== "string" || sender.tab instanceof Object === false) 40 | return; 41 | 42 | const tab = sender.tab.id; 43 | const frame = sender.frameId || 0; 44 | 45 | if (typeof tab !== "number" || typeof frame !== "number") 46 | return; 47 | 48 | switch (msg.cmd) { 49 | // Inject UserCSS to caller frame 50 | // 51 | // data - CSS code to inject 52 | case "inject css": 53 | if (typeof msg.data === "string") 54 | a.userCSS(tab, frame, msg.data); 55 | break; 56 | 57 | // Send a highly privileged XMLHttpRequest, it ignores Cross Origin Resource Sharing policies as well as 58 | // adblocker filtering 59 | // Requests must be explicitly whitelisted in a.sanitizeXhr() 60 | // 61 | // details - Details object, see a.xhr() 62 | // 63 | // Returns the response text, or null if the request failed 64 | case "xhr": 65 | if (msg.details instanceof Object) { 66 | const sanitizedDetails = a.sanitizeXhr(sender, msg.details); 67 | if (!sanitizedDetails) 68 | return; 69 | 70 | const onError = () => { 71 | res(null); 72 | }; 73 | 74 | if (a.xhr(sanitizedDetails, res, onError)) { 75 | // Must return true since I need to respond to content script asynchronously 76 | return true; 77 | } else { 78 | onError(); 79 | } 80 | } 81 | break; 82 | 83 | // Forcefully close the caller tab 84 | case "remove tab": 85 | if (tab !== chrome.tabs.TAB_ID_NONE) 86 | chrome.tabs.remove(tab, a.noopErr); 87 | break; 88 | 89 | //@pragma-if-debug 90 | 91 | case "log": 92 | if (a.debugMode) 93 | console.log(msg.data); 94 | break; 95 | 96 | //@pragma-end-if 97 | 98 | default: 99 | break; 100 | } 101 | }); 102 | 103 | // ------------------------------------------------------------------------------------------------------------- // 104 | 105 | // External messaging 106 | 107 | const reporter = chrome.runtime.getURL("/reporter/index.html"); 108 | 109 | chrome.runtime.onMessageExternal.addListener((msg, sender, res) => { 110 | if (msg instanceof Object === false || sender instanceof Object === false || typeof res !== "function") 111 | return; 112 | 113 | if (typeof msg.data !== "string" || sender.id !== a.NanoAdblockerExtensionID) 114 | return; 115 | 116 | switch (msg.data) { 117 | case "Ping": 118 | res({ data: "ok" }); 119 | break; 120 | 121 | case "Open Quick Issue Reporter": 122 | if (typeof msg.tab === "number") { 123 | chrome.tabs.create({ url: reporter + "?" + msg.tab.toString() }); 124 | res({ data: "ok" }); 125 | } 126 | break; 127 | 128 | default: 129 | break; 130 | } 131 | }); 132 | 133 | setTimeout(() => { 134 | chrome.runtime.sendMessage( 135 | a.NanoAdblockerExtensionID, 136 | { 137 | data: "Nano Defender Enabled", 138 | }, 139 | a.noopErr, 140 | ); 141 | }, 15 * 1000); 142 | 143 | // ------------------------------------------------------------------------------------------------------------- // 144 | 145 | // Taken from https://bit.ly/2OJzDAI (GitHub gorhill/uBlock) 146 | 147 | const root = chrome.runtime.getURL("/"); 148 | 149 | chrome.webRequest.onBeforeRequest.addListener( 150 | (details) => { 151 | if (!details.url.endsWith(a.rSecret)) 152 | return { redirectUrl: root }; 153 | }, 154 | { 155 | urls: [ 156 | a.rRoot + "*", 157 | ], 158 | }, 159 | [ 160 | "blocking", 161 | ], 162 | ); 163 | 164 | // ------------------------------------------------------------------------------------------------------------- // 165 | 166 | //@pragma-if-debug 167 | 168 | if (a.debugMode) { 169 | chrome.browserAction.setBadgeText({ text: "DBG" }); 170 | chrome.browserAction.setBadgeBackgroundColor({ color: "#406BD1" }); 171 | } else { 172 | chrome.browserAction.setBadgeText({ text: "DEV" }); 173 | chrome.browserAction.setBadgeBackgroundColor({ color: "#00871D" }); 174 | } 175 | 176 | //@pragma-end-if 177 | 178 | // ------------------------------------------------------------------------------------------------------------- // 179 | 180 | const hasNews = false; 181 | 182 | const newsPage = "https://jspenguin2017.github.io/uBlockProtector/#announcements"; 183 | const newsReadFlag = "news-read"; 184 | 185 | // This handler becomes inactive when there is a popup page set 186 | chrome.browserAction.onClicked.addListener(() => { 187 | chrome.browserAction.setBadgeText({ text: "" }); 188 | 189 | // IMPORTANT: This must match the manifest 190 | chrome.browserAction.setPopup({ popup: "popup/index.html" }); 191 | 192 | localStorage.setItem(newsReadFlag, "true"); 193 | 194 | chrome.tabs.create({ url: newsPage }); 195 | }); 196 | 197 | if (hasNews) { 198 | if (!chrome.extension.inIncognitoContext && !localStorage.getItem(newsReadFlag)) { 199 | chrome.browserAction.setBadgeText({ text: "NEW" }); 200 | chrome.browserAction.setBadgeBackgroundColor({ color: "#FF0000" }); 201 | 202 | chrome.browserAction.setPopup({ popup: "" }); 203 | } 204 | } else { 205 | localStorage.removeItem(newsReadFlag); 206 | } 207 | 208 | // ------------------------------------------------------------------------------------------------------------- // 209 | 210 | }; 211 | 212 | // ----------------------------------------------------------------------------------------------------------------- // 213 | 214 | a.noopErr = () => { 215 | void chrome.runtime.lastError; 216 | }; 217 | 218 | // ----------------------------------------------------------------------------------------------------------------- // 219 | 220 | a.cryptoRandom = () => { 221 | const array = new Uint32Array(4); 222 | crypto.getRandomValues(array); 223 | 224 | let out = ""; 225 | for (const entry of array) 226 | out += entry.toString(16); 227 | 228 | return out; 229 | }; 230 | 231 | // ----------------------------------------------------------------------------------------------------------------- // 232 | 233 | // Redirect helpers 234 | 235 | a.rSecret = a.cryptoRandom(); 236 | 237 | a.rRoot = chrome.runtime.getURL("/resources/"); 238 | 239 | a.rLink = (name) => { 240 | return a.rRoot + name + "?s=" + a.rSecret; 241 | }; 242 | 243 | // ----------------------------------------------------------------------------------------------------------------- // 244 | 245 | // Redirect resources 246 | 247 | // 1 second blank video, taken from https://bit.ly/2JcYAyq (GitHub uBlockOrigin/uAssets). 248 | a.blankMP4 = a.rLink("blank.mp4"); 249 | 250 | // ----------------------------------------------------------------------------------------------------------------- // 251 | 252 | // tab - Id of the tab 253 | // frame - Id of the frame 254 | // 255 | // Returns the Url of the tab, or an empty string if it is not known 256 | a.getTabURL = (() => { 257 | // tabs[tabId][frameId] = url 258 | const tabs = {}; 259 | 260 | //@pragma-if-debug 261 | 262 | if (a.debugMode) 263 | window.getTabURLInternal = tabs; 264 | 265 | //@pragma-end-if 266 | 267 | chrome.tabs.query({}, (existingTabs) => { 268 | for (const existingTab of existingTabs) { 269 | const id = existingTab.id; 270 | if (id === chrome.tabs.TAB_ID_NONE) 271 | continue; 272 | 273 | if (!tabs[id]) 274 | tabs[id] = {}; 275 | 276 | // Keep existing Url because that is probably more up to date 277 | tabs[id][0] = tabs[id][0] || existingTab.url; 278 | 279 | chrome.webNavigation.getAllFrames({ tabId: id }, (frames) => { 280 | if (chrome.runtime.lastError) 281 | return; 282 | 283 | if (!tabs[id]) 284 | return; 285 | 286 | for (const frame of frames) { 287 | const frameId = frame.frameId; 288 | 289 | // Keep existing Url like before 290 | tabs[id][frameId] = tabs[id][frameId] || frame.url; 291 | } 292 | }); 293 | } 294 | }); 295 | 296 | chrome.webNavigation.onCommitted.addListener((details) => { 297 | const { tabId, frameId, url } = details; 298 | 299 | // Clear store when the tab has navigated 300 | if (!tabs[tabId] || frameId === 0) 301 | tabs[tabId] = {}; 302 | 303 | tabs[tabId][frameId] = url; 304 | }); 305 | 306 | chrome.tabs.onRemoved.addListener((id) => { 307 | delete tabs[id]; 308 | }); 309 | 310 | return (tab, frame) => { 311 | if (tabs[tab]) 312 | return tabs[tab][frame] || ""; 313 | else 314 | return ""; 315 | }; 316 | })(); 317 | 318 | // Check if the domain of an URL ends with one of the domains in the list 319 | // A list entry "example.com" will match domains that matches /(^|.*\.)example\.com$/ 320 | // 321 | // url - URL to check 322 | // domList - List of domains to compare 323 | // isMatch - Whether the domains list is a match list 324 | // 325 | // Returns true if the domain of the URL is in the list, false otherwise 326 | a.domCmp = (() => { 327 | const domainExtractor = /^https?:\/\/([^/:?#]+)/; 328 | 329 | return (url, domList, isMatch) => { 330 | let dom = domainExtractor.exec(url); 331 | if (!dom) 332 | return false; 333 | 334 | dom = dom[1]; 335 | 336 | for (const entry of domList) { 337 | if ( 338 | dom.endsWith(entry) && 339 | ( 340 | dom.length === entry.length || 341 | dom.charAt(dom.length - entry.length - 1) === "." 342 | ) 343 | ) { 344 | return true === isMatch; 345 | } 346 | } 347 | 348 | return false === isMatch; 349 | }; 350 | })(); 351 | 352 | // ----------------------------------------------------------------------------------------------------------------- // 353 | 354 | // urls - Urls to loopback 355 | // types - Types of request to loopback 356 | // data - Data to loopback to, must be already encoded and ready to serve 357 | // domList - Domains list, omit to match all domains 358 | // isMatch - Whether the domains list is a match list, defaults to true 359 | a.staticServer = (urls, types, data, domList, isMatch = true) => { 360 | chrome.webRequest.onBeforeRequest.addListener( 361 | (details) => { 362 | const url = a.getTabURL(details.tabId, details.frameId); 363 | 364 | if (!domList || a.domCmp(url, domList, isMatch)) { 365 | 366 | //@pragma-if-debug 367 | 368 | if (a.debugMode) 369 | console.log("Redirected " + details.url + " to " + data); 370 | 371 | //@pragma-end-if 372 | 373 | return { redirectUrl: data }; 374 | } 375 | }, 376 | { 377 | urls: urls, 378 | types: types, 379 | }, 380 | [ 381 | "blocking", 382 | ], 383 | ); 384 | }; 385 | 386 | // urls - Urls to loopback 387 | // types - Types of request to loopback 388 | // server - Server function, it will be passed as the event listener, view Chromium API documentations for more 389 | // information: https://developer.chrome.com/extensions/webRequest 390 | // domList - Domains list, omit to match all domains 391 | // isMatch - Whether the domains list is a match list, defaults to true 392 | a.dynamicServer = (urls, types, server, domList, isMatch = true) => { 393 | chrome.webRequest.onBeforeRequest.addListener( 394 | (details) => { 395 | const url = a.getTabURL(details.tabId, details.frameId); 396 | 397 | if (!domList || a.domCmp(url, domList, isMatch)) { 398 | const response = server(details); 399 | 400 | //@pragma-if-debug 401 | 402 | if (a.debugMode && response) { 403 | if (response.cancel) 404 | console.log("Cancelled " + details.url); 405 | else if (response.redirectUrl) 406 | console.log("Redirected " + details.url + " to " + response.redirectUrl); 407 | } 408 | 409 | //@pragma-end-if 410 | 411 | return response; 412 | } 413 | }, 414 | { 415 | urls: urls, 416 | types: types, 417 | }, 418 | [ 419 | "blocking", 420 | ], 421 | ); 422 | }; 423 | 424 | // ----------------------------------------------------------------------------------------------------------------- // 425 | 426 | // tab - Target tab 427 | // frame - Target frame 428 | // code - CSS code to inject 429 | a.userCSS = (tab, frame, code) => { 430 | if (tab === chrome.tabs.TAB_ID_NONE) 431 | return; 432 | 433 | chrome.tabs.insertCSS(tab, { 434 | code: code, 435 | cssOrigin: "user", 436 | frameId: frame, 437 | }, a.noopErr); 438 | }; 439 | 440 | a.sanitizeXhr = (sener, details) => { 441 | // Nothing is allowed for now 442 | return null; 443 | }; 444 | 445 | // details - Details about this request 446 | // method - Method of the request, can be 'GET' or 'POST' 447 | // url - Url of the request 448 | // headers - Headers of the request, optional 449 | // payload - Payload of the request, optional 450 | // onload - Load handler 451 | // response - Response text 452 | // onerror - Error handler 453 | // 454 | // Returns true if the request is sent, false if details are not valid and the request was not sent 455 | a.xhr = (details, onload, onerror) => { 456 | if (typeof details.method !== "string" || typeof details.url !== "string") 457 | return false; 458 | 459 | if (details.method !== "GET" && details.method !== "POST") 460 | return false; 461 | 462 | console.log("[Nano] Cross Origin Request ::", details.url); 463 | 464 | const req = new XMLHttpRequest(); 465 | 466 | req.onreadystatechange = () => { 467 | if (req.readyState !== XMLHttpRequest.DONE) 468 | return; 469 | 470 | if (req.status === 200) 471 | onload(req.responseText); 472 | else 473 | onerror(); 474 | }; 475 | 476 | req.open(details.method, details.url); 477 | 478 | if (details.headers instanceof Object) { 479 | for (const key in details.headers) { 480 | const header = details.headers[key]; 481 | 482 | if (details.headers.hasOwnProperty(key) && typeof header === "string") 483 | req.setRequestHeader(key, header); 484 | } 485 | } 486 | 487 | if (typeof details.payload === "string") 488 | req.send(payload); 489 | else 490 | req.send(null); 491 | 492 | return true; 493 | }; 494 | 495 | // ----------------------------------------------------------------------------------------------------------------- // 496 | 497 | a.generic = () => { 498 | a.staticServer( 499 | [ 500 | "http://*.medianetworkinternational.com/js/advertisement.js*", 501 | ], 502 | [ 503 | "script", 504 | ], 505 | a.rLink("jquery.js"), 506 | ); 507 | 508 | // Not working correctly 509 | /* 510 | a.staticServer( 511 | [ 512 | "https://imasdk.googleapis.com/js/sdkloader/ima3.js*", 513 | "http://imasdk.googleapis.com/js/sdkloader/ima3.js*", 514 | ], 515 | [ 516 | "script", 517 | ], 518 | a.rLink("ima3.js"), 519 | // List whitelisted domains in the array 520 | //[ 521 | //], 522 | //false, 523 | ); 524 | */ 525 | 526 | a.staticServer( 527 | [ 528 | "https://*.moatads.com/*/MoatFreeWheelJSPEM.js*", 529 | ], 530 | [ 531 | "script", 532 | ], 533 | a.rLink("fw.js"), 534 | ); 535 | }; 536 | 537 | // ----------------------------------------------------------------------------------------------------------------- // 538 | 539 | //@pragma-if-debug 540 | 541 | // Attempt to make the server think the request is from a different IP, rarely works 542 | // Only available in debug mode 543 | // 544 | // urls - Urls to activate on 545 | // ip - Camouflage Ip, keep in mind that the server still have access to your real Ip 546 | // log - Whether details should be logged to console for every matched request, defaults to false 547 | a.proxy = (urls, ip, log) => { 548 | if (!a.debugMode) 549 | return void console.error("a.proxy() is only available in debug mode."); 550 | 551 | chrome.webRequest.onBeforeSendHeaders.addListener( 552 | (details) => { 553 | details.requestHeaders.push({ 554 | name: "X-Forwarded-For", 555 | value: ip, 556 | }); 557 | 558 | details.requestHeaders.push({ 559 | name: "Client-IP", 560 | value: ip, 561 | }); 562 | 563 | if (log) 564 | console.log(details); 565 | 566 | return { requestHeaders: details.requestHeaders }; 567 | }, 568 | { 569 | urls: urls, 570 | }, 571 | [ 572 | "blocking", 573 | "requestHeaders", 574 | ], 575 | ); 576 | }; 577 | 578 | //@pragma-end-if 579 | 580 | // ----------------------------------------------------------------------------------------------------------------- // 581 | -------------------------------------------------------------------------------- /src/background/debug.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 | // Background rules for debugging, only run in debug mode 22 | 23 | // ----------------------------------------------------------------------------------------------------------------- // 24 | 25 | "use strict"; 26 | 27 | // ----------------------------------------------------------------------------------------------------------------- // 28 | 29 | //@pragma-if-debug 30 | 31 | // ----------------------------------------------------------------------------------------------------------------- // 32 | 33 | // Tools 34 | 35 | if (a.debugMode) { 36 | 37 | { 38 | // https://github.com/jspenguin2017/uBlockProtector/issues/338 39 | 40 | a.proxy( 41 | [ 42 | "*://*.go.com/*", 43 | "*://go.com/*", 44 | ], 45 | "107.77.200.10", 46 | ); 47 | } 48 | 49 | { 50 | // https://github.com/jspenguin2017/uBlockProtector/issues/286 51 | 52 | a.proxy( 53 | [ 54 | "*://*.itv.com/*", 55 | "*://itv.com/*", 56 | ], 57 | "88.82.2.10", 58 | ); 59 | } 60 | 61 | { 62 | // https://gitlab.com/xuhaiyang1234/NanoAdblockerSecretIssues/issues/10 63 | 64 | a.proxy( 65 | [ 66 | "*://*.tvnow.de/*", 67 | "*://tvnow.de/*", 68 | ], 69 | "46.101.180.199", 70 | ); 71 | } 72 | 73 | // a.proxy() does not work for: 74 | // topserialy.to 75 | // viasport.fi 76 | 77 | } 78 | 79 | // ----------------------------------------------------------------------------------------------------------------- // 80 | 81 | // Rules 82 | 83 | if (a.debugMode) { 84 | 85 | { 86 | // https://github.com/uBlockOrigin/uAssets/issues/772 87 | 88 | const reBlock = /^https?:\/\/(?:[^.]*?\.)?uplynk\.com\/api\/v3\/preplay\//; 89 | const reStrip = /^https?:\/\/(?:[^.]*?\.)?uplynk\.com\/ext\/[^?]*\.m3u8\?/; 90 | 91 | a.dynamicServer( 92 | [ 93 | "*://*.uplynk.com/*", 94 | "*://uplynk.com/*", 95 | ], 96 | [ 97 | "xmlhttprequest", 98 | ], 99 | (details) => { 100 | if (reBlock.test(details.url)) { 101 | return { cancel: true }; 102 | } else if (reStrip.test(details.url)) { 103 | const i = details.url.indexOf('?'); 104 | return { redirectUrl: details.url.substring(0, i) }; 105 | } 106 | }, 107 | ); 108 | } 109 | 110 | { 111 | // https://github.com/jspenguin2017/uBlockProtector/issues/1015 112 | 113 | chrome.webRequest.onBeforeSendHeaders.addListener( 114 | (details) => { 115 | for (const header of details.requestHeaders) { 116 | if (header.name === "User-Agent") 117 | header.value = "curl/7.47.0"; 118 | } 119 | return { requestHeaders: details.requestHeaders }; 120 | }, 121 | { 122 | urls: [ 123 | "*://5k4i.com/*", 124 | "*://ceesty.com/*", 125 | "*://clkme.me/*", 126 | "*://clkmein.com/*", 127 | "*://cllkme.com/*", 128 | "*://corneey.com/*", 129 | "*://destyy.com/*", 130 | "*://festyy.com/*", 131 | "*://gestyy.com/*", 132 | "*://iklan.master-cyber.com/*", 133 | "*://links.orgasmatrix.com/*", 134 | "*://pj45.com/*", 135 | "*://sh.st/*", 136 | "*://shorte.st/*", 137 | "*://skiip.me/*", 138 | "*://viid.me/*", 139 | "*://wiid.me/*", 140 | "*://wik34.com/*", 141 | "*://xiw34.com/*", 142 | "*://zryydi.com/*", 143 | ], 144 | types: [ 145 | "main_frame", 146 | "sub_frame", 147 | ], 148 | }, 149 | [ 150 | "blocking", 151 | "requestHeaders", 152 | ], 153 | ); 154 | } 155 | 156 | } 157 | 158 | // ----------------------------------------------------------------------------------------------------------------- // 159 | 160 | //@pragma-end-if 161 | 162 | // ----------------------------------------------------------------------------------------------------------------- // 163 | -------------------------------------------------------------------------------- /src/background/rules.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 | // Background rules 22 | 23 | // ----------------------------------------------------------------------------------------------------------------- // 24 | 25 | "use strict"; 26 | 27 | // ----------------------------------------------------------------------------------------------------------------- // 28 | 29 | a.init(); 30 | a.generic(); 31 | 32 | // ----------------------------------------------------------------------------------------------------------------- // 33 | 34 | { 35 | 36 | // No specific rules for now 37 | 38 | } 39 | 40 | // ----------------------------------------------------------------------------------------------------------------- // 41 | -------------------------------------------------------------------------------- /src/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 | // Common constants and initializations for background and content script 22 | 23 | // ----------------------------------------------------------------------------------------------------------------- // 24 | 25 | "use strict"; 26 | 27 | // ----------------------------------------------------------------------------------------------------------------- // 28 | 29 | var a = {}; 30 | 31 | // ----------------------------------------------------------------------------------------------------------------- // 32 | 33 | //@pragma-if-debug 34 | 35 | a.debugMode = true; 36 | 37 | //@pragma-end-if 38 | 39 | // ----------------------------------------------------------------------------------------------------------------- // 40 | -------------------------------------------------------------------------------- /src/content/debug.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 | // Content rules for debugging 22 | // Only run in debug mode 23 | 24 | // ----------------------------------------------------------------------------------------------------------------- // 25 | 26 | "use strict"; 27 | 28 | // ----------------------------------------------------------------------------------------------------------------- // 29 | 30 | //@pragma-if-debug 31 | 32 | // ----------------------------------------------------------------------------------------------------------------- // 33 | 34 | // Tools 35 | 36 | if (a.debugMode) { 37 | 38 | // ------------------------------------------------------------------------------------------------------------- // 39 | 40 | // Force Twitch to show debug logs 41 | if (a.domCmp([ 42 | "twitch.tv", 43 | ], true)) { 44 | a.readOnly("log", "window.console.log.bind(window.console)", "window.console"); 45 | a.readOnly("warn", "window.console.warn.bind(window.console)", "window.console"); 46 | a.readOnly("error", "window.console.error.bind(window.console)", "window.console"); 47 | } 48 | 49 | // ------------------------------------------------------------------------------------------------------------- // 50 | 51 | } 52 | 53 | // ----------------------------------------------------------------------------------------------------------------- // 54 | 55 | // Rules 56 | 57 | if (a.debugMode) { 58 | 59 | // ------------------------------------------------------------------------------------------------------------- // 60 | 61 | // https://github.com/NanoAdblocker/NanoFilters/issues/218 62 | if (a.domCmp([ 63 | "di.fm", 64 | "jazzradio.com", 65 | ])) { 66 | a.loopbackXHR((_ignored, url) => { 67 | if (url.startsWith("https://pubads.g.doubleclick.net/")) { 68 | return [ 69 | '', 70 | '', 71 | '', 72 | ].join("\n"); 73 | } 74 | }); 75 | } 76 | 77 | // ------------------------------------------------------------------------------------------------------------- // 78 | 79 | // https://github.com/NanoMeow/QuickReports/issues/352 80 | // https://github.com/uBlockOrigin/uAssets/issues/4290 81 | // https://github.com/jspenguin2017/uBlockProtector/pull/1045 82 | if (a.domCmp([ 83 | "gamer.com.tw", 84 | ])) { 85 | a.timewarp("setInterval", a.matchMethod.stringExact, "1000"); 86 | a.inject(() => { 87 | "use strict"; 88 | 89 | const _XMLHttpRequest = window.XMLHttpRequest; 90 | 91 | const patchPlayer = (src, beta) => { 92 | const adsTimerOffset = //; 93 | const adsTimerDefinition = "00:00:05"; 94 | 95 | let adsTimerPrompt; 96 | let adsSkipPrompt; 97 | if (beta) { 98 | adsTimerPrompt = /\w\.innerHTML='

'\+window\._molSettings\.skipText.*?"<\/p>"/g; 99 | adsSkipPrompt = /\w\.innerHTML=window\._molSettings\.skipButtonText/g; 100 | } else { 101 | adsTimerPrompt = /\w\.innerHTML="\u5ee3\u544a.*?\u6d88\u9664\u5ee3\u544a.*?\uff1f"/; 102 | adsSkipPrompt = /\w\.innerHTML="\u9ede\u6b64\u8df3\u904e\u5ee3\u544a"/; 103 | } 104 | 105 | const req = new _XMLHttpRequest(); 106 | req.onreadystatechange = () => { 107 | if (req.readyState === 4) { 108 | let payload = req.responseText; 109 | try { 110 | payload = payload.replace(adsTimerOffset, ''); 111 | payload = payload.replace(adsTimerDefinition, "00:00:00"); 112 | payload = payload.replace(adsSkipPrompt, [ 113 | "$('.vast-skip-button')[0].click()", 114 | "$('#ani_video_html5_api').show()", 115 | "$('#ani_video_html5_api').prop('muted', false)", 116 | ].join(",")); 117 | payload = payload.replace(adsTimerPrompt, (match) => { 118 | return "(" + [ 119 | match, 120 | "$('#ani_video_html5_api').hide()", 121 | "$('#ani_video_html5_api').prop('muted', true)", 122 | ].join(",") + ")"; 123 | }); 124 | } catch (err) { } 125 | const script = window.document.createElement("script"); 126 | script.textContent = payload; 127 | window.document.body.append(script); 128 | } 129 | }; 130 | req.open("GET", src); 131 | req.send(); 132 | }; 133 | 134 | const _appendChild = window.Element.prototype.appendChild; 135 | window.Element.prototype.appendChild = function (elem) { 136 | if ( 137 | elem.tagName === "SCRIPT" && 138 | elem.src && 139 | elem.src.startsWith("https://i2.bahamut.com.tw/build/js/animeplayer") 140 | ) { 141 | return void patchPlayer(elem.src, elem.src.includes("beta")); 142 | } 143 | return _appendChild.apply(this, arguments); 144 | }; 145 | }); 146 | } 147 | 148 | // ------------------------------------------------------------------------------------------------------------- // 149 | 150 | } 151 | 152 | // ----------------------------------------------------------------------------------------------------------------- // 153 | 154 | //@pragma-end-if 155 | 156 | // ----------------------------------------------------------------------------------------------------------------- // 157 | -------------------------------------------------------------------------------- /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/jspenguin2017/uBlockProtector/0552c9ba7535678aea73b82a9f0639f992d29143/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.205", 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 | 29 | a.NanoAdblockerExtensionID = "{acf5b849-adb0-4004-b4ff-7f5332f48567}"; 30 | 31 | // ----------------------------------------------------------------------------------------------------------------- // 32 | -------------------------------------------------------------------------------- /src/popup/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0px; 3 | min-width: 250px; 4 | width: auto; 5 | user-select: none; 6 | } 7 | 8 | .title { 9 | background-color: #444444; 10 | color: #FFFFFF; 11 | font-size: 12px; 12 | text-align: center; 13 | padding: 5px; 14 | } 15 | 16 | .title > p { 17 | margin: 0px; 18 | } 19 | 20 | .wrapper { 21 | padding: 6px; 22 | } 23 | 24 | .wrapper:hover { 25 | background-color: #EEEEEE; 26 | } 27 | 28 | .wrapper > svg { 29 | margin-right: 3px; 30 | position: relative; 31 | top: 1px; 32 | width: 16px; 33 | } 34 | 35 | .wrapper > span { 36 | font-size: 14px; 37 | position: relative; 38 | top: -2px; 39 | } 40 | 41 | .separator.dashed { 42 | border-bottom: 1px dashed #CCCCCC; 43 | } 44 | 45 | .separator.solid { 46 | border-bottom: 1px solid #444444; 47 | } 48 | -------------------------------------------------------------------------------- /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 |

18 |

Nano Defender

19 |
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 | Quick Issue Reporter (Beta) 80 |
81 | 82 |
83 | 84 |
85 | 86 | 87 | 88 | Source Code 89 |
90 | 91 |
92 | 93 |
94 | 95 | 96 | 97 | License 98 |
99 | 100 |
101 | 102 |
103 | 104 | 105 | 106 | Credits 107 |
108 | 109 | 110 | -------------------------------------------------------------------------------- /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/reporter/index.css: -------------------------------------------------------------------------------- 1 | /* General */ 2 | * { 3 | appearance: none; 4 | -moz-appearance: none; 5 | -webkit-appearance: none; 6 | font-family: Arial, sans-serif; 7 | } 8 | 9 | body { 10 | font-size: 100%; 11 | margin: 0px; 12 | } 13 | 14 | input[type="text"], textarea { 15 | border: none; 16 | margin: 0px; 17 | width: 100%; 18 | } 19 | 20 | textarea { 21 | resize: vertical; 22 | } 23 | 24 | select { 25 | border: 0px; 26 | padding: 1px 0px 1px 0px; 27 | width: 100%; 28 | } 29 | 30 | @media (min-width: 600px) { 31 | h1 { 32 | font-size: 3em; 33 | } 34 | 35 | h2 { 36 | font-size: 2.25em; 37 | } 38 | 39 | h3 { 40 | font-size: 1.755em; 41 | } 42 | 43 | h4 { 44 | font-size: 1.5em; 45 | } 46 | 47 | h5 { 48 | font-size: 1.245em; 49 | } 50 | 51 | h6 { 52 | font-size: 1.005em; 53 | } 54 | 55 | label { 56 | font-size: 1.5em; 57 | } 58 | 59 | p { 60 | font-size: 1.5em; 61 | } 62 | 63 | input[type="text"], textarea, select { 64 | font-size: 1.25em; 65 | } 66 | } 67 | 68 | /* Basic */ 69 | .hidden { 70 | display: none; 71 | } 72 | 73 | .bold { 74 | font-weight: bold; 75 | } 76 | 77 | .float-left { 78 | float: left; 79 | } 80 | 81 | .float-right { 82 | float: right; 83 | } 84 | 85 | .clear-both { 86 | clear: both; 87 | } 88 | 89 | /* Colors */ 90 | .green { 91 | background-color: #009323; 92 | color: #FFFFFF; 93 | } 94 | 95 | .blue { 96 | background-color: #2463C9; 97 | color: #FFFFFF; 98 | } 99 | 100 | .red { 101 | background-color: #FF5555; 102 | color: #FFFFFF; 103 | } 104 | 105 | /* Buttons */ 106 | button { 107 | border: none; 108 | font-weight: bold; 109 | height: 35px; 110 | margin: 0px; 111 | opacity: 0.7; 112 | padding: 0px 15px; 113 | } 114 | 115 | button:focus { 116 | outline: none; 117 | } 118 | 119 | button:hover { 120 | opacity: 0.85; 121 | } 122 | 123 | button:active { 124 | opacity: 1; 125 | } 126 | 127 | @media (min-width: 600px) { 128 | button { 129 | font-size: 1.5em; 130 | height: 60px; 131 | padding: 0px 25px; 132 | } 133 | } 134 | 135 | /* Containers */ 136 | .container { 137 | background-color: #EEEEEE; 138 | padding: 10px; 139 | margin: 20px 0px; 140 | } 141 | 142 | @media (min-width: 600px) { 143 | .container { 144 | padding-left: 10%; 145 | padding-right: 10%; 146 | } 147 | } 148 | 149 | .container.footer { 150 | background-color: #FFFFFF; 151 | padding-bottom: 0px; 152 | padding-top: 0px; 153 | margin: 0px; 154 | } 155 | 156 | .container.footer p { 157 | color: #808080; 158 | font-size: 0.8em; 159 | } 160 | 161 | /* Popups */ 162 | .popup-container { 163 | background-color: rgba(0, 0, 0, 0.33); 164 | display: none; 165 | height: 100%; 166 | left: 0px; 167 | position: fixed; 168 | top: 0px; 169 | width: 100%; 170 | } 171 | 172 | .popup-container.open { 173 | display: block; 174 | } 175 | 176 | .popup { 177 | background-color: #FFFFFF; 178 | margin: 40px auto; 179 | opacity: 1; 180 | padding: 25px; 181 | width: 80%; 182 | } 183 | 184 | .popup h1, .popup h2, .popup h3, .popup h4, .popup h5, .popup h6 { 185 | border-bottom: 1px solid #808080; 186 | margin: 0px; 187 | padding-bottom: 3px; 188 | } 189 | 190 | @media (min-width: 600px) { 191 | .popup { 192 | width: 60%; 193 | } 194 | 195 | .popup button { 196 | transform: scale(0.75); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/reporter/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | Quick Issue Reporter 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 53 | 54 | 55 | 61 | 62 | 70 | 71 | 77 | 78 | 87 | 88 | 96 | 97 | 107 | 108 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /src/reporter/index.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 | // Script for quick issue reporter 22 | 23 | // ----------------------------------------------------------------------------------------------------------------- // 24 | 25 | "use strict"; 26 | 27 | // ----------------------------------------------------------------------------------------------------------------- // 28 | 29 | const knownGood = [ 30 | // Wrong page 31 | "addons.mozilla.org", 32 | "chrome.google.com", 33 | "hugoxu.com", 34 | "github.com", 35 | "jspenguin2017.github.io", 36 | "local.ntp", 37 | "www.microsoft.com", // Do not remove "www" 38 | 39 | // Bad installation 40 | "blockadblock.com", 41 | "detectadblock.com", 42 | 43 | // Other known good 44 | "youtube.com", 45 | ]; 46 | 47 | const knownBad = [ 48 | // https://github.com/NanoMeow/QuickReports/issues/903 49 | "browserleaks.com", 50 | ]; 51 | 52 | // ----------------------------------------------------------------------------------------------------------------- // 53 | 54 | let initialUrl = ""; 55 | 56 | // ----------------------------------------------------------------------------------------------------------------- // 57 | 58 | const lastReportStorageKey = "quick-issue-reporter-last-report"; 59 | const bugReportDomainSuffix = "-nanobugreport.hugoxu.com"; 60 | 61 | const reportsRateLimit = 900000; // 15 minutes 62 | const detailsLengthLimit = 3072; 63 | 64 | const updateDetailsLengthDisplay = () => { 65 | const length = $("#details").prop("value").length; 66 | 67 | $("#character-count").text(length.toString() + "/" + detailsLengthLimit.toString()); 68 | 69 | if (length > detailsLengthLimit) 70 | $("#character-count").addClass("red"); 71 | else 72 | $("#character-count").rmClass("red"); 73 | }; 74 | 75 | // ----------------------------------------------------------------------------------------------------------------- // 76 | 77 | const appName = (() => { 78 | const manifest = chrome.runtime.getManifest(); 79 | return manifest.name + " " + manifest.version; 80 | })(); 81 | 82 | const showMessage = (msg) => { 83 | $("#msg-specific-error p").html(msg); 84 | $("#msg-specific-error").addClass("open"); 85 | }; 86 | 87 | const domCmp = (domain, matchers) => { 88 | if (domain.endsWith(bugReportDomainSuffix)) 89 | return false; 90 | 91 | for (const d of matchers) { 92 | if (domain.endsWith(d) && (domain.length === d.length || domain.charAt(domain.length - d.length - 1) === ".")) 93 | return true; 94 | } 95 | return false; 96 | }; 97 | 98 | const randId = () => { 99 | const r = Math.random(); 100 | return r.toString(16).substring(2); 101 | }; 102 | 103 | // ----------------------------------------------------------------------------------------------------------------- // 104 | 105 | $("#category").on("change", function () { 106 | if (this.value === "Ads") { 107 | showMessage( 108 | "For missed ads and popups, please report to the EasyList Forum " + 109 | "first.", 110 | ); 111 | } 112 | 113 | if (this.value === "Bug") 114 | $("#url").prop("value", "https://" + randId() + bugReportDomainSuffix + "/").attr("disabled", ""); 115 | else 116 | $("#url").prop("value", initialUrl).rmAttr("disabled"); 117 | }); 118 | 119 | $("#details").on("input", updateDetailsLengthDisplay); 120 | updateDetailsLengthDisplay(); 121 | 122 | $("#send").on("click", async () => { 123 | const category = $("#category").prop("value"); 124 | const url = $("#url").prop("value").trim(); 125 | const details = $("#details").prop("value"); 126 | 127 | if (!category) 128 | return void showMessage("Please select an issue type."); 129 | 130 | let domain = /^https?:\/\/([^/]+)/.exec(url); 131 | if (!domain) 132 | return void showMessage("Please enter a valid URL."); 133 | 134 | domain = domain[1]; 135 | if (domCmp(domain, knownGood)) 136 | return void $("#msg-known-good").addClass("open"); 137 | if (domCmp(domain, knownBad)) 138 | return void $("#msg-known-bad").addClass("open"); 139 | 140 | if (category === "Other" && details.length < 10) { 141 | return void showMessage( 142 | "Please add a quick explanation for the "Other issue" category that you have chosen " + 143 | "(minimum 10 characters).", 144 | ); 145 | } 146 | if (category === "Bug" && details.length < 100) { 147 | return void showMessage( 148 | "Please incude a detailed step-by-step reproduction guide for this issue (minimum 100 characters).", 149 | ); 150 | } 151 | 152 | if (details.length > detailsLengthLimit) { 153 | return void showMessage( 154 | "Additional details can be at most " + detailsLengthLimit.toString() + " characters long.", 155 | ); 156 | } 157 | 158 | const payload = [ 159 | "send", 160 | "Quick Issue Reporter", 161 | navigator.userAgent, 162 | appName, 163 | "", 164 | "[" + category + "] " + url, 165 | "", 166 | ]; 167 | if (url !== initialUrl) { 168 | payload.push( 169 | "Original URL: `" + initialUrl + "`", 170 | "", 171 | ); 172 | } 173 | payload.push(details); 174 | 175 | let response; 176 | try { 177 | response = await post(payload.join("\n")); 178 | } catch (err) { 179 | return void $("#msg-generic-error").addClass("open"); 180 | } 181 | 182 | if (response === "ok") { 183 | localStorage.setItem(lastReportStorageKey, Date.now()); 184 | $("#msg-report-sent").addClass("open"); 185 | $("#main").addClass("hidden"); 186 | } else { 187 | console.error(response); 188 | $("#msg-generic-error").addClass("open"); 189 | } 190 | }); 191 | 192 | $(".popup-container button.float-right").on("click", function () { 193 | this.parentNode.parentNode.classList.remove("open"); 194 | }); 195 | 196 | // ----------------------------------------------------------------------------------------------------------------- // 197 | 198 | const init = () => { 199 | let lastReport = localStorage.getItem(lastReportStorageKey); 200 | 201 | // Maximum accuracy of integer is about 16 digits 202 | // Cap at 15 digits to be safe, which is still more than enough to represent the next 30 thousand years 203 | if (/^\d{13,15}$/.test(lastReport)) 204 | lastReport = parseInt(lastReport); 205 | 206 | const now = Date.now(); 207 | if (typeof lastReport === "number" && lastReport + reportsRateLimit > now) 208 | $("#msg-rate-limited").addClass("open"); 209 | else 210 | $("#main").rmClass("hidden"); 211 | }; 212 | 213 | if (/^\?\d{1,15}$/.test(location.search)) { 214 | chrome.tabs.get(parseInt(location.search.substring(1)), (tab) => { 215 | if (!chrome.runtime.lastError) { 216 | initialUrl = tab.url; 217 | if ($("#url").prop("value").trim() === "") 218 | $("#url").prop("value", tab.url); 219 | } 220 | 221 | init(); 222 | }); 223 | } else { 224 | init(); 225 | } 226 | 227 | // ----------------------------------------------------------------------------------------------------------------- // 228 | -------------------------------------------------------------------------------- /src/reporter/paper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Paper library. 3 | */ 4 | "use strict"; 5 | 6 | /** 7 | * Toggle wait screen. 8 | * @function 9 | */ 10 | const wait = (() => { 11 | const $popup = document.getElementById("paper-wait"); 12 | 13 | let state = false; 14 | return () => { 15 | if (state) { 16 | $popup.classList.remove("open"); 17 | } else { 18 | $popup.classList.add("open"); 19 | } 20 | 21 | state = !state; 22 | }; 23 | })(); 24 | 25 | /** 26 | * Send a POST request to the standard API endpoint. 27 | * @async @function 28 | * @param {string} payload - The payload to send. 29 | * @return {string} The response text when successful. 30 | * @throws {XMLHttpRequest} The XMLHttpRequest instance when not successful. 31 | */ 32 | const post = (payload) => { 33 | return new Promise((resolve, reject) => { 34 | wait(); 35 | 36 | let req = new XMLHttpRequest(); 37 | 38 | req.onreadystatechange = () => { 39 | if (req.readyState === XMLHttpRequest.DONE) { 40 | wait(); 41 | 42 | if (req.status === 200) { 43 | resolve(req.responseText); 44 | } else { 45 | reject(req); 46 | } 47 | } 48 | }; 49 | 50 | req.open("POST", "https://legacy.hugoxu.com/PrivateMessage/Report.php"); 51 | req.send(payload); 52 | }); 53 | }; 54 | -------------------------------------------------------------------------------- /src/resources/blank.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jspenguin2017/uBlockProtector/0552c9ba7535678aea73b82a9f0639f992d29143/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 | --------------------------------------------------------------------------------