diff --git a/assets/checksums.txt b/assets/checksums.txt index 37dd7033c..b163dbeee 100644 --- a/assets/checksums.txt +++ b/assets/checksums.txt @@ -1,5 +1,5 @@ 7edb2a585b445f28aa5ab06306f1a23f assets/ublock/privacy.txt -c120e92f634173e63362651858766da2 assets/ublock/filters.txt +1972fb1f3f18805a3e2468c9ea3cbdbd assets/ublock/filters.txt dcf3e05bae803343c9d632f0baf8bedd assets/ublock/mirror-candidates.txt 9947b5510d67e47ea59ce876e4fc67be assets/ublock/filter-lists.json 132b3ecc9da8a68c3faf740c00af734b assets/thirdparties/adblock-plus-japanese-filter.googlecode.com/hg/abp_jp.txt diff --git a/assets/ublock/filters.txt b/assets/ublock/filters.txt index 390ba160e..173299ca6 100644 --- a/assets/ublock/filters.txt +++ b/assets/ublock/filters.txt @@ -242,3 +242,20 @@ ovh.strim.io#@##tweets # https://github.com/gorhill/uBlock/issues/510#issuecomment-71050211 ||racksauce.com^$domain=promptfile.com + +# https://github.com/gorhill/uBlock/issues/510#issuecomment-71078475 +|http://$popup,domain=filenuke.com|sharesix.com +||filenuke.com/a/script.js$script +||mwem.filenuke.com/*/*$script +||rrnq.filenuke.com/*/*$script +||szbek.filenuke.com/*/*$script +||wwegr.filenuke.com/*/*$script +||sharesix.com/a/script.js$script +||hhg.sharesix.com/*/*$script +||jha.sharesix.com/*/*$script +||lsg.sharesix.com/*/*$script +||nvy.sharesix.com/*/*$script + +# https://github.com/gorhill/uBlock/issues/580 +# To counter `liverail.com` in Dan Pollock's, hpHosts, MVPS, Peter Lowe's +@@||cdn-static.liverail.com$domain=9to5mac.com \ No newline at end of file diff --git a/dist/description/description-nl.txt b/dist/description/description-nl.txt index 39f9804f8..73c61566a 100644 --- a/dist/description/description-nl.txt +++ b/dist/description/description-nl.txt @@ -1,8 +1,8 @@ -Een efficiënte blokkeerder: light geheugen- en CPU-verbruik. Toch kan het duizenden filters meer laden en gebruiken dan andere populaire blokkeerders. +Een efficiënte blokkeerder: licht geheugen- en CPU-verbruik. Toch kan het duizenden filters meer laden en gebruiken dan andere populaire blokkeerders. -Geïllustreerd overzicht van de efficiëntie : https://github.com/gorhill/uBlock/wiki/%C2%B5Block-vs.-ABP:-efficiency-compared +Geïllustreerd overzicht van de efficiëntie: https://github.com/gorhill/uBlock/wiki/%C2%B5Block-vs.-ABP:-efficiency-compared -Gebruik: De grote aan/uit-knop in de popup is om permanent µBlock in/uit te schakelen voor de huidige website. Het past enkel op de huidige website toe. Het is geen globale aan/uit-knop. +Hoe te gebruiken: De grote aan/uit-knop in de popup is om µBlock permanent in/uit te schakelen voor de huidige website. Het wordt enkel op de huidige website toegepast. Het is geen globale aan/uit-knop. *** @@ -26,13 +26,13 @@ Meer lijsten zijn beschikbaar om te selecteren indien gewenst: - Spam404 - Etc. -Natuurlijk wordt het geheugenverbruik groter naarmate er meer filters worden ingeschakeld. Zelfs na Fanboy's two extra lijsten, hpHosts’s Ad and tracking servers toe te voegen heeft µBlock een lagere geheugenverbruik dan andere populaire blokkeerders. +Natuurlijk wordt het geheugenverbruik groter naarmate er meer filters worden ingeschakeld. Maar zelfs na Fanboy's two extra lijsten, hpHosts’s Ad en tracking servers toe te voegen heeft µBlock een lager geheugenverbruik dan andere populaire blokkeerders. -Let op, sommige van deze extra lijsten verhoogt de kans dat websites breken -- zeker de lijsten die normaal als hosts-bestand worden gebruikt. +Let op, het gebruik van sommige van deze extra lijsten verhoogt de kans dat websites breken -- zeker de lijsten die normaal als hosts-bestand worden gebruikt. *** -Zonder de standaard filterlijst doet deze extensie niets. Dus als je ooit echt een bijdrage wilt leveren, denk dan aan de mensen die hard werken om deze filterlijsten die je aan het gebruiken bent de onderhouden, die allemaal gratis beschikbaar en te gebruiken zijn. +Zonder de standaard filterlijst doet deze extensie niets. Dus als je ooit echt een bijdrage wilt leveren, denk dan aan de mensen die hard werken om de filterlijsten die je aan het gebruiken bent te onderhouden, die allemaal gratis beschikbaar en te gebruiken zijn. *** diff --git a/src/_locales/ar/messages.json b/src/_locales/ar/messages.json index bb4dd13f6..53a046fdf 100644 --- a/src/_locales/ar/messages.json +++ b/src/_locales/ar/messages.json @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Network request log", + "message":"ميكرو بلوك - سجل الإتصال بالشبكة", "description":"Title for the network request log window" }, "aboutPageName":{ diff --git a/src/_locales/cs/messages.json b/src/_locales/cs/messages.json index 2d588737f..165b544e6 100644 --- a/src/_locales/cs/messages.json +++ b/src/_locales/cs/messages.json @@ -280,7 +280,7 @@ "description":"English: Multipurpose" }, "3pGroupRegions":{ - "message":"Regiony, jazyky", + "message":"Regionální, jazykové", "description":"English: Regions, languages" }, "3pGroupCustom":{ diff --git a/src/_locales/de/messages.json b/src/_locales/de/messages.json index bfc85bbc3..6605d98bd 100644 --- a/src/_locales/de/messages.json +++ b/src/_locales/de/messages.json @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Network request log", + "message":"µBlock — Protokoll der Netzwerk-Anforderungen", "description":"Title for the network request log window" }, "aboutPageName":{ @@ -352,11 +352,11 @@ "description":"default file name to use" }, "rulesHint":{ - "message":"List of your dynamic filtering rules.", + "message":"Liste deiner dynamischen Filterregeln.", "description":"English: List of your dynamic filtering rules." }, "rulesFormatHint":{ - "message":"Rule syntax: source destination type action<\/code> (full documentation<\/a>).", + "message":"Regel-Syntax: Quelle Ziel Typ Action<\/code> ( vollständige Dokumentation<\/a>).", "description":"English: dynamic rule syntax and full documentation." }, "whitelistPrompt":{ @@ -420,7 +420,7 @@ "description":"English: No non-blocked requests logged for this page" }, "logBehindTheScene":{ - "message":"Behind the scene", + "message":"Hintergrundanfragen", "description":"Pretty name for behind-the-scene network requests" }, "aboutChangelog":{ diff --git a/src/_locales/el/messages.json b/src/_locales/el/messages.json index 837fb0e37..944710ea3 100644 --- a/src/_locales/el/messages.json +++ b/src/_locales/el/messages.json @@ -24,7 +24,7 @@ "description":"appears as tab name in dashboard" }, "rulesPageName":{ - "message":"My rules", + "message":"Οι κανόνες μου", "description":"appears as tab name in dashboard" }, "whitelistPageName":{ @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Network request log", + "message":"μBlock - Καταγραφή δικτυακής αίτησης", "description":"Title for the network request log window" }, "aboutPageName":{ @@ -152,7 +152,7 @@ "description":"" }, "popupImageRulePrompt":{ - "message":"images", + "message":"Εικόνες", "description":"" }, "popupInlineScriptRulePrompt":{ diff --git a/src/_locales/es/messages.json b/src/_locales/es/messages.json index 40b7a2153..eb6d87b6d 100644 --- a/src/_locales/es/messages.json +++ b/src/_locales/es/messages.json @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Network request log", + "message":"µBlock — Registro de peticiones de red", "description":"Title for the network request log window" }, "aboutPageName":{ @@ -352,11 +352,11 @@ "description":"default file name to use" }, "rulesHint":{ - "message":"List of your dynamic filtering rules.", + "message":"Listado de sus reglas de filtrado dinámico.", "description":"English: List of your dynamic filtering rules." }, "rulesFormatHint":{ - "message":"Rule syntax: source destination type action<\/code> (full documentation<\/a>).", + "message":"Sintaxis de las reglas: origen destino tipo acción<\/code> ( documentación completa<\/a>).", "description":"English: dynamic rule syntax and full documentation." }, "whitelistPrompt":{ @@ -420,7 +420,7 @@ "description":"English: No non-blocked requests logged for this page" }, "logBehindTheScene":{ - "message":"Behind the scene", + "message":"Peticiones ocultas", "description":"Pretty name for behind-the-scene network requests" }, "aboutChangelog":{ diff --git a/src/_locales/hi/messages.json b/src/_locales/hi/messages.json index 2d367556f..8f04b615f 100644 --- a/src/_locales/hi/messages.json +++ b/src/_locales/hi/messages.json @@ -24,7 +24,7 @@ "description":"appears as tab name in dashboard" }, "rulesPageName":{ - "message":"My rules", + "message":"मेरे नियम", "description":"appears as tab name in dashboard" }, "whitelistPageName":{ diff --git a/src/_locales/hu/messages.json b/src/_locales/hu/messages.json index 75d1558e4..d3aa1ffb2 100644 --- a/src/_locales/hu/messages.json +++ b/src/_locales/hu/messages.json @@ -4,7 +4,7 @@ "description":"extension name." }, "extShortDesc":{ - "message":"Végre egy hatékony reklám és követésblokkoló, amely kíméletes a processzorral és a memóriával.", + "message":"Végre egy hatékony reklám- és követésblokkoló böngészőkhöz, amely kíméletes a processzorral és a memóriával.", "description":"this will be in the chrome web store: must be 132 characters or less" }, "dashboardName":{ @@ -24,7 +24,7 @@ "description":"appears as tab name in dashboard" }, "rulesPageName":{ - "message":"My rules", + "message":"Saját szabályok", "description":"appears as tab name in dashboard" }, "whitelistPageName":{ @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Network request log", + "message":"µBlock — Hálózati forgalom napló", "description":"Title for the network request log window" }, "aboutPageName":{ @@ -72,107 +72,107 @@ "description":"English: Go to request log" }, "popupSiteInlineScriptEnabled":{ - "message":"Inline script<\/code> tags are allowed<\/b> on this site", + "message":"Beszúrt parancsfájl<\/code> tag-ek engedélyezve<\/b> ezen a webhelyen", "description":"" }, "popupSiteInlineScriptDisabled":{ - "message":"Inline script<\/code> tags are blocked<\/b> on this site", + "message":"Beszúrt parancsfájl<\/code> tag-ek letiltva<\/b> ezen a webhelyen", "description":"" }, "popupSite1pScriptEnabled":{ - "message":"1st-party scripts are allowed<\/b> on this site", + "message":"Webhelytől származó parancsfájlok engedélyezve<\/b> ezen a webhelyen", "description":"" }, "popupSite1pScriptDisabled":{ - "message":"1st-party scripts are blocked<\/b> on this site", + "message":"Webhelytől származó parancsfájlok letiltva<\/b> ezen a webhelyen", "description":"" }, "popupSite3pScriptEnabled":{ - "message":"3rd-party scripts are allowed<\/b> on this site", + "message":"Külső webhelytől származó parancsfájlok engedélyezve<\/b> ezen a webhelyen", "description":"" }, "popupSite3pScriptDisabled":{ - "message":"3rd-party scripts are blocked<\/b> on this site", + "message":"Külső webhelytől származó parancsfájlok letiltva<\/b> ezen a webhelyen", "description":"" }, "popupSite1pFrameEnabled":{ - "message":"1st-party frames are allowed<\/b> on this site", + "message":"Webhelytől származó keretek engedélyezve<\/b> ezen a webhelyen", "description":"" }, "popupSite1pFrameDisabled":{ - "message":"1st-party frames are blocked<\/b> on this site", + "message":"Webhelytől származó keretek letiltva<\/b> ezen a webhelyen", "description":"" }, "popupSite3pFrameEnabled":{ - "message":"3rd-party frames are allowed<\/b> on this site", + "message":"Külső webhelytől származó keretek engedélyezve<\/b> ezen a webhelyen", "description":"" }, "popupSite3pFrameDisabled":{ - "message":"3rd-party frames are blocked<\/b> on this site", + "message":"Külső webhelytől származó keretek letiltva<\/b> ezen a webhelyen", "description":"" }, "popupDefaultInlineScriptEnabled":{ - "message":"Inline script<\/code> tags are allowed<\/b> everywhere by default", + "message":"Beszúrt parancsfájl<\/code> tag-ek alapértelmezetten engedélyezve<\/b> minden webhelyen", "description":"" }, "popupDefaultInlineScriptDisabled":{ - "message":"Inline script<\/code> tags are blocked<\/b> everywhere by default", + "message":"Beszúrt parancsfájl<\/code> tag-ek alapértelmezetten letiltva<\/b> minden webhelyen", "description":"" }, "popupDefault1pScriptEnabled":{ - "message":"1st-party scripts are allowed<\/b> everywhere by default", + "message":"Webhelytől származó parancsfájlok alapértelmezetten engedélyezve<\/b> minden webhelyen", "description":"" }, "popupDefault1pScriptDisabled":{ - "message":"1st-party scripts are blocked<\/b> everywhere by default", + "message":"Webhelytől származó parancsfájlok alapértelmezetten letiltva<\/b> minden webhelyen", "description":"" }, "popupDefault3pScriptEnabled":{ - "message":"3rd-party scripts are allowed<\/b> everywhere by default", + "message":"Külső webhelytől származó parancsfájlok alapértelmezetten engedélyezve<\/b> minden webhelyen", "description":"" }, "popupDefault3pScriptDisabled":{ - "message":"3rd-party scripts are blocked<\/b> everywhere by default", + "message":"Külső webhelytől származó parancsfájlok alapértelmezetten letiltva<\/b> minden webhelyen", "description":"" }, "popupDefault1pFrameEnabled":{ - "message":"1st-party frames are allowed<\/b> everywhere by default", + "message":"Webhelytől származó keretek alapértelmezetten engedélyezve<\/b> minden webhelyen", "description":"" }, "popupDefault1pFrameDisabled":{ - "message":"1st-party frames are blocked<\/b> everywhere by default", + "message":"Webhelytől származó keretek alapértelmezetten letiltva<\/b> minden webhelyen", "description":"" }, "popupDefault3pFrameEnabled":{ - "message":"3rd-party frames are allowed<\/b> everywhere by default", + "message":"Külső webhelytől származó keretek alapértelmezetten engedélyezve<\/b> minden webhelyen", "description":"" }, "popupDefault3pFrameDisabled":{ - "message":"3rd-party frames are blocked<\/b> everywhere by default", + "message":"Külső webhelytől származó keretek alapértelmezetten letiltva<\/b> minden webhelyen", "description":"" }, "popupImageRulePrompt":{ - "message":"images", + "message":"képek", "description":"" }, "popupInlineScriptRulePrompt":{ - "message":"inline scripts", + "message":"beszúrt parancsfájlok", "description":"" }, "popup1pScriptRulePrompt":{ - "message":"1st-party scripts", + "message":"Webhelytől származó parancsfájlok", "description":"" }, "popup3pScriptRulePrompt":{ - "message":"3rd-party scripts", + "message":"Külső webhelytől származó parancsfájlok", "description":"" }, "popup3pFrameRulePrompt":{ - "message":"3rd-party frames", + "message":"Külső webhelytől származó keretek", "description":"" }, "popupHitDomainCountPrompt":{ - "message":"Connected to {{count}} distinct domain(s) out of {{total}}", + "message":"Kapcsolódva {{count}} eltérő tartományhoz, összesen: {{total}}", "description":"appear in dynamic filtering pane" }, "pickerCreate":{ @@ -216,7 +216,7 @@ "description":"English: Make use of context menu where appropriate" }, "settingsAdvancedUserPrompt":{ - "message":"I am an advanced user (Required reading<\/a>)", + "message":"Haladó felhasználó vagyok (További tudnivalók<\/a>)", "description":"English: " }, "settingsExperimentalPrompt":{ @@ -320,7 +320,7 @@ "description":"English: Export" }, "1pExportFilename":{ - "message":"my-ublock-static-filters_{{datetime}}.txt", + "message":"ublock-statikus-szabalyok_{{datetime}}.txt", "description":"English: my-ublock-static-filters_{{datetime}}.txt" }, "1pApplyChanges":{ @@ -336,27 +336,27 @@ "description":"Will save manually-edited content and exit manual-edit mode" }, "rulesEditDiscard":{ - "message":"Mégsem", + "message":"Mégse", "description":"Will discard manually-edited content and exit manual-edit mode" }, "rulesImport":{ - "message":"Importálás fájlból...", + "message":"Importálás fájlból…", "description":"" }, "rulesExport":{ - "message":"Exportálás fájlba...", + "message":"Exportálás fájlba…", "description":"" }, "rulesDefaultFileName":{ - "message":"ublock-dinamikus_szabalyaim.txt", + "message":"ublock-dinamikus-szabalyok_{{datetime}}.txt", "description":"default file name to use" }, "rulesHint":{ - "message":"List of your dynamic filtering rules.", + "message":"Saját szűrőszabályok listája.", "description":"English: List of your dynamic filtering rules." }, "rulesFormatHint":{ - "message":"Rule syntax: source destination type action<\/code> (full documentation<\/a>).", + "message":"Szabályrendszer: forrás cél típus művelet<\/code> (Teljes dokumentáció<\/a>).", "description":"English: dynamic rule syntax and full documentation." }, "whitelistPrompt":{ @@ -372,7 +372,7 @@ "description":"English: Export" }, "whitelistExportFilename":{ - "message":"my-ublock-whitelist_{{datetime}}.txt", + "message":"ublock-kivetelek_{{datetime}}.txt", "description":"English: my-ublock-whitelist_{{datetime}}.txt" }, "whitelistApply":{ @@ -420,7 +420,7 @@ "description":"English: No non-blocked requests logged for this page" }, "logBehindTheScene":{ - "message":"Behind the scene", + "message":"Hálózati forgalom a háttérben", "description":"Pretty name for behind-the-scene network requests" }, "aboutChangelog":{ @@ -444,7 +444,7 @@ "description":"English: Backup to file" }, "aboutBackupFilename":{ - "message":"my-ublock-backup_{{datetime}}.txt", + "message":"ublock-mentes_{{datetime}}.txt", "description":"English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton":{ @@ -460,7 +460,7 @@ "description":"Message asking user to confirm restore" }, "aboutRestoreDataError":{ - "message":"The data could not be read or is invalid", + "message":"Nem olvasható vagy érvénytelen adat", "description":"Message to display when an error occurred during restore" }, "aboutResetDataConfirm":{ diff --git a/src/_locales/ja/messages.json b/src/_locales/ja/messages.json index 58fa78792..59a369827 100644 --- a/src/_locales/ja/messages.json +++ b/src/_locales/ja/messages.json @@ -1,6 +1,6 @@ { "extName":{ - "message":"μブロック", + "message":"µBlock", "description":"extension name." }, "extShortDesc":{ @@ -16,7 +16,7 @@ "description":"appears as tab name in dashboard" }, "3pPageName":{ - "message":"第三者製フィルター", + "message":"サードパーティ製フィルター", "description":"appears as tab name in dashboard" }, "1pPageName":{ @@ -40,7 +40,7 @@ "description":"appears as tab name in dashboard" }, "popupPowerSwitchInfo":{ - "message":"このボタンを押して
今のサイトだけに
エクステンションを完全にオンかオフにする", + "message":"µBlock の有効 \/ 無効を切り替えます。\n\nクリック: サイト全体 \nCtrl+クリック: このページのみ", "description":"English: Click: disable\/enable µBlock for this site.\n\nCtrl+click: disable µBlock only on this page." }, "popupBlockedRequestPrompt":{ @@ -52,7 +52,7 @@ "description":"English: on this page" }, "popupBlockedSinceInstallPrompt":{ - "message":"インストール以来", + "message":"インストールしてから", "description":"English: since install" }, "popupOr":{ @@ -220,7 +220,7 @@ "description":"English: " }, "settingsExperimentalPrompt":{ - "message":"実験的な機能を有効にする", + "message":"実験的な機能を有効にする (
About<\/a>)", "description":"English: Enable experimental features" }, "3pListsOfBlockedHostsPrompt":{ @@ -380,7 +380,7 @@ "description":"English: Apply changes" }, "logNetRequestsPrompt":{ - "message":"ネットワークリクエストのログ収集を有効にする", + "message":"ネットワークリクエストのログを有効にする", "description":"English: Enable the logging of network requests" }, "logNetRequestsHelp":{ @@ -388,7 +388,7 @@ "description":"English: see _locales\/en\/messages.log" }, "logBlockedRequestsHeader":{ - "message":"ブロックされたリルエスト", + "message":"ブロックされたリクエスト", "description":"English: Blocked requests" }, "logAllowedRequestsHeader":{ @@ -404,7 +404,7 @@ "description":"English: Domain" }, "logRequestsHeaderURL":{ - "message":"インターネットアドレス", + "message":"URL", "description":"English: URL" }, "logRequestsHeaderFilter":{ @@ -424,7 +424,7 @@ "description":"Pretty name for behind-the-scene network requests" }, "aboutChangelog":{ - "message":"の変更履歴", + "message":"バージョン更新履歴 (Change log)", "description":"English: Change log" }, "aboutWiki":{ @@ -432,7 +432,7 @@ "description":"English: project' wiki on Github" }, "aboutCode":{ - "message":"根源コード(GPLバージョン3)", + "message":"ソースコード (GPLバージョン3)", "description":"English: Source code (GPLv3)" }, "aboutContributors":{ diff --git a/src/_locales/nl/messages.json b/src/_locales/nl/messages.json index bf45cfd3e..346228331 100644 --- a/src/_locales/nl/messages.json +++ b/src/_locales/nl/messages.json @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Network request log", + "message":"µBlock — Log van netwerkverzoeken", "description":"Title for the network request log window" }, "aboutPageName":{ @@ -320,7 +320,7 @@ "description":"English: Export" }, "1pExportFilename":{ - "message":"my-ublock-static-filters_{{datetime}}.txt", + "message":"mijn-ublock-statische-filters_{{datetime}}.txt", "description":"English: my-ublock-static-filters_{{datetime}}.txt" }, "1pApplyChanges":{ @@ -348,15 +348,15 @@ "description":"" }, "rulesDefaultFileName":{ - "message":"my-ublock-dynamic-rules_{{datetime}}.txt", + "message":"mijn-ublock-dynamische-regels_{{datetime}}.txt", "description":"default file name to use" }, "rulesHint":{ - "message":"List of your dynamic filtering rules.", + "message":"Lijst van uw dynamische filterregels.", "description":"English: List of your dynamic filtering rules." }, "rulesFormatHint":{ - "message":"Rule syntax: source destination type action<\/code> (full documentation<\/a>).", + "message":"Regelsyntax: bron bestemming type actie<\/code> (volledige documentatie<\/a>).", "description":"English: dynamic rule syntax and full documentation." }, "whitelistPrompt":{ @@ -372,7 +372,7 @@ "description":"English: Export" }, "whitelistExportFilename":{ - "message":"my-ublock-whitelist_{{datetime}}.txt", + "message":"mijn-ublock-whitelist_{{datetime}}.txt", "description":"English: my-ublock-whitelist_{{datetime}}.txt" }, "whitelistApply":{ @@ -420,7 +420,7 @@ "description":"English: No non-blocked requests logged for this page" }, "logBehindTheScene":{ - "message":"Behind the scene", + "message":"Achter de schermen", "description":"Pretty name for behind-the-scene network requests" }, "aboutChangelog":{ @@ -444,7 +444,7 @@ "description":"English: Backup to file" }, "aboutBackupFilename":{ - "message":"my-ublock-backup_{{datetime}}.txt", + "message":"mijn-ublock-backup_{{datetime}}.txt", "description":"English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton":{ diff --git a/src/_locales/pt_PT/messages.json b/src/_locales/pt_PT/messages.json index f7750a06e..8fc4fd941 100644 --- a/src/_locales/pt_PT/messages.json +++ b/src/_locales/pt_PT/messages.json @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Network request log", + "message":"µBlock — Registo de pedidos de rede", "description":"Title for the network request log window" }, "aboutPageName":{ @@ -352,11 +352,11 @@ "description":"default file name to use" }, "rulesHint":{ - "message":"List of your dynamic filtering rules.", + "message":"Lista das suas regras de filtragem dinâmicas.", "description":"English: List of your dynamic filtering rules." }, "rulesFormatHint":{ - "message":"Rule syntax: source destination type action<\/code> (full documentation<\/a>).", + "message":"Regra de sintaxe: origem destino tipo ação<\/code> (documentação completa<\/a>).", "description":"English: dynamic rule syntax and full documentation." }, "whitelistPrompt":{ @@ -420,7 +420,7 @@ "description":"English: No non-blocked requests logged for this page" }, "logBehindTheScene":{ - "message":"Behind the scene", + "message":"Bastiadores", "description":"Pretty name for behind-the-scene network requests" }, "aboutChangelog":{ diff --git a/src/_locales/sv/messages.json b/src/_locales/sv/messages.json index ac5fefe35..cc263081b 100644 --- a/src/_locales/sv/messages.json +++ b/src/_locales/sv/messages.json @@ -24,7 +24,7 @@ "description":"appears as tab name in dashboard" }, "rulesPageName":{ - "message":"My rules", + "message":"Mina regler", "description":"appears as tab name in dashboard" }, "whitelistPageName":{ @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Network request log", + "message":"µBlock - Nätverks log", "description":"Title for the network request log window" }, "aboutPageName":{ @@ -72,103 +72,103 @@ "description":"English: Go to request log" }, "popupSiteInlineScriptEnabled":{ - "message":"Inline script<\/code> tags are allowed<\/b> on this site", + "message":"Inline skript<\/code>-taggar är tillåtna på<\/b> denna sida", "description":"" }, "popupSiteInlineScriptDisabled":{ - "message":"Inline script<\/code> tags are blocked<\/b> on this site", + "message":"Inline skript<\/code>-taggar är blockerade<\/b> på denna sida", "description":"" }, "popupSite1pScriptEnabled":{ - "message":"1st-party scripts are allowed<\/b> on this site", + "message":"förstapartsskript är tillåtna<\/b> på denna webbplats", "description":"" }, "popupSite1pScriptDisabled":{ - "message":"1st-party scripts are blocked<\/b> on this site", + "message":"förstapartsskript är blockerde<\/b> på denna webbplats", "description":"" }, "popupSite3pScriptEnabled":{ - "message":"3rd-party scripts are allowed<\/b> on this site", + "message":"tredjepartsskript är tillåtna<\/b> på denna webbplats", "description":"" }, "popupSite3pScriptDisabled":{ - "message":"3rd-party scripts are blocked<\/b> on this site", + "message":"tredjepartsskript är blockerade<\/b> på denna webbplats", "description":"" }, "popupSite1pFrameEnabled":{ - "message":"1st-party frames are allowed<\/b> on this site", + "message":"förstapartsramar är tillåtna<\/b> på denna webbplats", "description":"" }, "popupSite1pFrameDisabled":{ - "message":"1st-party frames are blocked<\/b> on this site", + "message":"förstapartsramar är blockerade<\/b> på denna webbplats", "description":"" }, "popupSite3pFrameEnabled":{ - "message":"3rd-party frames are allowed<\/b> on this site", + "message":"tredjepartsramar är tillåtna<\/b> på denna webbplats", "description":"" }, "popupSite3pFrameDisabled":{ - "message":"3rd-party frames are blocked<\/b> on this site", + "message":"tredjepartsramar är blockerade<\/b> på denna webbplats", "description":"" }, "popupDefaultInlineScriptEnabled":{ - "message":"Inline script<\/code> tags are allowed<\/b> everywhere by default", + "message":"Inline skripttaggarna<\/code> är tillåtna<\/b> överallt som standard", "description":"" }, "popupDefaultInlineScriptDisabled":{ - "message":"Inline script<\/code> tags are blocked<\/b> everywhere by default", + "message":"Inline skripttaggarna<\/code> är blockerade<\/b> överallt som standard", "description":"" }, "popupDefault1pScriptEnabled":{ - "message":"1st-party scripts are allowed<\/b> everywhere by default", + "message":"förstapartsskript är tillåtna<\/b> överallt som standard", "description":"" }, "popupDefault1pScriptDisabled":{ - "message":"1st-party scripts are blocked<\/b> everywhere by default", + "message":"förstapartsskript är blockerade<\/b> överallt som standard", "description":"" }, "popupDefault3pScriptEnabled":{ - "message":"3rd-party scripts are allowed<\/b> everywhere by default", + "message":"tredjepartsskript är tillåtna<\/b> överallt som standard", "description":"" }, "popupDefault3pScriptDisabled":{ - "message":"3rd-party scripts are blocked<\/b> everywhere by default", + "message":"tredjepartsskript är blockerade<\/b> överallt som standard", "description":"" }, "popupDefault1pFrameEnabled":{ - "message":"1st-party frames are allowed<\/b> everywhere by default", + "message":"förstapartsramar är tillåtna<\/b> överallt som standard", "description":"" }, "popupDefault1pFrameDisabled":{ - "message":"1st-party frames are blocked<\/b> everywhere by default", + "message":"förstapartsramar är blockerade<\/b> överallt som standard", "description":"" }, "popupDefault3pFrameEnabled":{ - "message":"3rd-party frames are allowed<\/b> everywhere by default", + "message":"tredjepartsramar är tillåtna<\/b> överallt som standard", "description":"" }, "popupDefault3pFrameDisabled":{ - "message":"3rd-party frames are blocked<\/b> everywhere by default", + "message":"tredjepartsramar är blockerade<\/b> överallt som standard", "description":"" }, "popupImageRulePrompt":{ - "message":"images", + "message":"bilder", "description":"" }, "popupInlineScriptRulePrompt":{ - "message":"inline scripts", + "message":"inline skript", "description":"" }, "popup1pScriptRulePrompt":{ - "message":"1st-party scripts", + "message":"förstaparstpartsskripts", "description":"" }, "popup3pScriptRulePrompt":{ - "message":"3rd-party scripts", + "message":"tredjepartsskript", "description":"" }, "popup3pFrameRulePrompt":{ - "message":"3rd-party frames", + "message":"tredjepartsramar", "description":"" }, "popupHitDomainCountPrompt":{ @@ -216,7 +216,7 @@ "description":"English: Make use of context menu where appropriate" }, "settingsAdvancedUserPrompt":{ - "message":"I am an advanced user (Required reading<\/a>)", + "message":"Jag är en avancerad användare ( obligatorisk läsning<\/a>)", "description":"English: " }, "settingsExperimentalPrompt":{ @@ -328,23 +328,23 @@ "description":"English: Apply changes" }, "rulesEdit":{ - "message":"Edit", + "message":"Redigera", "description":"Will enable manual-edit mode (textarea)" }, "rulesEditSave":{ - "message":"Save", + "message":"Spara", "description":"Will save manually-edited content and exit manual-edit mode" }, "rulesEditDiscard":{ - "message":"Discard", + "message":"Kasta", "description":"Will discard manually-edited content and exit manual-edit mode" }, "rulesImport":{ - "message":"Import from file...", + "message":"Importera från fil...", "description":"" }, "rulesExport":{ - "message":"Export to file...", + "message":"Exportera till fil...", "description":"" }, "rulesDefaultFileName":{ @@ -352,7 +352,7 @@ "description":"default file name to use" }, "rulesHint":{ - "message":"List of your dynamic filtering rules.", + "message":"Lista över din dynamiska filterregler.", "description":"English: List of your dynamic filtering rules." }, "rulesFormatHint":{ @@ -372,7 +372,7 @@ "description":"English: Export" }, "whitelistExportFilename":{ - "message":"my-ublock-whitelist_{{datetime}}.txt", + "message":"min-ublock-vitlista_{{datetime}}.txt", "description":"English: my-ublock-whitelist_{{datetime}}.txt" }, "whitelistApply":{ @@ -420,7 +420,7 @@ "description":"English: No non-blocked requests logged for this page" }, "logBehindTheScene":{ - "message":"Behind the scene", + "message":"Under huven", "description":"Pretty name for behind-the-scene network requests" }, "aboutChangelog":{ @@ -460,7 +460,7 @@ "description":"Message asking user to confirm restore" }, "aboutRestoreDataError":{ - "message":"The data could not be read or is invalid", + "message":"Datan gick inte att läsa eller är ogiltig", "description":"Message to display when an error occurred during restore" }, "aboutResetDataConfirm":{ diff --git a/src/_locales/uk/messages.json b/src/_locales/uk/messages.json index b7c765301..1a74acb57 100644 --- a/src/_locales/uk/messages.json +++ b/src/_locales/uk/messages.json @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Network request log", + "message":"µBlock — Журнал мережевих запитів", "description":"Title for the network request log window" }, "aboutPageName":{ @@ -352,11 +352,11 @@ "description":"default file name to use" }, "rulesHint":{ - "message":"List of your dynamic filtering rules.", + "message":"Список правил динамічного фільтрування.", "description":"English: List of your dynamic filtering rules." }, "rulesFormatHint":{ - "message":"Rule syntax: source destination type action<\/code> (full documentation<\/a>).", + "message":"Синтаксис правил: джерело призначення тип дія<\/code> (повна документація<\/a>).", "description":"English: dynamic rule syntax and full documentation." }, "whitelistPrompt":{ @@ -420,7 +420,7 @@ "description":"English: No non-blocked requests logged for this page" }, "logBehindTheScene":{ - "message":"Behind the scene", + "message":"За лаштунками", "description":"Pretty name for behind-the-scene network requests" }, "aboutChangelog":{ diff --git a/src/_locales/zh_CN/messages.json b/src/_locales/zh_CN/messages.json index b33f966a2..456d9aee9 100644 --- a/src/_locales/zh_CN/messages.json +++ b/src/_locales/zh_CN/messages.json @@ -4,7 +4,7 @@ "description":"extension name." }, "extShortDesc":{ - "message":"一款基于Chromium浏览器的高效广告拦截工具,超低的CPU与内存使用。", + "message":"高效的广告拦截工具,超低的CPU与内存使用。", "description":"this will be in the chrome web store: must be 132 characters or less" }, "dashboardName":{ @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Network request log", + "message":"µBlock 网络请求日志", "description":"Title for the network request log window" }, "aboutPageName":{ @@ -352,11 +352,11 @@ "description":"default file name to use" }, "rulesHint":{ - "message":"List of your dynamic filtering rules.", + "message":"动态过滤规则列表。", "description":"English: List of your dynamic filtering rules." }, "rulesFormatHint":{ - "message":"Rule syntax: source destination type action<\/code> (full documentation<\/a>).", + "message":"规则语法: 示范操作描述<\/code> ( 完整的文档<\/a>)。", "description":"English: dynamic rule syntax and full documentation." }, "whitelistPrompt":{ @@ -420,7 +420,7 @@ "description":"English: No non-blocked requests logged for this page" }, "logBehindTheScene":{ - "message":"Behind the scene", + "message":"后台", "description":"Pretty name for behind-the-scene network requests" }, "aboutChangelog":{ diff --git a/src/_locales/zh_TW/messages.json b/src/_locales/zh_TW/messages.json index 5040c62c0..4b032f338 100644 --- a/src/_locales/zh_TW/messages.json +++ b/src/_locales/zh_TW/messages.json @@ -24,7 +24,7 @@ "description":"appears as tab name in dashboard" }, "rulesPageName":{ - "message":"My rules", + "message":"自訂規則", "description":"appears as tab name in dashboard" }, "whitelistPageName":{ @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Network request log", + "message":"µBlock — 網路請求日誌", "description":"Title for the network request log window" }, "aboutPageName":{ @@ -152,23 +152,23 @@ "description":"" }, "popupImageRulePrompt":{ - "message":"images", + "message":"圖片", "description":"" }, "popupInlineScriptRulePrompt":{ - "message":"inline scripts", + "message":"行內的腳本", "description":"" }, "popup1pScriptRulePrompt":{ - "message":"1st-party scripts", + "message":"第一方腳本", "description":"" }, "popup3pScriptRulePrompt":{ - "message":"3rd-party scripts", + "message":"協力廠商腳本", "description":"" }, "popup3pFrameRulePrompt":{ - "message":"3rd-party frames", + "message":"協力廠商框架", "description":"" }, "popupHitDomainCountPrompt":{ @@ -328,27 +328,27 @@ "description":"English: Apply changes" }, "rulesEdit":{ - "message":"Edit", + "message":"編輯", "description":"Will enable manual-edit mode (textarea)" }, "rulesEditSave":{ - "message":"Save", + "message":"儲存", "description":"Will save manually-edited content and exit manual-edit mode" }, "rulesEditDiscard":{ - "message":"Discard", + "message":"捨棄", "description":"Will discard manually-edited content and exit manual-edit mode" }, "rulesImport":{ - "message":"Import from file...", + "message":"從檔案匯入...", "description":"" }, "rulesExport":{ - "message":"Export to file...", + "message":"匯出至檔案...", "description":"" }, "rulesDefaultFileName":{ - "message":"my-ublock-dynamic-rules_{{datetime}}.txt", + "message":"ublock自訂動態規則_{{datetime}}.txt", "description":"default file name to use" }, "rulesHint":{ diff --git a/src/css/devtool-log.css b/src/css/devtool-log.css index 3011fbd19..36557925b 100644 --- a/src/css/devtool-log.css +++ b/src/css/devtool-log.css @@ -61,27 +61,31 @@ body[dir="rtl"] #content { vertical-align: top; } #content table tr td:nth-of-type(1) { + padding: 3px 0; + text-align: center; + } +#content table tr td:nth-of-type(2) { white-space: normal; width: 25%; word-break: break-all; word-wrap: break-word; } -#content table tr td:nth-of-type(2) { +#content table tr td:nth-of-type(3) { white-space: nowrap; } -#content table tr td:nth-of-type(3) { +#content table tr td:nth-of-type(4) { border-right: none; white-space: normal; width: 60%; word-break: break-all; word-wrap: break-word; } -#content table tr td:nth-of-type(3) b { +#content table tr td:nth-of-type(4) b { font-weight: normal; } -#content table tr.blocked td:nth-of-type(3) b { +#content table tr.blocked td:nth-of-type(4) b { background-color: rgba(192, 0, 0, 0.2); } -#content table tr.allowed td:nth-of-type(3) b { +#content table tr.allowed td:nth-of-type(4) b { background-color: rgba(0, 160, 0, 0.2); } \ No newline at end of file diff --git a/src/js/background.js b/src/js/background.js index b47fe0af0..00d0d12ff 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -108,7 +108,7 @@ return { firstUpdateAfter: 5 * oneMinute, nextUpdateAfter: 7 * oneHour, - selfieMagic: 'qidcglrwobsm', + selfieMagic: 'knreayqtuguf', selfieAfter: 7 * oneMinute, pageStores: {}, diff --git a/src/js/contentscript-end.js b/src/js/contentscript-end.js index b6bbbf0a6..82ce59fc7 100644 --- a/src/js/contentscript-end.js +++ b/src/js/contentscript-end.js @@ -33,20 +33,30 @@ // https://github.com/gorhill/uBlock/issues/464 if ( document instanceof HTMLDocument === false ) { + //console.debug('contentscript-end.js > not a HTLMDocument'); return false; } if ( !vAPI ) { + //console.debug('contentscript-end.js > vAPI not found'); return; } if ( vAPI.canExecuteContentScript() !== true ) { + //console.debug('contentscript-end.js > can\'t execute'); + return; +} + +// https://github.com/gorhill/uBlock/issues/587 +// Pointless to execute without the start script having done its job. +if ( !vAPI.contentscriptStartInjected ) { return; } // https://github.com/gorhill/uBlock/issues/456 // Already injected? if ( vAPI.contentscriptEndInjected ) { + //console.debug('contentscript-end.js > content script already injected'); return; } vAPI.contentscriptEndInjected = true; diff --git a/src/js/contentscript-start.js b/src/js/contentscript-start.js index ab95b3427..1e9e4d3ef 100644 --- a/src/js/contentscript-start.js +++ b/src/js/contentscript-start.js @@ -36,22 +36,26 @@ // https://github.com/gorhill/uBlock/issues/464 if ( document instanceof HTMLDocument === false ) { + //console.debug('contentscript-start.js > not a HTLMDocument'); return false; } // Because in case if ( !vAPI ) { + //console.debug('contentscript-start.js > vAPI not found'); return; } // Because Safari if ( vAPI.canExecuteContentScript() !== true ) { + //console.debug('contentscript-start.js > can\'t execute'); return; } // https://github.com/gorhill/uBlock/issues/456 // Already injected? if ( vAPI.contentscriptStartInjected ) { + //console.debug('contentscript-start.js > content script already injected'); return; } vAPI.contentscriptStartInjected = true; @@ -139,7 +143,14 @@ var filteringHandler = function(details) { // The port will never be used again at this point, disconnecting allows // the browser to flush this script from memory. } - // Do not close the port before we are done. + + // https://github.com/gorhill/uBlock/issues/587 + // If no filters were found, maybe the script was injected before uBlock's + // process was fully initialized. When this happens, pages won't be + // cleaned right after browser launch. + vAPI.contentscriptStartInjected = details && details.ready; + + // Cleanup before leaving localMessager.close(); }; diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js index e8452f249..e24d58c05 100644 --- a/src/js/cosmetic-filtering.js +++ b/src/js/cosmetic-filtering.js @@ -933,7 +933,6 @@ FilterContainer.prototype.fromSelfie = function(selfie) { return dict; }; - this.frozen = true; this.acceptedCount = selfie.acceptedCount; this.duplicateCount = selfie.duplicateCount; this.hostnameFilters = dictFromSelfie(selfie.hostnameSpecificFilters); @@ -951,6 +950,7 @@ FilterContainer.prototype.fromSelfie = function(selfie) { this.highHighGenericDonthide = selfie.highHighGenericDonthide; this.highHighGenericHideCount = selfie.highHighGenericHideCount; this.highHighGenericDonthideCount = selfie.highHighGenericDonthideCount; + this.frozen = true; }; /******************************************************************************/ @@ -1127,7 +1127,12 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) { var domain = µb.URI.domainFromHostname(hostname) || hostname; var pos = domain.indexOf('.'); + // https://github.com/gorhill/uBlock/issues/587 + // r.ready will tell the content script the cosmetic filtering engine is + // up and ready. + var r = { + ready: this.frozen, domain: domain, entity: pos === -1 ? domain : domain.slice(0, pos - domain.length), skipCosmeticFiltering: this.acceptedCount === 0, diff --git a/src/js/devtool-log.js b/src/js/devtool-log.js index 5646b8ab1..f2a8e67b2 100644 --- a/src/js/devtool-log.js +++ b/src/js/devtool-log.js @@ -51,6 +51,8 @@ var renderURL = function(url, filter) { } if ( reText === '*' ) { reText = '\\*'; + } else if ( reText.charAt(0) === '/' && reText.slice(-1) === '/' ) { + reText = reText.slice(1, -1); } else { reText = reText .replace(/\./g, '\\.') @@ -87,6 +89,7 @@ var createRow = function() { tr.appendChild(doc.createElement('td')); tr.appendChild(doc.createElement('td')); tr.appendChild(doc.createElement('td')); + tr.appendChild(doc.createElement('td')); return tr; }; @@ -96,18 +99,26 @@ var renderLogEntry = function(entry) { var tr = createRow(); if ( entry.result.charAt(1) === 'b' ) { tr.classList.add('blocked'); + tr.cells[0].textContent = '\u2009\u2212\u2009'; } else if ( entry.result.charAt(1) === 'a' ) { tr.classList.add('allowed'); if ( entry.result.charAt(0) === 'm' ) { tr.classList.add('mirrored'); } + tr.cells[0].textContent = '\u2009+\u2009'; + } else { + tr.cells[0].textContent = '\u2009\u00A0\u2009'; } if ( entry.type === 'main_frame' ) { tr.classList.add('maindoc'); } - tr.cells[0].textContent = entry.result.slice(3); - tr.cells[1].textContent = entry.type; - vAPI.insertHTML(tr.cells[2], renderURL(entry.url, entry.result)); + var filterText = entry.result.slice(3); + if ( entry.result.lastIndexOf('sa', 0) === 0 ) { + filterText = '@@' + filterText; + } + tr.cells[1].textContent = filterText; + tr.cells[2].textContent = entry.type; + vAPI.insertHTML(tr.cells[3], renderURL(entry.url, entry.result)); tbody.insertBefore(tr, tbody.firstChild); }; diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index 3e106a94a..93a2b0719 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -80,8 +80,6 @@ const AllowAnyParty = AllowAction | AnyParty; var pageHostname = ''; // short-lived register -var reIgnoreEmpty = /^\s+$/; -var reIgnoreComment = /^\[|^!/; var reHostnameRule = /^[0-9a-z][0-9a-z.-]+[0-9a-z]$/; var reHostnameToken = /^[0-9a-z]+/g; var reGoodToken = /[%0-9a-z]{2,}/g; @@ -814,6 +812,61 @@ FilterManyWildcardsHostname.fromSelfie = function(s) { return new FilterManyWildcardsHostname(args[0], atoi(args[1]), args[2]); }; +/******************************************************************************/ + +// Regex-based filters + +var FilterRegex = function(s) { + this.re = new RegExp(s); +}; + +FilterRegex.prototype.match = function(url) { + return this.re.test(url); +}; + +FilterRegex.prototype.fid = '//'; + +FilterRegex.prototype.toString = function() { + return '/' + this.re.source + '/'; +}; + +FilterRegex.prototype.toSelfie = function() { + return this.re.source; +}; + +FilterRegex.fromSelfie = function(s) { + return new FilterRegex(s); +}; + +/******************************************************************************/ + +var FilterRegexHostname = function(s, hostname) { + this.re = new RegExp(s); + this.hostname = hostname; +}; + +FilterRegexHostname.prototype.match = function(url) { + // test hostname first, it's cheaper than evaluating a regex + return pageHostname.slice(-this.hostname.length) === this.hostname && + this.re.test(url); +}; + +FilterRegexHostname.prototype.fid = '//h'; + +FilterRegexHostname.prototype.toString = function() { + return '/' + this.re.source + '/$domain=' + this.hostname; +}; + +FilterRegexHostname.prototype.toSelfie = function() { + return this.re.source + '\t' + + this.hostname; +}; + +FilterRegexHostname.fromSelfie = function(s) { + var pos = s.indexOf('\t'); + return new FilterRegexHostname(s.slice(0, pos), s.slice(pos + 1)); +}; + /******************************************************************************/ /******************************************************************************/ @@ -921,12 +974,15 @@ FilterBucket.fromSelfie = function() { /******************************************************************************/ -var makeFilter = function(details, tokenBeg) { +var makeFilter = function(details) { var s = details.f; + if ( details.isRegex ) { + return new FilterRegex(s); + } var wcOffset = s.indexOf('*'); if ( wcOffset !== -1 ) { if ( s.indexOf('*', wcOffset + 1) !== -1 ) { - return details.anchor === 0 ? new FilterManyWildcards(s, tokenBeg) : null; + return details.anchor === 0 ? new FilterManyWildcards(s, details.tokenBeg) : null; } var lSegment = s.slice(0, wcOffset); var rSegment = s.slice(wcOffset + 1); @@ -936,10 +992,10 @@ var makeFilter = function(details, tokenBeg) { if ( details.anchor > 0 ) { return new FilterSingleWildcardRightAnchored(lSegment, rSegment); } - if ( tokenBeg === 0 ) { + if ( details.tokenBeg === 0 ) { return new FilterSingleWildcardPrefix0(lSegment, rSegment); } - return new FilterSingleWildcard(lSegment, rSegment, tokenBeg); + return new FilterSingleWildcard(lSegment, rSegment, details.tokenBeg); } if ( details.anchor < 0 ) { return new FilterPlainLeftAnchored(s); @@ -950,23 +1006,26 @@ var makeFilter = function(details, tokenBeg) { if ( details.hostnameAnchored ) { return new FilterPlainHnAnchored(s); } - if ( tokenBeg === 0 ) { + if ( details.tokenBeg === 0 ) { return new FilterPlainPrefix0(s); } - if ( tokenBeg === 1 ) { + if ( details.tokenBeg === 1 ) { return new FilterPlainPrefix1(s); } - return new FilterPlain(s, tokenBeg); + return new FilterPlain(s, details.tokenBeg); }; /******************************************************************************/ -var makeHostnameFilter = function(details, tokenBeg, hostname) { +var makeHostnameFilter = function(details, hostname) { var s = details.f; + if ( details.isRegex ) { + return new FilterRegexHostname(s, hostname); + } var wcOffset = s.indexOf('*'); if ( wcOffset !== -1 ) { if ( s.indexOf('*', wcOffset + 1) !== -1 ) { - return details.anchor === 0 ? new FilterManyWildcardsHostname(s, tokenBeg, hostname) : null; + return details.anchor === 0 ? new FilterManyWildcardsHostname(s, details.tokenBeg, hostname) : null; } var lSegment = s.slice(0, wcOffset); var rSegment = s.slice(wcOffset + 1); @@ -976,10 +1035,10 @@ var makeHostnameFilter = function(details, tokenBeg, hostname) { if ( details.anchor > 0 ) { return new FilterSingleWildcardRightAnchoredHostname(lSegment, rSegment, hostname); } - if ( tokenBeg === 0 ) { + if ( details.tokenBeg === 0 ) { return new FilterSingleWildcardPrefix0Hostname(lSegment, rSegment, hostname); } - return new FilterSingleWildcardHostname(lSegment, rSegment, tokenBeg, hostname); + return new FilterSingleWildcardHostname(lSegment, rSegment, details.tokenBeg, hostname); } if ( details.anchor < 0 ) { return new FilterPlainLeftAnchoredHostname(s, hostname); @@ -987,13 +1046,13 @@ var makeHostnameFilter = function(details, tokenBeg, hostname) { if ( details.anchor > 0 ) { return new FilterPlainRightAnchoredHostname(s, hostname); } - if ( tokenBeg === 0 ) { + if ( details.tokenBeg === 0 ) { return new FilterPlainPrefix0Hostname(s, hostname); } - if ( tokenBeg === 1 ) { + if ( details.tokenBeg === 1 ) { return new FilterPlainPrefix1Hostname(s, hostname); } - return new FilterPlainHostname(s, tokenBeg, hostname); + return new FilterPlainHostname(s, details.tokenBeg, hostname); }; /******************************************************************************/ @@ -1061,7 +1120,10 @@ var trimChar = function(s, c) { /******************************************************************************/ var FilterParser = function() { + this.reHasWildcard = /[\^\*]/; + this.reHasUppercase = /[A-Z]/; this.hostnames = []; + this.notHostnames = []; this.types = []; this.reset(); }; @@ -1093,8 +1155,12 @@ FilterParser.prototype.reset = function() { this.hostnameAnchored = false; this.hostnamePure = false; this.hostnames.length = 0; - this.notHostname = false; + this.notHostnames.length = 0; + this.isRegex = false; this.thirdParty = false; + this.token = ''; + this.tokenBeg = 0; + this.tokenEnd = 0; this.types.length = 0; this.important = 0; this.unsupported = false; @@ -1141,101 +1207,22 @@ FilterParser.prototype.parseOptParty = function(not) { FilterParser.prototype.parseOptHostnames = function(raw) { var hostnames = raw.split('|'); - var hostname, not; + var hostname; for ( var i = 0; i < hostnames.length; i++ ) { hostname = hostnames[i]; - not = hostname.charAt(0) === '~'; - if ( not ) { - hostname = hostname.slice(1); + if ( hostname.charAt(0) === '~' ) { + this.notHostnames.push(hostname.slice(1)); + } else { + this.hostnames.push(hostname); } - // https://github.com/gorhill/uBlock/issues/191 - // Well it doesn't seem to make a whole lot of sense to have both - // non-negated hostnames mixed with negated hostnames. - if ( this.hostnames.length !== 0 && not !== this.notHostname ) { - console.error('FilterContainer.parseOptHostnames(): ambiguous filter syntax: "%s"', this.f); - this.unsupported = true; - return; - } - this.notHostname = not; - this.hostnames.push(hostname); } }; /******************************************************************************/ -FilterParser.prototype.parse = function(s) { - // important! - this.reset(); - - if ( reHostnameRule.test(s) ) { - this.f = s; - this.hostnamePure = this.hostnameAnchored = true; - return this; - } - - // element hiding filter? - if ( s.indexOf('##') >= 0 || s.indexOf('#@') >= 0 ) { - this.elemHiding = true; - return this; - } - - // block or allow filter? - if ( s.slice(0, 2) === '@@' ) { - this.action = AllowAction; - s = s.slice(2); - } - - // options - var pos = s.indexOf('$'); - if ( pos > 0 ) { - this.fopts = s.slice(pos + 1); - s = s.slice(0, pos); - } - - // regex? (not supported) - if ( s.charAt(0) === '/' && s.slice(-1) === '/' ) { - this.unsupported = true; - return this; - } - - // hostname anchoring - if ( s.slice(0, 2) === '||' ) { - this.hostnameAnchored = true; - s = s.slice(2); - } - - // left-anchored - if ( s.charAt(0) === '|' ) { - this.anchor = -1; - s = s.slice(1); - } - - // right-anchored - if ( s.slice(-1) === '|' ) { - this.anchor = 1; - s = s.slice(0, -1); - } - - // normalize placeholders - // TODO: transforming `^` into `*` is not a strict interpretation of - // ABP syntax. - s = s.replace(/\^/g, '*'); - s = s.replace(/\*\*+/g, '*'); - - // remove leading and trailing wildcards - s = trimChar(s, '*'); - - // pure hostname-based? - this.hostnamePure = this.hostnameAnchored && reHostnameRule.test(s); - - this.f = s; - - if ( !this.fopts ) { - return this; - } - - // parse options - var opts = this.fopts.split(','); +FilterParser.prototype.parseOptions = function(s) { + this.fopts = s; + var opts = s.split(','); var opt, not; for ( var i = 0; i < opts.length; i++ ) { opt = opts[i]; @@ -1271,9 +1258,119 @@ FilterParser.prototype.parse = function(s) { this.unsupported = true; break; } +}; + +/******************************************************************************/ + +FilterParser.prototype.parse = function(s) { + // important! + this.reset(); + + // plain hostname? + if ( reHostnameRule.test(s) ) { + this.f = s; + this.hostnamePure = this.hostnameAnchored = true; + return this; + } + + // element hiding filter? + var pos = s.indexOf('#'); + if ( pos !== -1 ) { + var c = s.charAt(pos + 1); + if ( c === '#' || c === '@' ) { + console.error('static-net-filtering.js > unexpected cosmetic filters'); + this.elemHiding = true; + return this; + } + } + + // options + pos = s.indexOf('$'); + if ( pos !== -1 ) { + this.parseOptions(s.slice(pos + 1)); + s = s.slice(0, pos); + } + + // block or allow filter? + if ( s.lastIndexOf('@@', 0) === 0 ) { + this.action = AllowAction; + s = s.slice(2); + } + + // regex? + if ( s.charAt(0) === '/' && s.slice(-1) === '/' ) { + this.isRegex = true; + this.f = s.slice(1, -1); + return this; + } + + // hostname anchoring + if ( s.lastIndexOf('||', 0) === 0 ) { + this.hostnameAnchored = true; + s = s.slice(2); + } + + // left-anchored + if ( s.charAt(0) === '|' ) { + this.anchor = -1; + s = s.slice(1); + } + + // right-anchored + if ( s.slice(-1) === '|' ) { + this.anchor = 1; + s = s.slice(0, -1); + } + + // normalize placeholders + // TODO: transforming `^` into `*` is not a strict interpretation of + // ABP syntax. + if ( this.reHasWildcard.test(s) ) { + s = s.replace(/\^/g, '*').replace(/\*\*+/g, '*'); + s = trimChar(s, '*'); + } + + // plain hostname? + this.hostnamePure = this.hostnameAnchored && reHostnameRule.test(s); + + // This might look weird but we gain memory footprint by not going through + // toLowerCase(), at least on Chromium. Because copy-on-write? + + this.f = this.reHasUppercase.test(s) ? s.toLowerCase() : s; + return this; }; +/******************************************************************************/ + +FilterParser.prototype.makeToken = function() { + if ( this.isRegex ) { + this.token = '*'; + return; + } + + var matches; + + if ( this.hostnameAnchored ) { + matches = findHostnameToken(this.f); + if ( !matches || matches[0].length === 0 ) { + return; + } + this.tokenBeg = matches.index; + this.tokenEnd = reHostnameToken.lastIndex; + this.token = this.f.slice(this.tokenBeg, this.tokenEnd); + return; + } + + matches = findFirstGoodToken(this.f); + if ( !matches || matches[0].length === 0 ) { + return; + } + this.tokenBeg = matches.index; + this.tokenEnd = reGoodToken.lastIndex; + this.token = this.f.slice(this.tokenBeg, this.tokenEnd); +}; + /******************************************************************************/ /******************************************************************************/ @@ -1288,7 +1385,6 @@ var TokenEntry = function() { var FilterContainer = function() { this.reAnyToken = /[%0-9a-z]+/g; this.tokens = []; - this.buckets = new Array(4); this.blockedAnyPartyHostnames = new µb.LiquidDict(); this.blocked3rdPartyHostnames = new µb.LiquidDict(); this.filterParser = new FilterParser(); @@ -1411,7 +1507,9 @@ FilterContainer.prototype.fromSelfie = function(selfie) { '*|': FilterSingleWildcardRightAnchored, '*|h': FilterSingleWildcardRightAnchoredHostname, '*+': FilterManyWildcards, - '*+h': FilterManyWildcardsHostname + '*+h': FilterManyWildcardsHostname, + '//': FilterRegex, + '//h': FilterRegexHostname }; var catKey, tokenKey; @@ -1464,26 +1562,28 @@ FilterContainer.prototype.add = function(s) { // ORDER OF TESTS IS IMPORTANT! // Ignore empty lines - if ( reIgnoreEmpty.test(s) ) { + s = s.trim(); + if ( s.length === 0 ) { return false; } // Ignore comments - if ( reIgnoreComment.test(s) ) { + var c = s.charAt(0); + if ( c === '[' || c === '!' ) { return false; } var parsed = this.filterParser.parse(s); - // Ignore rules with other conditions for now - if ( parsed.unsupported ) { - this.rejectedCount += 1; - // console.log('µBlock> abp-filter.js/FilterContainer.add(): unsupported filter "%s"', s); + // Ignore element-hiding filters + if ( parsed.elemHiding ) { return false; } - // Ignore element-hiding filters - if ( parsed.elemHiding ) { + // Ignore filters with unsupported options + if ( parsed.unsupported ) { + this.rejectedCount += 1; + // console.log('µBlock> abp-filter.js/FilterContainer.add(): unsupported filter "%s"', s); return false; } @@ -1534,95 +1634,95 @@ FilterContainer.prototype.add = function(s) { /******************************************************************************/ FilterContainer.prototype.addFilter = function(parsed) { - // TODO: avoid duplicates - - var matches = parsed.hostnameAnchored ? - findHostnameToken(parsed.f) : - findFirstGoodToken(parsed.f); - if ( !matches || !matches[0].length ) { + parsed.makeToken(); + if ( parsed.token === '' ) { + console.error('static-net-filtering.js > FilterContainer.addFilter("%s"): can\'t tokenize', parsed.f); return false; } - var tokenBeg = matches.index; - var tokenEnd = parsed.hostnameAnchored ? - reHostnameToken.lastIndex : - reGoodToken.lastIndex; - var filter; - - var i = parsed.hostnames.length; - - // Applies to specific domains - - if ( i !== 0 && !parsed.notHostname ) { - while ( i-- ) { - filter = makeHostnameFilter(parsed, tokenBeg, parsed.hostnames[i]); - if ( !filter ) { - return false; - } - this.addFilterEntry(filter, parsed, AnyParty, tokenBeg, tokenEnd); - } - return true; - } var party = AnyParty; if ( parsed.firstParty !== parsed.thirdParty ) { party = parsed.firstParty ? FirstParty : ThirdParty; } - // Applies to all domains, with exception(s) + var filter; + var i = parsed.hostnames.length; + var j = parsed.notHostnames.length; - // https://github.com/gorhill/uBlock/issues/191 - // Invert the purpose of the filter for negated hostnames - if ( i !== 0 && parsed.notHostname ) { - filter = makeFilter(parsed, tokenBeg); + // Applies to all domains without exceptions + if ( i === 0 && j === 0 ) { + filter = makeFilter(parsed); + if ( !filter ) { + return false; + } + this.addFilterEntry(filter, parsed, party); + return true; + } + + // Applies to specific domains + if ( i !== 0 ) { + while ( i-- ) { + filter = makeHostnameFilter(parsed, parsed.hostnames[i]); + if ( !filter ) { + return false; + } + this.addFilterEntry(filter, parsed, party); + } + } + // No exceptions + if ( j === 0 ) { + return true; + } + + // Case: + // - applies everywhere except to specific domains + // Example: + // - ||adm.fwmrm.net/p/msnbc_live/$object-subrequest,third-party,domain=~msnbc.msn.com|~www.nbcnews.com + if ( i === 0 ) { + filter = makeFilter(parsed); if ( !filter ) { return false; } // https://github.com/gorhill/uBlock/issues/251 // Apply third-party option if it is present - this.addFilterEntry(filter, parsed, party, tokenBeg, tokenEnd); - // Reverse purpose of filter - parsed.action ^= ToggleAction; - while ( i-- ) { - filter = makeHostnameFilter(parsed, tokenBeg, parsed.hostnames[i]); - if ( !filter ) { - return false; - } - // https://github.com/gorhill/uBlock/issues/191#issuecomment-53654024 - // If it is a block filter, we need to reverse the order of - // evaluation. - if ( parsed.action === BlockAction ) { - parsed.important = Important; - } - this.addFilterEntry(filter, parsed, AnyParty, tokenBeg, tokenEnd); + this.addFilterEntry(filter, parsed, party); + } + + // Cases: + // - applies everywhere except to specific domains + // - applies to specific domains except other specific domains + // Example: + // - /^https?\:\/\/(?!(...)\/)/$script,third-party,xmlhttprequest,domain=photobucket.com|~secure.photobucket.com + + // Reverse purpose of filter + parsed.action ^= ToggleAction; + while ( j-- ) { + filter = makeHostnameFilter(parsed, parsed.notHostnames[j]); + if ( !filter ) { + return false; } - return true; + // https://github.com/gorhill/uBlock/issues/191#issuecomment-53654024 + // If it is a block filter, we need to reverse the order of + // evaluation. + if ( parsed.action === BlockAction ) { + parsed.important = Important; + } + this.addFilterEntry(filter, parsed, party); } - - // Applies to all domains without exceptions - - filter = makeFilter(parsed, tokenBeg); - if ( !filter ) { - return false; - } - - this.addFilterEntry(filter, parsed, party, tokenBeg, tokenEnd); - return true; }; /******************************************************************************/ -FilterContainer.prototype.addFilterEntry = function(filter, parsed, party, tokenBeg, tokenEnd) { - var s = parsed.f; - var tokenKey = s.slice(tokenBeg, tokenEnd); +FilterContainer.prototype.addFilterEntry = function(filter, parsed, party) { var bits = parsed.action | parsed.important | party; if ( parsed.types.length === 0 ) { - this.addToCategory(bits | AnyType, tokenKey, filter); + this.addToCategory(bits | AnyType, parsed.token, filter); return; } var n = parsed.types.length; for ( var i = 0; i < n; i++ ) { - this.addToCategory(bits | parsed.types[i], tokenKey, filter); + this.addToCategory(bits | parsed.types[i], parsed.token, filter); } }; @@ -1692,6 +1792,13 @@ FilterContainer.prototype.matchTokens = function(bucket, url) { return f; } } + + // Regex-based filters + f = bucket['*']; + if ( f !== undefined && f.match(url) !== false ) { + return f; + } + return false; }; @@ -1756,10 +1863,10 @@ FilterContainer.prototype.matchStringExactType = function(context, requestURL, r pageHostname = context.pageHostname || ''; // Be prepared to support unknown types - var bf = false; - var bucket; - var categories = this.categories; var type = typeNameToTypeValue[requestType] || typeOtherToTypeValue; + var categories = this.categories; + var bf = false, bucket; +>>>>>>> f718e8e1f239690eae7ff964e1e2c3535c781043 // Tokenize only once this.tokenize(url); @@ -1855,8 +1962,8 @@ FilterContainer.prototype.matchString = function(context) { // This will be used by hostname-based filters pageHostname = context.pageHostname || ''; - var bf, bucket; var categories = this.categories; + var bf, bucket; // Tokenize only once this.tokenize(url); diff --git a/src/js/storage.js b/src/js/storage.js index 2bb032f11..2a4d77c29 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -370,12 +370,15 @@ var cosmeticFilteringEngine = this.cosmeticFilteringEngine; var parseCosmeticFilters = this.userSettings.parseAllABPHideFilters; - var reIsCosmeticFilter = /#@?#/; - var reLocalhost = /(?:^|\s)(?:localhost\.localdomain|localhost|local|broadcasthost|0\.0\.0\.0|127\.0\.0\.1|::1|fe80::1%lo0)(?=\s|$)/g; - var reAsciiSegment = /^[\x21-\x7e]+$/; + var reIsCosmeticFilter = /#[@#]/; + var reIsWhitespaceChar = /\s/; + var reMaybeLocalIp = /^[\d:f]/; + var reIsLocalhostRedirect = /\s+(?:broadcasthost|local|localhost|localhost\.localdomain)(?=\s|$)/; + var reLocalIp = /^(?:0\.0\.0\.0|127\.0\.0\.1|::1|fe80::1%lo0)/; + //var reAsciiSegment = /^[\x21-\x7e]+$/; var matches; var lineBeg = 0, lineEnd, currentLineBeg; - var line, c; + var line, lineRaw, c, pos; while ( lineBeg < rawEnd ) { lineEnd = rawText.indexOf('\n', lineBeg); @@ -389,10 +392,14 @@ // rhill 2014-04-18: The trim is important here, as without it there // could be a lingering `\r` which would cause problems in the // following parsing code. - line = rawText.slice(lineBeg, lineEnd).trim(); + line = lineRaw = rawText.slice(lineBeg, lineEnd).trim(); currentLineBeg = lineBeg; lineBeg = lineEnd + 1; + if ( line.length === 0 ) { + continue; + } + // Strip comments c = line.charAt(0); if ( c === '!' || c === '[' ) { @@ -400,6 +407,7 @@ } // Parse or skip cosmetic filters + // All cosmetic filters are caught here if ( parseCosmeticFilters ) { if ( cosmeticFilteringEngine.add(line) ) { continue; @@ -408,36 +416,59 @@ continue; } + // Whatever else is next can be assumed to not be a cosmetic filter + + // Most comments start in first column if ( c === '#' ) { continue; } + // Catch comments somewhere on the line + // Remove: + // ... #blah blah blah + // ... # blah blah blah + // Don't remove: + // ...#blah blah blah + // because some ABP filters uses the `#` character (URL fragment) + pos = line.indexOf('#'); + if ( pos !== -1 && reIsWhitespaceChar.test(line.charAt(pos - 1)) ) { + line = line.slice(0, pos).trim(); + } + // https://github.com/gorhill/httpswitchboard/issues/15 // Ensure localhost et al. don't end up in the ubiquitous blacklist. - // TODO: do this only if it's not an [Adblock] list - line = line - .replace(/\s+#.*$/, '') - .toLowerCase() - .replace(reLocalhost, '') - .trim(); + // With hosts files, we need to remove local IP redirection + if ( reMaybeLocalIp.test(c) ) { + // Ignore hosts file redirect configuration + // 127.0.0.1 localhost + // 255.255.255.255 broadcasthost + if ( reIsLocalhostRedirect.test(line) ) { + continue; + } + line = line.replace(reLocalIp, '').trim(); + } + + if ( line.length === 0 ) { + continue; + } // The filter is whatever sequence of printable ascii character without // whitespaces - matches = reAsciiSegment.exec(line); - if ( matches === null ) { - //console.debug('µBlock.mergeFilterList(): skipping "%s"', lineRaw); - continue; - } + //matches = reAsciiSegment.exec(line); + //if ( matches === null ) { + // console.debug('storage.js > µBlock.mergeFilterList(): skipping "%s"', lineRaw); + // continue; + //} // Bypass anomalies // For example, when a filter contains whitespace characters, or // whatever else outside the range of printable ascii characters. - if ( matches[0] !== line ) { - // console.error('"%s" !== "%s"', matches[0], line); - continue; - } + //if ( matches[0] !== line ) { + // console.error('"%s" !== "%s"', matches[0], line); + // continue; + //} - staticNetFilteringEngine.add(matches[0]); + staticNetFilteringEngine.add(line); } }; @@ -600,11 +631,11 @@ // for launch time. µb.assets.allowRemoteFetch = true; - vAPI.onLoadAllCompleted(); - // https://github.com/gorhill/uBlock/issues/184 // Check for updates not too far in the future. µb.updater.restart(µb.firstUpdateAfter); + + vAPI.onLoadAllCompleted(); }; // To bring older versions up to date