diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2015-10-17 18:10:23 +0200 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2015-10-17 18:10:23 +0200 |
commit | ea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7 (patch) | |
tree | f5f542e168df6b8da261ee0d95476a254fff9139 /src | |
parent | 2a260e13033aa80f474f3c7ca2f7f4ca4aec2f54 (diff) | |
parent | 230639d959468fc67c7ca5cf0249009eee0853b8 (diff) | |
download | uBlock-ea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7.zip uBlock-ea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7.tar.gz uBlock-ea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7.tar.bz2 |
Merge branch 'upstream'
Diffstat (limited to 'src')
41 files changed, 403 insertions, 164 deletions
diff --git a/src/1p-filters.html b/src/1p-filters.html index 0c5d01c..37e8161 100644 --- a/src/1p-filters.html +++ b/src/1p-filters.html @@ -13,7 +13,7 @@ <div id="cloudWidget" class="hide" data-cloud-entry="myFiltersPane"></div> -<p data-i18n="1pFormatHint"></p> +<p><span data-i18n="1pFormatHint"></span> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Static-filter-syntax" target="_blank"></a></p> <p> <button id="userFiltersApply" class="custom important" type="button" disabled="true" data-i18n="1pApplyChanges"></button>  <button id="userFiltersRevert" class="custom" type="button" disabled="true" data-i18n="genericRevert"></button> diff --git a/src/_locales/ar/messages.json b/src/_locales/ar/messages.json index 1d9dba5..69462dd 100644 --- a/src/_locales/ar/messages.json +++ b/src/_locales/ar/messages.json @@ -236,7 +236,7 @@ "description":"English: Parse and enforce Adblock+ element hiding filters." }, "3pParseAllABPHideFiltersInfo":{ - "message":"هذا الخيار يفعل تحليل وتطبيق فلاتر <a href=\"https:\/\/adblockplus.org\/en\/faq_internal#elemhide\">Adblock Plus-compatible “element hiding” filters<\/a> هذي الفلاتر مخصصه للتجميل الصفحه. هذي الفلاتر تخفي بعض صناديق او اعلانات المزعجه التي لا يمنعها محرك الفلاتر تفعيل هذي الخاصيه سوف يجعل الاضافه تستعمل الذاكره اكثر", + "message":"<p>هذا الخيار يمكّن من تحليل و تفعيل <a href=\"https:\/\/adblockplus.org\/en\/faq_internal#elemhide\"> فلاتر متطابقة مع فلاتر ”إخفاء العناصر“ لتطبيق Adblock Plus<\/a>. هذه الفلاتر جماليّة بالأساس، تهدف إلى إخفاء عناصر في صفحة واب، تعتبر إزعاجا بصريّا، قد لا يتمكّن محرّك فلاتر الرّوابط من كشفها و صدّها.<\/p><p>تفعيل هذا الخيار من شأنه زيادة أثر uBlock₀ على الذّاكرة.<\/p>", "description":"This option enables the parsing and enforcing of Adblock Plus-compatible 'element hiding' filters. These filters are essentially cosmetic, they serve to hide elements in a web page which are deemed to be a visual nuisance, and which can't be blocked by the net request-based filtering engine.\n\nEnabling this feature increases uBlock Origin's memory footprint." }, "3pListsOfBlockedHostsHeader":{ @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"دون معلمات", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"بايت", "description":"" }, "dummy":{ diff --git a/src/_locales/ca/messages.json b/src/_locales/ca/messages.json index 63e247f..fcc01a5 100644 --- a/src/_locales/ca/messages.json +++ b/src/_locales/ca/messages.json @@ -104,7 +104,7 @@ "description":"" }, "popup3pPassiveRulePrompt":{ - "message":"css\/images de tercers", + "message":"css\/imatges de tercers", "description":"" }, "popupInlineScriptRulePrompt":{ @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"sense paràmetres", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ diff --git a/src/_locales/cs/messages.json b/src/_locales/cs/messages.json index e2c4373..ebe1d36 100644 --- a/src/_locales/cs/messages.json +++ b/src/_locales/cs/messages.json @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"bez parametrů", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"bajtů", "description":"" }, "dummy":{ diff --git a/src/_locales/da/messages.json b/src/_locales/da/messages.json index 268240e..ca72885 100644 --- a/src/_locales/da/messages.json +++ b/src/_locales/da/messages.json @@ -104,7 +104,7 @@ "description":"" }, "popup3pPassiveRulePrompt":{ - "message":"3rd-party css\/images", + "message":"Tredjeparts css\/billeder", "description":"" }, "popupInlineScriptRulePrompt":{ @@ -176,7 +176,7 @@ "description":"English: Color-blind friendly" }, "settingsCloudStorageEnabledPrompt":{ - "message":"Enable cloud storage support", + "message":"Aktiver støtte for sky-lagring", "description":"" }, "settingsAdvancedUserPrompt":{ @@ -192,7 +192,7 @@ "description":"English: " }, "settingsWebRTCIPAddressHiddenPrompt":{ - "message":"Prevent WebRTC from leaking local IP addresses", + "message":"Forhindre WebRTC i at lække lokale IP-adresser", "description":"English: " }, "settingsExperimentalPrompt":{ @@ -436,7 +436,7 @@ "description":"Small header to identify the static filtering section" }, "loggerStaticFilteringSentence":{ - "message":"{{action}} netværksanmodninger af {{type}} {{br}}som matcher følgende URL {{url}} {{br}}som stammer fra {{origin}},{{br}}{{importance}} der er et matchende undtagelses-filter.", + "message":"{{action}} netværksanmodninger af {{type}} {{br}}som matcher følgende URL {{url}} {{br}}og som stammer fra {{origin}},{{br}}{{importance}} der er et matchende undtagelses-filter.", "description":"Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartBlock":{ @@ -572,11 +572,11 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"uden parametre", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ - "message":"Found in:", + "message":"Fundet i:", "description":"English: List of filter list names follows" }, "docblockedBack":{ @@ -600,11 +600,11 @@ "description":"English: Permanently" }, "cloudPush":{ - "message":"Export to cloud storage", + "message":"Eksporter til skylagring", "description":"tooltip" }, "cloudPull":{ - "message":"Import from cloud storage", + "message":"Importer fra skylagring", "description":"tooltip" }, "cloudNoData":{ @@ -612,11 +612,11 @@ "description":"" }, "cloudDeviceNamePrompt":{ - "message":"This device name:", + "message":"Denne enheds navn:", "description":"used as a prompt for the user to provide a custom device name" }, "genericSubmit":{ - "message":"Submit", + "message":"Indsend", "description":"for generic 'submit' buttons" }, "genericRevert":{ diff --git a/src/_locales/de/messages.json b/src/_locales/de/messages.json index 3b9b0ec..b646607 100644 --- a/src/_locales/de/messages.json +++ b/src/_locales/de/messages.json @@ -164,7 +164,7 @@ "description":"English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt":{ - "message":"Zeige die Zahl der blockierten Anfragen auf dem Icon", + "message":"Zeige die Zahl der blockierten Anfragen auf dem Symbol", "description":"English: Show the number of blocked requests on the icon" }, "settingsContextMenuPrompt":{ @@ -196,7 +196,7 @@ "description":"English: " }, "settingsExperimentalPrompt":{ - "message":"Aktiviere experimentelle Features (<a href='https:\/\/github.com\/gorhill\/uBlock\/wiki\/Experimental-features'>About<\/a>)", + "message":"Aktiviere experimentelle Funktionen (<a href='https:\/\/github.com\/gorhill\/uBlock\/wiki\/Experimental-features'>About<\/a>)", "description":"English: Enable experimental features" }, "settingsStorageUsed":{ @@ -296,7 +296,7 @@ "description":"a filter list is 'out of date' (possibly needs to be updated)" }, "3pLastUpdate":{ - "message":"Letztes Update: {{ago}}", + "message":"Letzte Aktualisierung: {{ago}}", "description":"English: Last update: {{ago}}, where 'ago' will be replaced with something like '2 days ago'" }, "1pFormatHint":{ @@ -348,7 +348,7 @@ "description":"Will discard manually-edited content and exit manual-edit mode" }, "rulesImport":{ - "message":"Aus Datei importieren...", + "message":"Aus Datei importieren …", "description":"" }, "rulesExport":{ @@ -380,7 +380,7 @@ "description":"English: Export" }, "whitelistExportFilename":{ - "message":"my-ublock-whitelist_{{datetime}}.txt", + "message":"meine-ublock-whitelist_{{datetime}}.txt", "description":"English: my-ublock-whitelist_{{datetime}}.txt" }, "whitelistApply":{ @@ -492,7 +492,7 @@ "description":"English: Contributors" }, "aboutBackupDataButton":{ - "message":"Backup in eine Datei...", + "message":"Backup in eine Datei", "description":"English: Backup to file" }, "aboutBackupFilename":{ @@ -500,11 +500,11 @@ "description":"English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton":{ - "message":"Aus einer Datei wiederherstellen...", + "message":"Aus einer Datei wiederherstellen ...", "description":"English: Restore from file..." }, "aboutResetDataButton":{ - "message":"Fange von ganz vorne an...", + "message":"Auf Vorgaben zurücksetzen …", "description":"English: Reset to default settings..." }, "aboutRestoreDataConfirm":{ diff --git a/src/_locales/el/messages.json b/src/_locales/el/messages.json index 18f15bb..4af2dc0 100644 --- a/src/_locales/el/messages.json +++ b/src/_locales/el/messages.json @@ -104,7 +104,7 @@ "description":"" }, "popup3pPassiveRulePrompt":{ - "message":"3rd-party css\/images", + "message":"Css\/Εικόνες τρίτου μέρους", "description":"" }, "popupInlineScriptRulePrompt":{ @@ -176,7 +176,7 @@ "description":"English: Color-blind friendly" }, "settingsCloudStorageEnabledPrompt":{ - "message":"Enable cloud storage support", + "message":"Ενεργοποίηση υποστήριξης cloud storage", "description":"" }, "settingsAdvancedUserPrompt":{ @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"χωρίς παραμέτρους", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -600,11 +600,11 @@ "description":"English: Permanently" }, "cloudPush":{ - "message":"Export to cloud storage", + "message":"Εξαγωγή στο cloud storage", "description":"tooltip" }, "cloudPull":{ - "message":"Import from cloud storage", + "message":"Εισαγωγή από cloud storage", "description":"tooltip" }, "cloudNoData":{ @@ -612,11 +612,11 @@ "description":"" }, "cloudDeviceNamePrompt":{ - "message":"This device name:", + "message":"Το όνομα της συσκευής:", "description":"used as a prompt for the user to provide a custom device name" }, "genericSubmit":{ - "message":"Submit", + "message":"Υποβολή", "description":"for generic 'submit' buttons" }, "genericRevert":{ diff --git a/src/_locales/fy/messages.json b/src/_locales/fy/messages.json index 0960c1b..0d14cf8 100644 --- a/src/_locales/fy/messages.json +++ b/src/_locales/fy/messages.json @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"sûnder parameters", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ diff --git a/src/_locales/he/messages.json b/src/_locales/he/messages.json index 303ac8a..960e436 100644 --- a/src/_locales/he/messages.json +++ b/src/_locales/he/messages.json @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"ללא פרמטרים", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"ביתים", "description":"" }, "dummy":{ diff --git a/src/_locales/hi/messages.json b/src/_locales/hi/messages.json index c9596fb..af38aca 100644 --- a/src/_locales/hi/messages.json +++ b/src/_locales/hi/messages.json @@ -620,11 +620,11 @@ "description":"for generic 'submit' buttons" }, "genericRevert":{ - "message":"Revert", + "message":"पलटदे", "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"बाइट्स", "description":"" }, "dummy":{ diff --git a/src/_locales/hu/messages.json b/src/_locales/hu/messages.json index 8e40b03..262e7c1 100644 --- a/src/_locales/hu/messages.json +++ b/src/_locales/hu/messages.json @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"paraméterek nélkül", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ diff --git a/src/_locales/id/messages.json b/src/_locales/id/messages.json index bc5bcb3..6acc82e 100644 --- a/src/_locales/id/messages.json +++ b/src/_locales/id/messages.json @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"tanpa parameter", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"byte", "description":"" }, "dummy":{ diff --git a/src/_locales/it/messages.json b/src/_locales/it/messages.json index a224459..726381c 100644 --- a/src/_locales/it/messages.json +++ b/src/_locales/it/messages.json @@ -516,7 +516,7 @@ "description":"Message to display when an error occurred during restore" }, "aboutResetDataConfirm":{ - "message":"Verranno cancellate tutte le impostazioni, e uBlock sarà riavviato.\n\nResettare uBlock alle impostazioni di fabbrica?", + "message":"Verranno cancellate tutte le impostazioni, e uBlock₀ sarà riavviato.\n\nResettare uBlock alle impostazioni di fabbrica?", "description":"Message asking user to confirm reset" }, "errorCantConnectTo":{ @@ -564,7 +564,7 @@ "description":"Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedPrompt1":{ - "message":"uBlock ha impedito alla seguente pagina di caricarsi:", + "message":"uBlock₀ ha impedito alla seguente pagina di caricarsi:", "description":"English: uBlock₀ has prevented the following page from loading:" }, "docblockedPrompt2":{ @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"senza parametri", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"byte", "description":"" }, "dummy":{ diff --git a/src/_locales/ja/messages.json b/src/_locales/ja/messages.json index 01dce44..10f5b08 100644 --- a/src/_locales/ja/messages.json +++ b/src/_locales/ja/messages.json @@ -192,7 +192,7 @@ "description":"English: " }, "settingsWebRTCIPAddressHiddenPrompt":{ - "message":"Prevent WebRTC from leaking local IP addresses", + "message":"ローカルIPアドレスの漏洩をもたらすWebRTCを防止する", "description":"English: " }, "settingsExperimentalPrompt":{ @@ -436,7 +436,7 @@ "description":"Small header to identify the static filtering section" }, "loggerStaticFilteringSentence":{ - "message":"{{action}} network requests of {{type}} {{br}}which URL address matches {{url}} {{br}}and which originates {{origin}},{{br}}{{importance}} there is a matching exception filter.", + "message":"ネットワークリクエストが {{type}} である場合に、{{br}}URLアドレスが {{url}} と一致し、{{br}}{{origin}} を発信源としている場合は {{action}} をします。{{br}}{{importance}} が存在する場合は例外フィルターと一致させます。", "description":"Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartBlock":{ @@ -452,7 +452,7 @@ "description":"Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAnyType":{ - "message":"any type", + "message":"任意の種類", "description":"Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartOrigin":{ @@ -460,19 +460,19 @@ "description":"Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAnyOrigin":{ - "message":"from anywhere", + "message":"全体", "description":"Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartNotImportant":{ - "message":"except when", + "message":"例外", "description":"Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartImportant":{ - "message":"even if", + "message":"非例外", "description":"Used in the static filtering wizard" }, "loggerStaticFilteringFinderSentence1":{ - "message":"Static filter {{filter}} found in:", + "message":"静的フィルター {{filter}} が見つかりました:", "description":"Below this sentence, the filter lists in which the filter was found" }, "aboutChangelog":{ @@ -572,11 +572,11 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"パラメーター未指定", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ - "message":"Found in:", + "message":"次のフィルターで見つかりました:", "description":"English: List of filter list names follows" }, "docblockedBack":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"バイト", "description":"" }, "dummy":{ diff --git a/src/_locales/ko/messages.json b/src/_locales/ko/messages.json index 2c16e04..608057f 100644 --- a/src/_locales/ko/messages.json +++ b/src/_locales/ko/messages.json @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"매개 변수 없이", + "message":"제외 매개 변수", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ diff --git a/src/_locales/nb/messages.json b/src/_locales/nb/messages.json index 17f0f99..3474bf2 100644 --- a/src/_locales/nb/messages.json +++ b/src/_locales/nb/messages.json @@ -292,7 +292,7 @@ "description":"English: new version available" }, "3pExternalListObsolete":{ - "message":"utdatert", + "message":"utgått på dato", "description":"a filter list is 'out of date' (possibly needs to be updated)" }, "3pLastUpdate":{ @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"uten parametere", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ diff --git a/src/_locales/ro/messages.json b/src/_locales/ro/messages.json index d8a937e..3fe1610 100644 --- a/src/_locales/ro/messages.json +++ b/src/_locales/ro/messages.json @@ -16,7 +16,7 @@ "description":"appears as tab name in dashboard" }, "3pPageName":{ - "message":"Filtre externe", + "message":"Filtre terțe", "description":"appears as tab name in dashboard" }, "1pPageName":{ @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"fără parametri", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"octeți", "description":"" }, "dummy":{ diff --git a/src/_locales/sk/messages.json b/src/_locales/sk/messages.json index 381c3c2..e08a2d3 100644 --- a/src/_locales/sk/messages.json +++ b/src/_locales/sk/messages.json @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"bez parametrov", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"bajtov", "description":"" }, "dummy":{ diff --git a/src/_locales/sl/messages.json b/src/_locales/sl/messages.json index 1fc5a14..c1087f2 100644 --- a/src/_locales/sl/messages.json +++ b/src/_locales/sl/messages.json @@ -104,7 +104,7 @@ "description":"" }, "popup3pPassiveRulePrompt":{ - "message":"3rd-party css\/images", + "message":"css\/slike tretje osebe", "description":"" }, "popupInlineScriptRulePrompt":{ @@ -176,7 +176,7 @@ "description":"English: Color-blind friendly" }, "settingsCloudStorageEnabledPrompt":{ - "message":"Enable cloud storage support", + "message":"Omogoči podporo za shrambo v oblako", "description":"" }, "settingsAdvancedUserPrompt":{ @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"brez parametrov", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -600,11 +600,11 @@ "description":"English: Permanently" }, "cloudPush":{ - "message":"Export to cloud storage", + "message":"Izvozi iz shrambe oblaka", "description":"tooltip" }, "cloudPull":{ - "message":"Import from cloud storage", + "message":"Uvozi iz shrambe oblaka", "description":"tooltip" }, "cloudNoData":{ @@ -612,11 +612,11 @@ "description":"" }, "cloudDeviceNamePrompt":{ - "message":"This device name:", + "message":"Ime te naprave:", "description":"used as a prompt for the user to provide a custom device name" }, "genericSubmit":{ - "message":"Submit", + "message":"Predloži", "description":"for generic 'submit' buttons" }, "genericRevert":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"biti", "description":"" }, "dummy":{ diff --git a/src/_locales/sq/messages.json b/src/_locales/sq/messages.json index 4f13dd5..e0db1d5 100644 --- a/src/_locales/sq/messages.json +++ b/src/_locales/sq/messages.json @@ -40,7 +40,7 @@ "description":"appears as tab name in dashboard" }, "popupPowerSwitchInfo":{ - "message":"Klikoj: uBlock bëhet joaktiv\/aktiv te ky uebsajti.\n\nCtrl+klikim: uBlock bëhet joaktiv vetëm te kjo faqja.", + "message":"Klikoj: uBlock₀ bëhet joaktiv\/aktiv te ky uebsajti.\n\nCtrl+klikim: uBlock₀ bëhet joaktiv vetëm te kjo faqja.", "description":"English: Click: disable\/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." }, "popupBlockedRequestPrompt":{ @@ -76,7 +76,7 @@ "description":"English: Go to request log" }, "popupTipNoPopups":{ - "message":"Bllokoj të gjitha dritaret që hap kjo faqja", + "message":"Bllokoj të gjitha dritaret automatike që hap kjo faqja", "description":"English: Toggle the blocking of all popups for this site" }, "popupTipNoStrictBlocking":{ @@ -160,7 +160,7 @@ "description":"English: Block element" }, "settingsCollapseBlockedPrompt":{ - "message":"Fsheh simbolin e elementeve të bllokuara", + "message":"Fsheh treguesin e elementeve të bllokuara", "description":"English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt":{ @@ -172,11 +172,11 @@ "description":"English: Make use of context menu where appropriate" }, "settingsColorBlindPrompt":{ - "message":"Ngjyra të qarta për daltonikët", + "message":"Ndryshoj ngjyrat për daltonikët", "description":"English: Color-blind friendly" }, "settingsCloudStorageEnabledPrompt":{ - "message":"Enable cloud storage support", + "message":"Aktivizoj renë informatike", "description":"" }, "settingsAdvancedUserPrompt":{ @@ -184,7 +184,7 @@ "description":"English: " }, "settingsPrefetchingDisabledPrompt":{ - "message":"Çaktivizoj hapjen e parakohshme të faqeve (parandalon lidhjen për kërkesat e bllokuara nga rrjeti)", + "message":"Çaktivizoj hapjen e parakohshme të faqeve (duke parandaluar lidhjen me kërkesat e bllokuara)", "description":"English: " }, "settingsHyperlinkAuditingDisabledPrompt":{ @@ -252,7 +252,7 @@ "description":"English: Ads" }, "3pGroupPrivacy":{ - "message":"Sfera private", + "message":"Privatësia", "description":"English: Privacy" }, "3pGroupMalware":{ @@ -276,7 +276,7 @@ "description":"English: Custom" }, "3pExternalListsHint":{ - "message":"Një URL për rresht. Rreshtat që kanë si parashtesë ‘!’ nuk do të merren parasysh, sikundër adresat pa kuptim.", + "message":"Një URL për rresht. Nuk do të merren parasysh rreshtat që kanë si parashtesë ‘!’, sikundër adresat pa kuptim.", "description":"English: One URL per line. Lines prefixed with ‘!’ will be ignored. Invalid URLs will be silently ignored." }, "3pExternalListsApply":{ @@ -348,11 +348,11 @@ "description":"Will discard manually-edited content and exit manual-edit mode" }, "rulesImport":{ - "message":"Importoj nga një skedë...", + "message":"Importoj nga një skedar...", "description":"" }, "rulesExport":{ - "message":"Ruaj në skedë", + "message":"Ruaj në skedar", "description":"" }, "rulesDefaultFileName":{ @@ -368,7 +368,7 @@ "description":"English: dynamic rule syntax and full documentation." }, "whitelistPrompt":{ - "message":"Lista juaj me emrat e hosteve për të cilat uBlock do të jetë joaktiv. Një element për rresht. Emrat e pasaktë nuk do të merren parasysh.", + "message":"Lista e hosteve për të cilat uBlock₀ do të jetë joaktiv. Një element për rresht. Nuk do të merren parasysh emrat e pasaktë.", "description":"English: Your list of host names for which uBlock₀ will be disabled. One host name per line. Invalid host names will be silently ignored." }, "whitelistImport":{ @@ -436,7 +436,7 @@ "description":"Small header to identify the static filtering section" }, "loggerStaticFilteringSentence":{ - "message":"{{action}} kërkesat nga rrjeti të {{type}} {{br}}adresa e të cilave korrespondon me {{url}} {{br}}dhe kanë si origjinë {{origin}},{{br}}{{importance}} ka një filtër përjashtues të ngjashëm.", + "message":"{{action}} kërkesat e {{type}} {{br}}adresa e të cilave korrespondon me {{url}} {{br}}dhe që kanë si origjinë {{origin}},{{br}}{{importance}} ekziston një filtër përjashtues i ngjashëm.", "description":"Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartBlock":{ @@ -464,7 +464,7 @@ "description":"Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartNotImportant":{ - "message":"përveç kur", + "message":"përveçse kur", "description":"Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartImportant":{ @@ -492,7 +492,7 @@ "description":"English: Contributors" }, "aboutBackupDataButton":{ - "message":"Kopjoj në skedë", + "message":"Kopjoj në skedar", "description":"English: Backup to file" }, "aboutBackupFilename":{ @@ -500,7 +500,7 @@ "description":"English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton":{ - "message":"Rindërtoj sipas skedës...", + "message":"Rindërtoj sipas skedarit...", "description":"English: Restore from file..." }, "aboutResetDataButton":{ @@ -508,7 +508,7 @@ "description":"English: Reset to default settings..." }, "aboutRestoreDataConfirm":{ - "message":"Të gjithë parametrat do të mbishkruhen me të dhënat e kopjuara më {{time}}, dhe uBlock do të rifillojë.\n\nDo i mbishkruani parametrat aktualë?", + "message":"Të gjithë parametrat do të mbishkruhen me të dhënat e kopjuara më {{time}}, dhe uBlock₀ do të hapet përsëri.\n\nDo i mbishkruani parametrat aktualë?", "description":"Message asking user to confirm restore" }, "aboutRestoreDataError":{ @@ -516,7 +516,7 @@ "description":"Message to display when an error occurred during restore" }, "aboutResetDataConfirm":{ - "message":"Të gjithë parametrat do të fshihen dhe uBlock do të rifillojë.\n\nDo ktheni parametrat origjinalë?", + "message":"Të gjithë parametrat do të fshihen dhe uBlock₀ do të hapet përsëri.\n\nDo ktheni parametrat origjinalë?", "description":"Message asking user to confirm reset" }, "errorCantConnectTo":{ @@ -524,7 +524,7 @@ "description":"English: Network error: unable to connect to {{url}}" }, "subscriberConfirm":{ - "message":"uBlock: Do e shtoni këtë adresën në listën e filtrave tuaj?\n\nTitulli: \"{{title}}\"\nURL: {{url}}", + "message":"uBlock₀: Do e shtoni këtë adresën në listën e filtrave tuaj?\n\nTitulli: \"{{title}}\"\nURL: {{url}}", "description":"English: The message seen by the user to confirm subscription to a ABP filter list" }, "elapsedOneMinuteAgo":{ @@ -564,7 +564,7 @@ "description":"Firefox-specific: appears as 'uBlock₀ (off)'" }, "docblockedPrompt1":{ - "message":"uBlock e pengoi hapjen e faqes:", + "message":"uBlock Origin e pengoi hapjen e faqes:", "description":"English: uBlock₀ has prevented the following page from loading:" }, "docblockedPrompt2":{ @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"pa parametra", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -600,11 +600,11 @@ "description":"English: Permanently" }, "cloudPush":{ - "message":"Export to cloud storage", + "message":"Eksportoj në renë informatike", "description":"tooltip" }, "cloudPull":{ - "message":"Import from cloud storage", + "message":"Importoj nga reja informatike", "description":"tooltip" }, "cloudNoData":{ @@ -612,11 +612,11 @@ "description":"" }, "cloudDeviceNamePrompt":{ - "message":"This device name:", + "message":"Emri i aparatit:", "description":"used as a prompt for the user to provide a custom device name" }, "genericSubmit":{ - "message":"Submit", + "message":"Parashtroj", "description":"for generic 'submit' buttons" }, "genericRevert":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"bajt", "description":"" }, "dummy":{ diff --git a/src/_locales/sv/messages.json b/src/_locales/sv/messages.json index a19adc7..a0fbb9f 100644 --- a/src/_locales/sv/messages.json +++ b/src/_locales/sv/messages.json @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"utan parametrar", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"byte", "description":"" }, "dummy":{ diff --git a/src/_locales/te/messages.json b/src/_locales/te/messages.json index 9613669..d85dbc0 100644 --- a/src/_locales/te/messages.json +++ b/src/_locales/te/messages.json @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"పారామితులు లేని", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"బైట్లు", "description":"" }, "dummy":{ diff --git a/src/_locales/uk/messages.json b/src/_locales/uk/messages.json index a652df6..9e6f2de 100644 --- a/src/_locales/uk/messages.json +++ b/src/_locales/uk/messages.json @@ -176,7 +176,7 @@ "description":"English: Color-blind friendly" }, "settingsCloudStorageEnabledPrompt":{ - "message":"Увімкнути підтримку хмаринкового сховища", + "message":"Увімкнути підтримку хмарного сховища", "description":"" }, "settingsAdvancedUserPrompt":{ @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"without parameters", + "message":"без параметрів", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ @@ -600,11 +600,11 @@ "description":"English: Permanently" }, "cloudPush":{ - "message":"Експортувати до хмаринкового сховища", + "message":"Експортувати до хмарного сховища", "description":"tooltip" }, "cloudPull":{ - "message":"Імпортувати із хмаринкового сховища", + "message":"Імпортувати із хмарного сховища", "description":"tooltip" }, "cloudNoData":{ @@ -624,7 +624,7 @@ "description":"for generic 'revert' buttons" }, "genericBytes":{ - "message":"bytes", + "message":"байтів", "description":"" }, "dummy":{ diff --git a/src/_locales/zh_CN/messages.json b/src/_locales/zh_CN/messages.json index b938a8e..c1701c9 100644 --- a/src/_locales/zh_CN/messages.json +++ b/src/_locales/zh_CN/messages.json @@ -572,7 +572,7 @@ "description":"English: Because of the following filter" }, "docblockedNoParamsPrompt":{ - "message":"没有参数", + "message":"无参数", "description":"label to be used for the parameter-less URL" }, "docblockedFoundIn":{ diff --git a/src/background.html b/src/background.html index 5852880..43863d2 100644 --- a/src/background.html +++ b/src/background.html @@ -30,6 +30,7 @@ <script src="js/traffic.js"></script> <script src="js/contextmenu.js"></script> <script src="js/reverselookup.js"></script> +<script src="js/rpcreceiver.js"></script> <script src="js/start.js"></script> </body> </html> diff --git a/src/css/dashboard-common.css b/src/css/dashboard-common.css index b291720..b23e0ca 100644 --- a/src/css/dashboard-common.css +++ b/src/css/dashboard-common.css @@ -15,6 +15,12 @@ h3 { a { text-decoration: none; } +a.info { + color: #ccc; + } +a.info:hover { + color: #444; + } button { padding: 0.33em; } diff --git a/src/css/popup.css b/src/css/popup.css index 50b0f0e..cef5934 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -3,6 +3,7 @@ body { border: 0; float: left; margin: 0; + opacity: 1; overflow: hidden; padding: 0; white-space: nowrap; diff --git a/src/css/settings.css b/src/css/settings.css index 48ba84a..308334f 100644 --- a/src/css/settings.css +++ b/src/css/settings.css @@ -11,12 +11,6 @@ ul#userSettings, ul#userSettings ul { list-style-type: none; } -ul#userSettings a.info { - color: #ccc; - } -ul#userSettings a.info:hover { - color: #444; - } ul#userSettings .subgroup { margin-top: 1em; } diff --git a/src/js/3p-filters.js b/src/js/3p-filters.js index a3e81b8..b5fca1b 100644 --- a/src/js/3p-filters.js +++ b/src/js/3p-filters.js @@ -371,8 +371,22 @@ var onPurgeClicked = function() { if ( !href ) { return; } + messager.send({ what: 'purgeCache', path: href }); button.remove(); + + // If the cached version is purged, the installed version must be assumed + // to be obsolete. + var entry = listDetails.current && listDetails.current[href]; + if ( entry && entry.off !== true ) { + if ( typeof entry.homeURL !== 'string' || entry.homeURL === '' ) { + li.descendants('span.status.new').css('display', ''); + } else { + li.descendants('span.status.obsolete').css('display', ''); + } + needUpdate = true; + } + if ( li.descendants('input').first().prop('checked') ) { cacheWasPurged = true; renderWidgets(); diff --git a/src/js/assets.js b/src/js/assets.js index 8549cd8..08616c5 100644 --- a/src/js/assets.js +++ b/src/js/assets.js @@ -61,6 +61,7 @@ var lastRepoMetaTimestamp = 0; var lastRepoMetaIsRemote = false; var refreshRepoMetaPeriod = 5 * oneHour; var errorCantConnectTo = vAPI.i18n('errorCantConnectTo'); +var xhrTimeout = vAPI.localStorage.getItem('xhrTimeout') || 30000; var exports = { autoUpdate: true, @@ -275,8 +276,14 @@ var cachedAssetsManager = (function() { exports.remove(/./); }; + exports.exists = function(path) { + return entries !== null && entries.hasOwnProperty(path); + }; + exports.onRemovedListener = null; + getEntries(function(){}); + return exports; })(); @@ -285,6 +292,10 @@ var cachedAssetsManager = (function() { var getTextFileFromURL = function(url, onLoad, onError) { // console.log('µBlock.assets/getTextFileFromURL("%s"):', url); + if ( typeof onError !== 'function' ) { + onError = onLoad; + } + // https://github.com/gorhill/uMatrix/issues/15 var onResponseReceived = function() { this.onload = this.onerror = this.ontimeout = null; @@ -318,7 +329,7 @@ var getTextFileFromURL = function(url, onLoad, onError) { var xhr = new XMLHttpRequest(); try { xhr.open('get', url, true); - xhr.timeout = 30000; + xhr.timeout = xhrTimeout; xhr.onload = onResponseReceived; xhr.onerror = onErrorReceived; xhr.ontimeout = onErrorReceived; @@ -376,11 +387,16 @@ var getRepoMetadata = function(callback) { lastRepoMetaTimestamp = Date.now(); lastRepoMetaIsRemote = exports.remoteFetchBarrier === 0; + var defaultChecksums; var localChecksums; var repoChecksums; var checksumsReceived = function() { - if ( localChecksums === undefined || repoChecksums === undefined ) { + if ( + defaultChecksums === undefined || + localChecksums === undefined || + repoChecksums === undefined + ) { return; } // Remove from cache assets which no longer exist in the repo @@ -392,6 +408,17 @@ var getRepoMetadata = function(callback) { continue; } entry = entries[path]; + // https://github.com/gorhill/uBlock/issues/760 + // If the resource does not have a cached instance, we must reset + // the checksum to its value at install time. + if ( + stringIsNotEmpty(defaultChecksums[path]) && + entry.localChecksum !== defaultChecksums[path] && + cachedAssetsManager.exists(path) === false + ) { + entry.localChecksum = defaultChecksums[path]; + checksumsChanged = true; + } // If repo checksums could not be fetched, assume no change. // https://github.com/gorhill/uBlock/issues/602 // Added: if repo checksum is that of the empty string, @@ -450,41 +477,64 @@ var getRepoMetadata = function(callback) { return out.join('\n'); }; - var parseChecksums = function(text, which) { - var entries = repoMetadata.entries; + var parseChecksums = function(text, eachFn) { var lines = text.split(/\n+/); var i = lines.length; - var fields, assetPath; + var fields; while ( i-- ) { fields = lines[i].trim().split(/\s+/); if ( fields.length !== 2 ) { continue; } - assetPath = fields[1]; - if ( entries[assetPath] === undefined ) { - entries[assetPath] = new AssetEntry(); - } - entries[assetPath][which + 'Checksum'] = fields[0]; + eachFn(fields[1], fields[0]); } }; var onLocalChecksumsLoaded = function(details) { + var entries = repoMetadata.entries; + var processChecksum = function(path, checksum) { + if ( entries.hasOwnProperty(path) === false ) { + entries[path] = new AssetEntry(); + } + entries[path].localChecksum = checksum; + }; if ( (localChecksums = validateChecksums(details)) ) { - parseChecksums(localChecksums, 'local'); + parseChecksums(localChecksums, processChecksum); } checksumsReceived(); }; var onRepoChecksumsLoaded = function(details) { + var entries = repoMetadata.entries; + var processChecksum = function(path, checksum) { + if ( entries.hasOwnProperty(path) === false ) { + entries[path] = new AssetEntry(); + } + entries[path].repoChecksum = checksum; + }; if ( (repoChecksums = validateChecksums(details)) ) { - parseChecksums(repoChecksums, 'repo'); + parseChecksums(repoChecksums, processChecksum); } checksumsReceived(); }; + // https://github.com/gorhill/uBlock/issues/760 + // We need the checksum values at install time, because some resources + // may have been purged, in which case the checksum must be reset to the + // value at install time. + var onDefaultChecksumsLoaded = function() { + defaultChecksums = Object.create(null); + var processChecksum = function(path, checksum) { + defaultChecksums[path] = checksum; + }; + parseChecksums(this.responseText || '', processChecksum); + checksumsReceived(); + }; + repoMetadata = new RepoMetadata(); repoMetadata.waiting.push(callback); readRepoFile('assets/checksums.txt', onRepoChecksumsLoaded); + getTextFileFromURL(vAPI.getURL('assets/checksums.txt'), onDefaultChecksumsLoaded); readLocalFile('assets/checksums.txt', onLocalChecksumsLoaded); }; @@ -1166,8 +1216,14 @@ exports.purge = function(pattern, before) { cachedAssetsManager.remove(pattern, before); }; +exports.purgeCacheableAsset = function(pattern, before) { + cachedAssetsManager.remove(pattern, before); + lastRepoMetaTimestamp = 0; +}; + exports.purgeAll = function(callback) { cachedAssetsManager.removeAll(callback); + lastRepoMetaTimestamp = 0; }; /******************************************************************************/ diff --git a/src/js/background.js b/src/js/background.js index 1aa5d54..8ff3b2b 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -57,7 +57,7 @@ return { collapseBlocked: true, colorBlindFriendly: false, contextMenuEnabled: true, - dynamicFilteringEnabled: false, + dynamicFilteringEnabled: true, experimentalEnabled: false, externalLists: defaultExternalLists, firewallPaneMinimized: true, diff --git a/src/js/contentscript-end.js b/src/js/contentscript-end.js index 776862f..f2986b8 100644 --- a/src/js/contentscript-end.js +++ b/src/js/contentscript-end.js @@ -478,7 +478,7 @@ var uBlockCollapser = (function() { // https://www.chromestatus.com/features/4668884095336448 // "Multiple shadow roots is being deprecated." if ( shadow !== null ) { - if ( shadow.className !== sessionId ) { + if ( shadow.className !== sessionId ) { elem.style.setProperty('display', 'none', 'important'); } continue; @@ -486,9 +486,13 @@ var uBlockCollapser = (function() { // https://github.com/gorhill/uBlock/pull/555 // Not all nodes can be shadowed: // https://github.com/w3c/webcomponents/issues/102 + // https://github.com/gorhill/uBlock/issues/762 + // Remove display style that might get in the way of the shadow + // node doing its magic. try { shadow = elem.createShadowRoot(); shadow.className = sessionId; + elem.style.removeProperty('display'); } catch (ex) { elem.style.setProperty('display', 'none', 'important'); } @@ -921,11 +925,15 @@ var uBlockCollapser = (function() { return; } var onMouseClick = function(ev) { + var elem = ev.target; + while ( elem !== null && elem.localName !== 'a' ) { + elem = elem.parentElement; + } messager.send({ what: 'mouseClick', x: ev.clientX, y: ev.clientY, - url: ev.target && ev.target.localName === 'a' ? ev.target.href : '' + url: elem !== null ? elem.href : '' }); }; diff --git a/src/js/contentscript-start.js b/src/js/contentscript-start.js index ac7d924..a625085 100644 --- a/src/js/contentscript-start.js +++ b/src/js/contentscript-start.js @@ -195,9 +195,13 @@ var hideElements = function(selectors) { // https://github.com/gorhill/uBlock/pull/555 // Not all nodes can be shadowed: // https://github.com/w3c/webcomponents/issues/102 + // https://github.com/gorhill/uBlock/issues/762 + // Remove display style that might get in the way of the shadow + // node doing its magic. try { shadow = elem.createShadowRoot(); shadow.className = sessionId; + elem.style.removeProperty('display'); } catch (ex) { elem.style.setProperty('display', 'none', 'important'); } diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js index 9a5d23f..3ef45d4 100644 --- a/src/js/cosmetic-filtering.js +++ b/src/js/cosmetic-filtering.js @@ -230,20 +230,19 @@ FilterEntity.fromSelfie = function(s) { /******************************************************************************/ var FilterParser = function() { - this.prefix = ''; - this.suffix = ''; + this.prefix = this.suffix = this.style = ''; this.unhide = 0; this.hostnames = []; this.invalid = false; this.cosmetic = true; - this.reParser = /^\s*([^#]*)(##|#@#)(.+)\s*$/; + this.reParser = /^([^#]*?)(##|#@#)(.+)$/; + this.reScriptContains = /^script:contains\(.+?\)$/; }; /******************************************************************************/ FilterParser.prototype.reset = function() { - this.prefix = ''; - this.suffix = ''; + this.prefix = this.suffix = this.style = ''; this.unhide = 0; this.hostnames.length = 0; this.invalid = false; @@ -262,10 +261,20 @@ FilterParser.prototype.parse = function(s) { this.cosmetic = false; return this; } - - // Remember original string - this.prefix = matches[1]; - this.suffix = matches[3]; + this.prefix = matches[1].trim(); + this.unhide = matches[2].charAt(1) === '@' ? 1 : 0; + this.suffix = matches[3].trim(); + + // Cosmetic filters with explicit style properties can apply only: + // - to specific cosmetic filters (those which apply to a specific site) + // - to block cosmetic filters (not exception cosmetic filters) + if ( this.suffix.slice(-1) === '}' ) { + // Not supported for now: this code will ensure some backward + // compatibility for when cosmetic filters with explicit style + // properties start to be in use. + this.invalid = true; + return this; + } // 2014-05-23: // https://github.com/gorhill/httpswitchboard/issues/260 @@ -283,10 +292,31 @@ FilterParser.prototype.parse = function(s) { this.suffix = this.suffix.slice(1); } - this.unhide = matches[2].charAt(1) === '@' ? 1 : 0; if ( this.prefix !== '' ) { this.hostnames = this.prefix.split(/\s*,\s*/); } + + // Script tag filters: pre-process them so that can be used with minimal + // overhead in the content script. + // Examples: + // focus.de##script:contains(/uabInject/) + // focus.de##script:contains(uabInject) + if ( this.suffix.charAt(0) === 's' && this.reScriptContains.test(this.suffix) ) { + // Currently supported only as non-generic selector. Also, exception + // script tag filter makes no sense, ignore. + if ( this.hostnames.length === 0 || this.unhide === 1 ) { + this.invalid = true; + return this; + } + var suffix = this.suffix; + this.suffix = 'script//:'; + if ( suffix.charAt(16) !== '/' || suffix.slice(-2) !== '/)' ) { + this.suffix += suffix.slice(16, -1).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + } else { + this.suffix += suffix.slice(17, -2).replace(/\\/g, '\\'); + } + } + return this; }; @@ -554,6 +584,8 @@ FilterContainer.prototype.reset = function() { // hostname, entity-based filters this.hostnameFilters = {}; this.entityFilters = {}; + this.scriptTagFilters = {}; + this.scriptTagFilterCount = 0; }; /******************************************************************************/ @@ -576,11 +608,14 @@ FilterContainer.prototype.isValidSelector = (function() { try { // https://github.com/gorhill/uBlock/issues/693 div.matches(s + ',\n#foo'); + return true; } catch (e) { - console.error('uBlock> invalid cosmetic filter:', s); - return false; } - return true; + if ( s.lastIndexOf('script//:', 0) === 0 ) { + return true; + } + console.error('uBlock> invalid cosmetic filter:', s); + return false; }; })(); @@ -790,6 +825,11 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) { // h ir twitter.com .promoted-tweet if ( fields[0] === 'h' ) { + // Special filter: script tags. Not a real CSS selector. + if ( fields[3].lastIndexOf('script//:', 0) === 0 ) { + this.createScriptTagFilter(fields[2], fields[3].slice(9)); + continue; + } filter = new FilterHostname(fields[3], fields[2]); bucket = this.hostnameFilters[fields[1]]; if ( bucket === undefined ) { @@ -821,6 +861,11 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg, skip) { // entity selector if ( fields[0] === 'e' ) { + // Special filter: script tags. Not a real CSS selector. + if ( fields[2].lastIndexOf('script//:', 0) === 0 ) { + this.createScriptTagFilter(fields[1], fields[2].slice(9)); + continue; + } bucket = this.entityFilters[fields[1]]; if ( bucket === undefined ) { this.entityFilters[fields[1]] = [fields[2]]; @@ -886,6 +931,49 @@ FilterContainer.prototype.skipCompiledContent = function(text, lineBeg) { /******************************************************************************/ +FilterContainer.prototype.createScriptTagFilter = function(hostname, s) { + if ( this.scriptTagFilters.hasOwnProperty(hostname) ) { + this.scriptTagFilters[hostname] += '|' + s; + } else { + this.scriptTagFilters[hostname] = s; + } + this.scriptTagFilterCount += 1; +}; + +/******************************************************************************/ + +FilterContainer.prototype.retrieveScriptTagRegex = function(domain, hostname) { + if ( this.scriptTagFilterCount === 0 ) { + return; + } + var out = [], hn = hostname, pos; + for (;;) { + if ( this.scriptTagFilters.hasOwnProperty(hn) ) { + out.push(this.scriptTagFilters[hn]); + } + if ( hn === domain ) { + break; + } + pos = hn.indexOf('.'); + if ( pos === -1 ) { + break; + } + hn = hn.slice(pos + 1); + } + pos = domain.indexOf('.'); + if ( pos !== -1 ) { + hn = domain.slice(0, pos); + if ( this.scriptTagFilters.hasOwnProperty(hn) ) { + out.push(this.scriptTagFilters[hn]); + } + } + if ( out.length !== 0 ) { + return out.join('|'); + } +}; + +/******************************************************************************/ + FilterContainer.prototype.freeze = function() { this.duplicateBuster = {}; @@ -939,7 +1027,9 @@ FilterContainer.prototype.toSelfie = function() { highMediumGenericHideCount: this.highMediumGenericHideCount, highHighGenericHide: this.highHighGenericHide, highHighGenericHideCount: this.highHighGenericHideCount, - genericDonthide: this.genericDonthide + genericDonthide: this.genericDonthide, + scriptTagFilters: this.scriptTagFilters, + scriptTagFilterCount: this.scriptTagFilterCount }; }; @@ -1000,6 +1090,8 @@ FilterContainer.prototype.fromSelfie = function(selfie) { this.highHighGenericHide = selfie.highHighGenericHide; this.highHighGenericHideCount = selfie.highHighGenericHideCount; this.genericDonthide = selfie.genericDonthide; + this.scriptTagFilters = selfie.scriptTagFilters; + this.scriptTagFilterCount = selfie.scriptTagFilterCount; this.frozen = true; }; diff --git a/src/js/document-blocked.js b/src/js/document-blocked.js index 5b1c469..c64954a 100644 --- a/src/js/document-blocked.js +++ b/src/js/document-blocked.js @@ -193,12 +193,9 @@ uDom.nodeFromId('why').textContent = details.fs; }; var renderParams = function(parentNode, rawURL) { - var url = null; - try { - url = new URL(rawURL); - } catch(ex) { - } - if ( url === null || url.search.length === 0 ) { + var a = document.createElement('a'); + a.href = rawURL; + if ( a.search.length === 0 ) { return false; } @@ -209,7 +206,7 @@ uDom.nodeFromId('why').textContent = details.fs; ); parentNode.appendChild(li); - var params = url.search.slice(1).split('&'); + var params = a.search.slice(1).split('&'); var param, name, value, ul; for ( var i = 0; i < params.length; i++ ) { param = params[i]; diff --git a/src/js/messaging.js b/src/js/messaging.js index 2841fef..6076f8d 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -815,7 +815,7 @@ var onMessage = function(request, sender, callback) { switch ( request.what ) { case 'purgeCache': - µb.assets.purge(request.path); + µb.assets.purgeCacheableAsset(request.path); break; default: diff --git a/src/js/reverselookup-worker.js b/src/js/reverselookup-worker.js index b82f9ea..946001c 100644 --- a/src/js/reverselookup-worker.js +++ b/src/js/reverselookup-worker.js @@ -31,25 +31,35 @@ var listEntries = Object.create(null); // Helpers -var rescape = function(s) { +var reEscape = function(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }; +var reSpecialChars = /[\*\^\t\v\n]/; + /******************************************************************************/ var fromNetFilter = function(details) { var lists = []; - var entry, pos; + var compiledFilter = details.compiledFilter; + var entry, content, pos, c; for ( var path in listEntries ) { entry = listEntries[path]; if ( entry === undefined ) { continue; } - pos = entry.content.indexOf(details.compiledFilter); + content = entry.content; + pos = content.indexOf(compiledFilter); if ( pos === -1 ) { continue; } + // https://github.com/gorhill/uBlock/issues/835 + // We need an exact match. + c = content.charAt(pos + compiledFilter.length); + if ( c !== '' && reSpecialChars.test(c) === false ) { + continue; + } lists.push({ title: entry.title, supportURL: entry.supportURL @@ -103,16 +113,16 @@ var fromCosmeticFilter = function(details) { var matches = rePlainSelector.exec(filter); if ( matches ) { if ( matches[0] === filter ) { // simple CSS selector - reStr = rescape('c\vlg\v' + filter); + reStr = reEscape('c\vlg\v' + filter); } else { // complex CSS selector - reStr = rescape('c\vlg+\v' + matches[0] + '\v' + filter); + reStr = reEscape('c\vlg+\v' + matches[0] + '\v' + filter); } } else if ( reHighLow.test(filter) ) { // [alt] or [title] - reStr = rescape('c\vhlg0\v' + filter); + reStr = reEscape('c\vhlg0\v' + filter); } else if ( reHighMedium.test(filter) ) { // [href^="..."] - reStr = rescape('c\vhmg0\v') + '[a-z.-]+' + rescape('\v') + '[a-z]*' + rescape(filter); + reStr = reEscape('c\vhmg0\v') + '[a-z.-]+' + reEscape('\v') + '[a-z]*' + reEscape(filter); } else { // all else - reStr = rescape('c\vhhg0\v' + filter); + reStr = reEscape('c\vhhg0\v' + filter); } candidates[details.rawFilter] = new RegExp(reStr + '(?:\\n|$)'); @@ -125,9 +135,9 @@ var fromCosmeticFilter = function(details) { if ( hostname !== '' ) { for ( ;; ) { candidates[hostname + '##' + filter] = new RegExp( - rescape('c\vh\v') + + reEscape('c\vh\v') + '\\w+' + - rescape('\v' + hostname + '\v' + filter) + + reEscape('\v' + hostname + '\v' + filter) + '(?:\\n|$)' ); // If there is no valid domain, there won't be any other @@ -152,7 +162,7 @@ var fromCosmeticFilter = function(details) { if ( pos !== -1 ) { var entity = domain.slice(0, pos); candidates[entity + '.*##' + filter] = new RegExp( - rescape('c\ve\v' + entity + '\v' + filter) + + reEscape('c\ve\v' + entity + '\v' + filter) + '(?:\\n|$)' ); } diff --git a/src/js/rpcreceiver.js b/src/js/rpcreceiver.js new file mode 100644 index 0000000..995fd76 --- /dev/null +++ b/src/js/rpcreceiver.js @@ -0,0 +1,53 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + Copyright (C) 2015 Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +/* global vAPI, µBlock */ + +/******************************************************************************/ + +(function() { + +'use strict'; + +/******************************************************************************/ + +if ( typeof vAPI.rpcReceiver !== 'object' ) { + return; +} + +/******************************************************************************/ + +vAPI.rpcReceiver.getScriptTagFilters = function(details) { + var µb = µBlock; + var cfe = µb.cosmeticFilteringEngine; + if ( !cfe ) { return; } + var hostname = details.hostname; + return cfe.retrieveScriptTagRegex( + µb.URI.domainFromHostname(hostname) || hostname, + hostname + ); +}; + +/******************************************************************************/ + +})(); + +/******************************************************************************/ diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index 92cc7af..6bbf13a 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -1454,7 +1454,10 @@ FilterParser.prototype.parseOptions = function(s) { this.parseOptParty(false, not); continue; } - if ( opt === 'elemhide' ) { + // https://issues.adblockplus.org/ticket/616 + // `generichide` concept already supported, just a matter of + // adding support for the new keyword. + if ( opt === 'elemhide' || opt === 'generichide' ) { if ( this.action === AllowAction ) { this.parseOptType('elemhide', false); this.action = BlockAction; diff --git a/src/popup.html b/src/popup.html index f3c8c70..62f0b07 100644 --- a/src/popup.html +++ b/src/popup.html @@ -10,7 +10,7 @@ </head> <body> -<a href="dashboard.html" target="_blank" id="gotoPrefs" title="popupTipDashboard"><span id="appname"> </span> <span id="version"> </span></a> +<a href="dashboard.html" target="_blank" id="gotoPrefs" data-i18n-tip="popupTipDashboard" data-tip-position="under"><span id="appname"> </span> <span id="version"> </span></a> <div id="panes"> <div> <p id="switch" data-i18n-tip="popupPowerSwitchInfo" data-tip-position="under"><span class="fa"></span></p> diff --git a/src/settings.html b/src/settings.html index 25bd7d6..3c35353 100644 --- a/src/settings.html +++ b/src/settings.html @@ -15,12 +15,12 @@ <li><input id="icon-badge" type="checkbox"><label data-i18n="settingsIconBadgePrompt" for="icon-badge"></label> <li><input id="context-menu-enabled" type="checkbox"><label data-i18n="settingsContextMenuPrompt" for="context-menu-enabled"></label> <li><input id="color-blind-friendly" type="checkbox"><label data-i18n="settingsColorBlindPrompt" for="color-blind-friendly"></label> - <li><input id="cloud-storage-enabled" type="checkbox"><label data-i18n="settingsCloudStorageEnabledPrompt" for="cloud-storage-enabled"></label> + <li><input id="cloud-storage-enabled" type="checkbox"><label data-i18n="settingsCloudStorageEnabledPrompt" for="cloud-storage-enabled"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Cloud-storage" target="_blank"></a> <li><input id="advanced-user-enabled" type="checkbox"><label data-i18n="settingsAdvancedUserPrompt" for="advanced-user-enabled"></label> <li class="subgroup"><span data-i18n="3pGroupPrivacy"></span><ul> <li><input id="prefetching-disabled" type="checkbox"><label data-i18n="settingsPrefetchingDisabledPrompt" for="prefetching-disabled"></label> <a class="fa info" href="https://wikipedia.org/wiki/Link_prefetching#Issues_and_criticisms" target="_blank"></a> <li><input id="hyperlink-auditing-disabled" type="checkbox"><label data-i18n="settingsHyperlinkAuditingDisabledPrompt" for="hyperlink-auditing-disabled"></label> <a class="fa info" href="http://www.wilderssecurity.com/threads/hyperlink-auditing-aka-a-ping-and-beacon-aka-navigator-sendbeacon.364904/" target="_blank"></a> - <li><input id="webrtc-ipaddress-hidden" type="checkbox"><label data-i18n="settingsWebRTCIPAddressHiddenPrompt" for="webrtc-ipaddress-hidden"></label> <a class="fa info" href="https://www.w3.org/wiki/Privacy/IPAddresses" target="_blank"></a> + <li><input id="webrtc-ipaddress-hidden" type="checkbox"><label data-i18n="settingsWebRTCIPAddressHiddenPrompt" for="webrtc-ipaddress-hidden"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Prevent-WebRTC-from-leaking-local-IP-address" target="_blank"></a> </ul> </ul> |