summaryrefslogtreecommitdiff
path: root/extensions
diff options
context:
space:
mode:
authorGaming4JC <g4jc@bulletmail.org>2018-05-13 22:52:42 -0400
committerGaming4JC <g4jc@bulletmail.org>2018-05-13 22:52:42 -0400
commited90827b59e92f01157634fde3a164a1e1e601e3 (patch)
tree02bf6c7bb1d27a7f1ccc29928b4013e75c2ba958 /extensions
parent359fed020facde55cba51b2be00ced84dfd07c77 (diff)
downloadiceweasel-uxp-ed90827b59e92f01157634fde3a164a1e1e601e3.tar.gz
delete pdfjs add noscript
Diffstat (limited to 'extensions')
-rw-r--r--extensions/moz.build2
-rw-r--r--extensions/noscript/GPL.txt339
-rw-r--r--extensions/noscript/META-INF/manifest.mf1820
-rw-r--r--extensions/noscript/META-INF/mozilla.rsabin0 -> 4221 bytes
-rw-r--r--extensions/noscript/META-INF/mozilla.sf5
-rw-r--r--extensions/noscript/NoScript_License.txt17
-rw-r--r--extensions/noscript/bootstrap.js64
-rw-r--r--extensions/noscript/chrome.manifest62
-rw-r--r--extensions/noscript/chrome/content/noscript/ABE.g55
-rw-r--r--extensions/noscript/chrome/content/noscript/ABE.js1540
-rw-r--r--extensions/noscript/chrome/content/noscript/ABELexer.js1378
-rw-r--r--extensions/noscript/chrome/content/noscript/ABEParser.js1466
-rw-r--r--extensions/noscript/chrome/content/noscript/ASPIdiocy.js566
-rw-r--r--extensions/noscript/chrome/content/noscript/AddressMatcher.js279
-rw-r--r--extensions/noscript/chrome/content/noscript/Bug.js21
-rw-r--r--extensions/noscript/chrome/content/noscript/ChannelReplacement.js61
-rw-r--r--extensions/noscript/chrome/content/noscript/ClearClickHandler.js1414
-rw-r--r--extensions/noscript/chrome/content/noscript/Cookie.js148
-rw-r--r--extensions/noscript/chrome/content/noscript/DNS.js374
-rw-r--r--extensions/noscript/chrome/content/noscript/DOM.js245
-rw-r--r--extensions/noscript/chrome/content/noscript/DoNotTrack.js59
-rw-r--r--extensions/noscript/chrome/content/noscript/Entities.js37
-rw-r--r--extensions/noscript/chrome/content/noscript/ExternalFilters.js728
-rw-r--r--extensions/noscript/chrome/content/noscript/FlashIdiocy.js133
-rw-r--r--extensions/noscript/chrome/content/noscript/ForcedRedirectionCallback.js59
-rw-r--r--extensions/noscript/chrome/content/noscript/FrameScript.jsm87
-rw-r--r--extensions/noscript/chrome/content/noscript/HTTPS.js405
-rw-r--r--extensions/noscript/chrome/content/noscript/IO.js53
-rw-r--r--extensions/noscript/chrome/content/noscript/IOUtil.js290
-rw-r--r--extensions/noscript/chrome/content/noscript/InjectionChecker.js1734
-rw-r--r--extensions/noscript/chrome/content/noscript/JSURL.js88
-rw-r--r--extensions/noscript/chrome/content/noscript/Lang.js17
-rw-r--r--extensions/noscript/chrome/content/noscript/MSEInterception.js98
-rw-r--r--extensions/noscript/chrome/content/noscript/Main.js4530
-rw-r--r--extensions/noscript/chrome/content/noscript/MainChild.js870
-rw-r--r--extensions/noscript/chrome/content/noscript/MainParent.js611
-rw-r--r--extensions/noscript/chrome/content/noscript/Membrane.js20
-rw-r--r--extensions/noscript/chrome/content/noscript/MimeService.js18
-rw-r--r--extensions/noscript/chrome/content/noscript/MimeServiceParent.js19
-rw-r--r--extensions/noscript/chrome/content/noscript/NoScript_License.txt17
-rw-r--r--extensions/noscript/chrome/content/noscript/PasteHandler.jsm83
-rw-r--r--extensions/noscript/chrome/content/noscript/Plugins.js30
-rw-r--r--extensions/noscript/chrome/content/noscript/Policy.js927
-rw-r--r--extensions/noscript/chrome/content/noscript/Profiler.js63
-rw-r--r--extensions/noscript/chrome/content/noscript/RequestWatchdog.js1155
-rw-r--r--extensions/noscript/chrome/content/noscript/Restartless.jsm248
-rw-r--r--extensions/noscript/chrome/content/noscript/ScriptSurrogate.js440
-rw-r--r--extensions/noscript/chrome/content/noscript/ScriptlessBGThumbs.js48
-rw-r--r--extensions/noscript/chrome/content/noscript/SiteUtils.js358
-rw-r--r--extensions/noscript/chrome/content/noscript/Strings.js37
-rw-r--r--extensions/noscript/chrome/content/noscript/SyntaxChecker.js31
-rw-r--r--extensions/noscript/chrome/content/noscript/Thread.js95
-rw-r--r--extensions/noscript/chrome/content/noscript/UISync.jsm316
-rw-r--r--extensions/noscript/chrome/content/noscript/URIValidator.js49
-rw-r--r--extensions/noscript/chrome/content/noscript/WebExt.js49
-rw-r--r--extensions/noscript/chrome/content/noscript/WebGLInterception.js64
-rw-r--r--extensions/noscript/chrome/content/noscript/WinScript.js78
-rw-r--r--extensions/noscript/chrome/content/noscript/about.xul173
-rw-r--r--extensions/noscript/chrome/content/noscript/antlr.js11
-rw-r--r--extensions/noscript/chrome/content/noscript/clearClick.js112
-rw-r--r--extensions/noscript/chrome/content/noscript/clearClick.xul58
-rw-r--r--extensions/noscript/chrome/content/noscript/defer.jsm17
-rw-r--r--extensions/noscript/chrome/content/noscript/e10sChild.js63
-rw-r--r--extensions/noscript/chrome/content/noscript/e10sIPC.js68
-rw-r--r--extensions/noscript/chrome/content/noscript/e10sParent.js101
-rw-r--r--extensions/noscript/chrome/content/noscript/e10sProcessScript.js8
-rw-r--r--extensions/noscript/chrome/content/noscript/frameScript.js3
-rw-r--r--extensions/noscript/chrome/content/noscript/html5_events98
-rw-r--r--extensions/noscript/chrome/content/noscript/iaUI.js204
-rw-r--r--extensions/noscript/chrome/content/noscript/importer.jsm30
-rw-r--r--extensions/noscript/chrome/content/noscript/loader.js73
-rw-r--r--extensions/noscript/chrome/content/noscript/noscript.js193
-rw-r--r--extensions/noscript/chrome/content/noscript/noscript.xbl18
-rw-r--r--extensions/noscript/chrome/content/noscript/noscriptBM.js127
-rw-r--r--extensions/noscript/chrome/content/noscript/noscriptBMOverlay.xul11
-rw-r--r--extensions/noscript/chrome/content/noscript/noscriptOptions.js755
-rw-r--r--extensions/noscript/chrome/content/noscript/noscriptOptions.xul469
-rw-r--r--extensions/noscript/chrome/content/noscript/noscriptOverlay-noStatusBar.xul318
-rw-r--r--extensions/noscript/chrome/content/noscript/noscriptOverlay.js2685
-rw-r--r--extensions/noscript/chrome/content/noscript/noscriptOverlay.xul318
-rw-r--r--extensions/noscript/chrome/content/noscript/tree-copy.js53
-rw-r--r--extensions/noscript/chrome/locale/ar/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/ar/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/ar/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/be-BY/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/be-BY/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/be-BY/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/bg-BG/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/bg-BG/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/bg-BG/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/bn-IN/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/bn-IN/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/bn-IN/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/ca-AD/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/ca-AD/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/ca-AD/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/cs-CZ/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/cs-CZ/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/cs-CZ/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/cy-GB/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/cy-GB/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/cy-GB/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/da/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/da/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/da/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/de/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/de/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/de/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/el/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/el/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/el/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/en-GB/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/en-GB/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/en-GB/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/en-US/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/en-US/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/en-US/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/eo/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/eo/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/eo/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/es-AR/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/es-AR/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/es-AR/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/es-CL/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/es-CL/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/es-CL/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/es-ES/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/es-ES/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/es-ES/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/et-EE/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/et-EE/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/et-EE/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/eu/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/eu/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/eu/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/fa-IR/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/fa-IR/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/fa-IR/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/fi/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/fi/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/fi/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/fr/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/fr/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/fr/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/gl-ES/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/gl-ES/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/gl-ES/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/he-IL/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/he-IL/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/he-IL/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/hr-HR/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/hr-HR/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/hr-HR/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/hsb/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/hsb/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/hsb/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/hu-HU/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/hu-HU/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/hu-HU/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/id-ID/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/id-ID/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/id-ID/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/it/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/it/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/it/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/ja-JP/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/ja-JP/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/ja-JP/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/kk-KZ/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/kk-KZ/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/kk-KZ/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/km-KH/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/km-KH/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/km-KH/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/ko-KR/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/ko-KR/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/ko-KR/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/lt/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/lt/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/lt/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/mk-MK/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/mk-MK/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/mk-MK/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/ms-MY/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/ms-MY/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/ms-MY/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/nb-NO/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/nb-NO/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/nb-NO/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/nl/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/nl/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/nl/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/pl/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/pl/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/pl/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/pt-BR/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/pt-BR/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/pt-BR/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/pt-PT/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/pt-PT/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/pt-PT/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/ro/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/ro/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/ro/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/ru-RU/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/ru-RU/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/ru-RU/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/sk-SK/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/sk-SK/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/sk-SK/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/sl-SI/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/sl-SI/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/sl-SI/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/sr-RS/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/sr-RS/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/sr-RS/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/sr/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/sr/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/sr/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/sv-SE/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/sv-SE/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/sv-SE/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/te-IN/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/te-IN/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/te-IN/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/th/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/th/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/th/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/tr/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/tr/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/tr/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/uk/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/uk/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/uk/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/vi/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/vi/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/vi/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/zh-CN/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/zh-CN/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/zh-CN/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/locale/zh-TW/noscript/about.properties15
-rw-r--r--extensions/noscript/chrome/locale/zh-TW/noscript/noscript.dtd192
-rw-r--r--extensions/noscript/chrome/locale/zh-TW/noscript/noscript.properties56
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/abe16.pngbin0 -> 800 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/about.css88
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/block.wavbin0 -> 7587 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/browser.css322
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/clearclick16.pngbin0 -> 861 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/close.pngbin0 -> 1963 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/console16.pngbin0 -> 756 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/content.css1
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/ef-no16.pngbin0 -> 687 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/ef16.pngbin0 -> 758 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/emb16.pngbin0 -> 868 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/embed-no16.pngbin0 -> 798 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/embed16.pngbin0 -> 808 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/faq16.pngbin0 -> 809 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/flash16.pngbin0 -> 835 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/flash32.pngbin0 -> 2092 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/folder_closed.pngbin0 -> 813 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/folder_open.pngbin0 -> 831 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/font.pngbin0 -> 567 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/glb-emb16.pngbin0 -> 1780 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/glb-no16.pngbin0 -> 944 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/glb16.pngbin0 -> 781 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/https16.pngbin0 -> 749 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/ia.pngbin0 -> 2842 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/icon24.pngbin0 -> 1914 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/icon32.pngbin0 -> 3053 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/icon64.pngbin0 -> 9279 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/icon80.pngbin0 -> 3847 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/inactive-emb16.pngbin0 -> 833 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/inactive-glb16.pngbin0 -> 497 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/inactive-no-emb16.pngbin0 -> 978 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/inactive-no16.pngbin0 -> 968 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/inactive-prt16.pngbin0 -> 594 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/inactive-yes16.pngbin0 -> 416 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/inactive-yu16.pngbin0 -> 830 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/java16.pngbin0 -> 666 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/java32.pngbin0 -> 1620 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/mobile.css67
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/no-emb16.pngbin0 -> 1025 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/no16.pngbin0 -> 997 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/options.css46
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/prt16.pngbin0 -> 847 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/redirect16.pngbin0 -> 572 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/revtemp16.pngbin0 -> 998 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/somelight16.pngbin0 -> 913 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/somelight32.pngbin0 -> 2458 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/subprt16.pngbin0 -> 1001 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/temp16.pngbin0 -> 853 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/unsafe-reload16.pngbin0 -> 943 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/untrusted-glb16.pngbin0 -> 982 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/untrusted16.pngbin0 -> 1032 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/webgl16.pngbin0 -> 995 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/webgl32.pngbin0 -> 2451 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/xss16.pngbin0 -> 1034 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/yes16.pngbin0 -> 786 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/yu-emb16.pngbin0 -> 904 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/yu-glb16.pngbin0 -> 852 bytes
-rw-r--r--extensions/noscript/chrome/skin/classic/noscript/yu16.pngbin0 -> 841 bytes
-rw-r--r--extensions/noscript/components/noscriptService.js15
-rw-r--r--extensions/noscript/defaults/preferences/noscript.js434
-rw-r--r--extensions/noscript/install.rdf102
-rw-r--r--extensions/noscript/mozilla.cfg13
-rw-r--r--extensions/noscript/webextension/legacy.js36
-rw-r--r--extensions/noscript/webextension/manifest.json28
-rw-r--r--extensions/pdfjs/LICENSE177
-rw-r--r--extensions/pdfjs/README.mozilla3
-rw-r--r--extensions/pdfjs/chrome.manifest1
-rw-r--r--extensions/pdfjs/content/PdfJs.jsm348
-rw-r--r--extensions/pdfjs/content/PdfJsNetwork.jsm257
-rw-r--r--extensions/pdfjs/content/PdfJsTelemetry.jsm70
-rw-r--r--extensions/pdfjs/content/PdfStreamConverter.jsm1054
-rw-r--r--extensions/pdfjs/content/PdfjsChromeUtils.jsm357
-rw-r--r--extensions/pdfjs/content/PdfjsContentUtils.jsm150
-rw-r--r--extensions/pdfjs/content/build/pdf.js8387
-rw-r--r--extensions/pdfjs/content/build/pdf.worker.js52500
-rw-r--r--extensions/pdfjs/content/network.js614
-rw-r--r--extensions/pdfjs/content/pdfjschildbootstrap.js36
-rw-r--r--extensions/pdfjs/content/web/cmaps/78-EUC-H.bcmapbin2404 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/78-EUC-V.bcmapbin173 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/78-H.bcmapbin2379 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/78-RKSJ-H.bcmapbin2398 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/78-RKSJ-V.bcmapbin173 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/78-V.bcmapbin169 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/78ms-RKSJ-H.bcmapbin2651 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/78ms-RKSJ-V.bcmapbin290 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/83pv-RKSJ-H.bcmapbin905 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/90ms-RKSJ-H.bcmapbin721 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/90ms-RKSJ-V.bcmapbin290 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/90msp-RKSJ-H.bcmapbin715 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/90msp-RKSJ-V.bcmapbin291 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/90pv-RKSJ-H.bcmapbin982 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/90pv-RKSJ-V.bcmapbin260 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Add-H.bcmapbin2419 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Add-RKSJ-H.bcmapbin2413 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Add-RKSJ-V.bcmapbin287 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Add-V.bcmapbin282 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-CNS1-0.bcmapbin317 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-CNS1-1.bcmapbin371 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-CNS1-2.bcmapbin376 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-CNS1-3.bcmapbin401 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-CNS1-4.bcmapbin405 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-CNS1-5.bcmapbin406 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-CNS1-6.bcmapbin406 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-CNS1-UCS2.bcmapbin41193 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-GB1-0.bcmapbin217 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-GB1-1.bcmapbin250 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-GB1-2.bcmapbin465 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-GB1-3.bcmapbin470 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-GB1-4.bcmapbin601 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-GB1-5.bcmapbin625 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-GB1-UCS2.bcmapbin33974 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Japan1-0.bcmapbin225 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Japan1-1.bcmapbin226 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Japan1-2.bcmapbin233 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Japan1-3.bcmapbin242 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Japan1-4.bcmapbin337 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Japan1-5.bcmapbin430 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Japan1-6.bcmapbin485 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Japan1-UCS2.bcmapbin40951 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Korea1-0.bcmapbin241 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Korea1-1.bcmapbin386 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Korea1-2.bcmapbin391 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Adobe-Korea1-UCS2.bcmapbin23293 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/B5-H.bcmapbin1086 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/B5-V.bcmapbin142 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/B5pc-H.bcmapbin1099 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/B5pc-V.bcmapbin144 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/CNS-EUC-H.bcmapbin1780 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/CNS-EUC-V.bcmapbin1920 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/CNS1-H.bcmapbin706 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/CNS1-V.bcmapbin143 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/CNS2-H.bcmapbin504 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/CNS2-V.bcmap3
-rw-r--r--extensions/pdfjs/content/web/cmaps/ETHK-B5-H.bcmapbin4426 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/ETHK-B5-V.bcmapbin158 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/ETen-B5-H.bcmapbin1125 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/ETen-B5-V.bcmapbin158 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/ETenms-B5-H.bcmap3
-rw-r--r--extensions/pdfjs/content/web/cmaps/ETenms-B5-V.bcmapbin172 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/EUC-H.bcmapbin578 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/EUC-V.bcmapbin170 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Ext-H.bcmapbin2536 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Ext-RKSJ-H.bcmapbin2542 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Ext-RKSJ-V.bcmapbin218 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Ext-V.bcmapbin215 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GB-EUC-H.bcmapbin549 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GB-EUC-V.bcmapbin179 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GB-H.bcmap4
-rw-r--r--extensions/pdfjs/content/web/cmaps/GB-V.bcmapbin175 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBK-EUC-H.bcmapbin14692 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBK-EUC-V.bcmapbin180 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBK2K-H.bcmapbin19662 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBK2K-V.bcmapbin219 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBKp-EUC-H.bcmapbin14686 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBKp-EUC-V.bcmapbin181 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBT-EUC-H.bcmapbin7290 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBT-EUC-V.bcmapbin180 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBT-H.bcmapbin7269 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBT-V.bcmapbin176 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBTpc-EUC-H.bcmapbin7298 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBTpc-EUC-V.bcmapbin182 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBpc-EUC-H.bcmapbin557 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/GBpc-EUC-V.bcmapbin181 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/H.bcmapbin553 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKdla-B5-H.bcmapbin2654 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKdla-B5-V.bcmapbin148 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKdlb-B5-H.bcmapbin2414 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKdlb-B5-V.bcmapbin148 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKgccs-B5-H.bcmapbin2292 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKgccs-B5-V.bcmapbin149 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKm314-B5-H.bcmapbin1772 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKm314-B5-V.bcmapbin149 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKm471-B5-H.bcmapbin2171 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKm471-B5-V.bcmapbin149 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKscs-B5-H.bcmapbin4437 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/HKscs-B5-V.bcmapbin159 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Hankaku.bcmapbin132 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Hiragana.bcmapbin124 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSC-EUC-H.bcmapbin1848 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSC-EUC-V.bcmapbin164 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSC-H.bcmapbin1831 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSC-Johab-H.bcmapbin16791 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSC-Johab-V.bcmapbin166 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSC-V.bcmapbin160 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSCms-UHC-H.bcmapbin2787 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSCms-UHC-HW-H.bcmapbin2789 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSCms-UHC-HW-V.bcmapbin169 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSCms-UHC-V.bcmapbin166 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSCpc-EUC-H.bcmapbin2024 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/KSCpc-EUC-V.bcmapbin166 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Katakana.bcmapbin100 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/LICENSE36
-rw-r--r--extensions/pdfjs/content/web/cmaps/NWP-H.bcmapbin2765 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/NWP-V.bcmapbin252 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/RKSJ-H.bcmapbin534 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/RKSJ-V.bcmapbin170 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/Roman.bcmapbin96 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniCNS-UCS2-H.bcmapbin48280 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniCNS-UCS2-V.bcmapbin156 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniCNS-UTF16-H.bcmapbin50419 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniCNS-UTF16-V.bcmapbin156 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniCNS-UTF32-H.bcmapbin52679 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniCNS-UTF32-V.bcmapbin160 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniCNS-UTF8-H.bcmapbin53629 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniCNS-UTF8-V.bcmapbin157 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniGB-UCS2-H.bcmapbin43366 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniGB-UCS2-V.bcmapbin193 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniGB-UTF16-H.bcmapbin44086 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniGB-UTF16-V.bcmapbin178 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniGB-UTF32-H.bcmapbin45738 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniGB-UTF32-V.bcmapbin182 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniGB-UTF8-H.bcmapbin46837 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniGB-UTF8-V.bcmapbin181 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-H.bcmapbin25439 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-H.bcmapbin119 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-V.bcmapbin680 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-V.bcmapbin664 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS-UTF16-H.bcmapbin39443 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS-UTF16-V.bcmapbin643 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS-UTF32-H.bcmapbin40539 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS-UTF32-V.bcmapbin677 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS-UTF8-H.bcmapbin41695 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS-UTF8-V.bcmapbin678 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF16-H.bcmapbin39534 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF16-V.bcmapbin647 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF32-H.bcmapbin40630 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF32-V.bcmapbin681 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF8-H.bcmapbin41779 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF8-V.bcmapbin682 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJISPro-UCS2-HW-V.bcmapbin705 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJISPro-UCS2-V.bcmapbin689 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJISPro-UTF8-V.bcmapbin726 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJISX0213-UTF32-H.bcmapbin40517 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJISX0213-UTF32-V.bcmapbin684 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-H.bcmapbin40608 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-V.bcmapbin688 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniKS-UCS2-H.bcmapbin25783 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniKS-UCS2-V.bcmapbin178 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniKS-UTF16-H.bcmapbin26327 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniKS-UTF16-V.bcmapbin164 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniKS-UTF32-H.bcmapbin26451 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniKS-UTF32-V.bcmapbin168 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniKS-UTF8-H.bcmapbin27790 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/UniKS-UTF8-V.bcmapbin169 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/V.bcmapbin166 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/cmaps/WP-Symbol.bcmapbin179 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/debugger.js616
-rw-r--r--extensions/pdfjs/content/web/images/annotation-check.svg11
-rw-r--r--extensions/pdfjs/content/web/images/annotation-comment.svg16
-rw-r--r--extensions/pdfjs/content/web/images/annotation-help.svg26
-rw-r--r--extensions/pdfjs/content/web/images/annotation-insert.svg10
-rw-r--r--extensions/pdfjs/content/web/images/annotation-key.svg11
-rw-r--r--extensions/pdfjs/content/web/images/annotation-newparagraph.svg11
-rw-r--r--extensions/pdfjs/content/web/images/annotation-noicon.svg7
-rw-r--r--extensions/pdfjs/content/web/images/annotation-note.svg42
-rw-r--r--extensions/pdfjs/content/web/images/annotation-paragraph.svg16
-rw-r--r--extensions/pdfjs/content/web/images/findbarButton-next-rtl.pngbin199 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/findbarButton-next-rtl@2x.pngbin304 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/findbarButton-next.pngbin193 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/findbarButton-next@2x.pngbin296 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/findbarButton-previous-rtl.pngbin193 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/findbarButton-previous-rtl@2x.pngbin296 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/findbarButton-previous.pngbin199 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/findbarButton-previous@2x.pngbin304 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/grab.curbin326 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/grabbing.curbin326 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/loading-icon.gifbin2545 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/loading-small.pngbin7402 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/loading-small@2x.pngbin16131 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-documentProperties.pngbin403 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-documentProperties@2x.pngbin933 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-firstPage.pngbin179 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-firstPage@2x.pngbin266 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-handTool.pngbin301 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-handTool@2x.pngbin583 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-lastPage.pngbin175 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-lastPage@2x.pngbin276 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw.pngbin360 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw@2x.pngbin731 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCw.pngbin359 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCw@2x.pngbin714 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/shadow.pngbin290 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/texture.pngbin2417 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-bookmark.pngbin174 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-bookmark@2x.pngbin260 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-download.pngbin259 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-download@2x.pngbin425 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-menuArrows.pngbin107 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-menuArrows@2x.pngbin152 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-openFile.pngbin295 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-openFile@2x.pngbin550 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-pageDown-rtl.pngbin242 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-pageDown-rtl@2x.pngbin398 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-pageDown.pngbin238 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-pageDown@2x.pngbin396 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-pageUp-rtl.pngbin245 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-pageUp-rtl@2x.pngbin405 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-pageUp.pngbin246 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-pageUp@2x.pngbin403 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-presentationMode.pngbin321 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-presentationMode@2x.pngbin586 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-print.pngbin257 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-print@2x.pngbin464 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-search.pngbin309 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-search@2x.pngbin653 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle-rtl.pngbin246 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle-rtl@2x.pngbin456 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle.pngbin243 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle@2x.pngbin458 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle-rtl.pngbin225 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle-rtl@2x.pngbin344 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle.pngbin225 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle@2x.pngbin331 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-viewAttachments.pngbin384 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-viewAttachments@2x.pngbin859 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-viewOutline-rtl.pngbin177 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-viewOutline-rtl@2x.pngbin394 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-viewOutline.pngbin178 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-viewOutline@2x.pngbin331 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail.pngbin185 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail@2x.pngbin219 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-zoomIn.pngbin136 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-zoomIn@2x.pngbin160 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-zoomOut.pngbin88 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/toolbarButton-zoomOut@2x.pngbin109 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/treeitem-collapsed-rtl.pngbin143 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/treeitem-collapsed-rtl@2x.pngbin167 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/treeitem-collapsed.pngbin128 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/treeitem-collapsed@2x.pngbin149 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/treeitem-expanded.pngbin125 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/images/treeitem-expanded@2x.pngbin172 -> 0 bytes
-rw-r--r--extensions/pdfjs/content/web/l10n.js151
-rw-r--r--extensions/pdfjs/content/web/viewer.css2034
-rw-r--r--extensions/pdfjs/content/web/viewer.html337
-rw-r--r--extensions/pdfjs/content/web/viewer.js8671
-rw-r--r--extensions/pdfjs/jar.mn3
-rw-r--r--extensions/pdfjs/moz.build7
580 files changed, 45119 insertions, 75970 deletions
diff --git a/extensions/moz.build b/extensions/moz.build
index 69d6af6..3a9f112 100644
--- a/extensions/moz.build
+++ b/extensions/moz.build
@@ -5,6 +5,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += [
- 'pdfjs',
+ 'noscript',
]
diff --git a/extensions/noscript/GPL.txt b/extensions/noscript/GPL.txt
new file mode 100644
index 0000000..0a98ec0
--- /dev/null
+++ b/extensions/noscript/GPL.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 2 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, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. \ No newline at end of file
diff --git a/extensions/noscript/META-INF/manifest.mf b/extensions/noscript/META-INF/manifest.mf
new file mode 100644
index 0000000..1a2b4c8
--- /dev/null
+++ b/extensions/noscript/META-INF/manifest.mf
@@ -0,0 +1,1820 @@
+Manifest-Version: 1.0
+
+Name: install.rdf
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 6l5ExxaHQwxFB8GI8sMrcg==
+SHA1-Digest: Hnd0Dwn6sx+L98+9sf9E7oY9fCI=
+SHA256-Digest: 0KPqvc734C4IvDibFMmQfdNz5JMJGPYSRCF3UlhF9hw=
+
+Name: chrome.manifest
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: V7KkvHOa25w5EOH+NRM6hw==
+SHA1-Digest: z4/9Lia05sKUaZOm5aOQWjShvvw=
+SHA256-Digest: dcHHf03cXEznCOrzGTmb7aSGQjgudC3oY1VJADA8H2E=
+
+Name: bootstrap.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 3pgLD1uMWAX3IlZlD+WD2Q==
+SHA1-Digest: vQqATNf53pNBtiCtAJlq/5TtNmA=
+SHA256-Digest: KotBZsDpeGwFCk8afxB1vH9j/vPnsTxxiE/udcDdhO8=
+
+Name: GPL.txt
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Xc3+JfIRGapUNeq50CVq9w==
+SHA1-Digest: QuhZ5zOu5fE5tq1vLDOP3bdCSKQ=
+SHA256-Digest: EcSotBSlNDZfAtp9rZ3D5HHTWxXtMd+dQAb7KhRMREM=
+
+Name: mozilla.cfg
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: QN7VUFbn7i4XfCTfQhZogA==
+SHA1-Digest: f47dmcoACYEBc7bQRVnwCaMAqGA=
+SHA256-Digest: YVM7CzatrWB2N9ag4LKu13M4oKth3b6n11+xqYTg6+Q=
+
+Name: NoScript_License.txt
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: CYkluXWIXUk6QpUjqxcMtA==
+SHA1-Digest: 624YpFdNjCFbDE7kLhN+vbF9hgM=
+SHA256-Digest: jCnBFvD7jgQEZJiR4gJZBBuxkWUcsmK/kt0pp57pCYc=
+
+Name: chrome/content/noscript/ABE.g
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 0ndiHMR4gYmPSx0U2w0Glw==
+SHA1-Digest: YaQhyi7gw+UKy7h45EG/o3tjSm4=
+SHA256-Digest: UF8ZcxO4+Wo7sa1Bk/t1IPxDZTkohDvdHaJfFOkPNow=
+
+Name: chrome/content/noscript/ABE.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: nqW3JB/1mCkMnoi9cq5JXg==
+SHA1-Digest: kYtE9+zWJY7WxFDIySPSLKUkgbs=
+SHA256-Digest: ndFsVDwJKcN3AZlKk2FGUd8+Ac/3ygepPkRDTi01lSk=
+
+Name: chrome/content/noscript/ABELexer.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 2vn5ncWk3RoiIgzRFDWbfw==
+SHA1-Digest: zOGAS9GCyuI94LIUNyiaxRFqW+E=
+SHA256-Digest: MKRXB0J1Zjb/O1bYr7+ENFfUco73JcwIkTEYrPYZflQ=
+
+Name: chrome/content/noscript/ABEParser.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: +Q7F49vEB2ge5LnrDcqQZQ==
+SHA1-Digest: idl2qN6ruxPfDks9LUMR4uR/6sQ=
+SHA256-Digest: k59cjXU1maQUie3G64dJgV8zKjDcp9RpVySUgVYM8tc=
+
+Name: chrome/content/noscript/about.xul
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Ko/NTaSdoxfNmQ60WSQd3w==
+SHA1-Digest: VrCxO46JS+3fzDr8d2FFBtFIwjg=
+SHA256-Digest: lcCQ73x86zM6BkPUzMtGJLyZ7S3tnURECkVLdJ9FxMI=
+
+Name: chrome/content/noscript/AddressMatcher.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 7ljs5vp/L9x7Gapl6R4wVg==
+SHA1-Digest: h11BwNuVU826xsrz7rKxR2YReiM=
+SHA256-Digest: PD5SHOeC/OkupHtWB85WdzVBPA60pL1TrY3FLAG+X4E=
+
+Name: chrome/content/noscript/antlr.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: u+5zq9KU3YhTYZwnRO4/Vg==
+SHA1-Digest: uRLcqhWxdDNGO5Nqy2zGqc01/bk=
+SHA256-Digest: Y1qGzE6XbhNWb3HZlME31rZpkAhlLJ1b7psjQXQJ5Zo=
+
+Name: chrome/content/noscript/ASPIdiocy.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: lcuhpZC8unztEU41C+wTDg==
+SHA1-Digest: +d9gRnpk1u7Gz6R0yPxJbkRVj60=
+SHA256-Digest: SQKJH8/lsHF7gWSGd5h7Ctmfe4gCee0BcpO49pwgK8U=
+
+Name: chrome/content/noscript/Bug.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: DcX/6xmaGT89vswATO5sTg==
+SHA1-Digest: jsa6GMTrayqkdgbu2NquDsJ1bck=
+SHA256-Digest: ZIN7e+Ei3b4cZ/AoUuquofKQM2gLIc9F1UU93IfcRgo=
+
+Name: chrome/content/noscript/ChannelReplacement.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: wqLge9ivOER94PkOuQUz5Q==
+SHA1-Digest: TZ6d5J/AW3amsC/9aRqPYXdLm7U=
+SHA256-Digest: 1/ZpsoQYOJUExIOjkMOB5g8vIFgQBS8CwYRUaumsQPc=
+
+Name: chrome/content/noscript/clearClick.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: UUI7RbryvunLCtbQejw4bQ==
+SHA1-Digest: gtXR+VBtWnsPnVBv3E0u6FL0McY=
+SHA256-Digest: c17xUOO73Si8Fd1Ykf8Vyu3l+H4SJerkn3xxX1Bb6GM=
+
+Name: chrome/content/noscript/clearClick.xul
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: C+gsI3w8QBnKvtarHvWgtw==
+SHA1-Digest: aD2kpx4CDzAtYg7rnQ/7IYQMysk=
+SHA256-Digest: EFp7zzdJnEhmzJiUJMRklQDlHMzSYH1nin0buJJTHNk=
+
+Name: chrome/content/noscript/ClearClickHandler.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: aNnKlLTdtGzNaREy7QqO/Q==
+SHA1-Digest: kQ9QVwFfMDFFAu9CpJXpJtgSyjA=
+SHA256-Digest: 27SVM5fo9AnAzVyy1OiTM+KdH2OXx0J4NQ2pKCgSdh8=
+
+Name: chrome/content/noscript/Cookie.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 209O1VQ1INFtJqh+vDZYnA==
+SHA1-Digest: ATBv5Y6DnU7lFIdN4cxAK1WQpt8=
+SHA256-Digest: bIqNJOvZyBmjFqjCXXw532qSrLLsXCi57FAc6C11aS4=
+
+Name: chrome/content/noscript/defer.jsm
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: NIpbt8TsDurLbWsz6fKyAA==
+SHA1-Digest: c/9xd0fFqpZq+OvYh9uJJDqGnAE=
+SHA256-Digest: 0Gwu9A6qWBJr9YighDX50vTJv5DPKDdJjC3JdgPwUEo=
+
+Name: chrome/content/noscript/DNS.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 2y5u05xVf2GwvKdcXHtYFQ==
+SHA1-Digest: RjsEP/XBIw+FNyUOoFtxDUYMD0Y=
+SHA256-Digest: bMA+QfL6GRrbxajqxbpdR9Ujrxeuf45qm+sENWM8jCQ=
+
+Name: chrome/content/noscript/DOM.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: JraWQaeU/YMnLLc6vhW4lw==
+SHA1-Digest: MQ66UEyOqVr7b2/iMuquOz3myVc=
+SHA256-Digest: /P+RnuFXV1l1l8trVCGUp8Zq0C3NssZIUZkaUb+BfVY=
+
+Name: chrome/content/noscript/DoNotTrack.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 9JRsQhUDTcHzROHGWnFH+Q==
+SHA1-Digest: bi7E2ani6pOabVt8U861Hjihimc=
+SHA256-Digest: xcrrejk64n8WTyrUURwlAEcJvgu9TuzZsTdGS5mRzAU=
+
+Name: chrome/content/noscript/e10sChild.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 1biTtVock1DxrYFdBuXz4g==
+SHA1-Digest: gZOa5Bg3J+CJQOhqjRVa+1bkOKk=
+SHA256-Digest: ehauwAWuYVaq7GJM3tStPjjDVGKWhextJ5xavIyci2o=
+
+Name: chrome/content/noscript/e10sIPC.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: f9ZrrMUEzsm1xA3xFjvW8A==
+SHA1-Digest: TMDaLQ0PRu8AdK/+A5smVereJM8=
+SHA256-Digest: wGwtzNGEeSg/FB4+ENfYJ/rq8fqIaU4lR8rfbX97Ubc=
+
+Name: chrome/content/noscript/e10sParent.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: W07jrcZx7lxv2Eqh+EYBww==
+SHA1-Digest: +1VY0T2Tokd66fr5kMhcdC+Hdug=
+SHA256-Digest: JR/Qtnf+BXH9r9Utshr8QrwWuJnCW5/cyf7H0kMW3Zk=
+
+Name: chrome/content/noscript/e10sProcessScript.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: si+8sS7zxHuNbH8JeLRZdw==
+SHA1-Digest: GLHJKtkz7ddTPNHGyfMtad3Rxp0=
+SHA256-Digest: yuLT575dHh17aWk01AZszGemQLRQ5xi6GPnDERE4fno=
+
+Name: chrome/content/noscript/Entities.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 2WdF3QCjQN58N5eajkioHA==
+SHA1-Digest: dnhs1KNtgXcNOtIzsb64rVgqsjc=
+SHA256-Digest: 5mVDVhhG660/QJ6JPkyMg/JhFLYwg4fwfpIYa/J+4OQ=
+
+Name: chrome/content/noscript/ExternalFilters.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: qQdm4Wo2B3d5NpQNmrftsA==
+SHA1-Digest: ySmv2bXn93Zu+4RgQEhCZgzzfn4=
+SHA256-Digest: njHZ95cij1eEVzVRbpt+aRGvYCQNvFtfnwbjtd7nom4=
+
+Name: chrome/content/noscript/FlashIdiocy.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: NrNKDK6FRugi+VSloK921Q==
+SHA1-Digest: 6WHGdT4I6ryJXLptiTxPV3ARtwY=
+SHA256-Digest: UW1w10j60SuH5SC0OBFGLHcCTWIsr8fpk/ONoxGm6mg=
+
+Name: chrome/content/noscript/ForcedRedirectionCallback.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: S5jy1fUsSTHFqvgr4JVBtg==
+SHA1-Digest: b3JgRHZPXwoCJBjEoETlvgpaggw=
+SHA256-Digest: zRMh6dpUO4/z9Am7gYSvfHG/hPHYZPYDKV/qt9NcRMc=
+
+Name: chrome/content/noscript/frameScript.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: bnGK7aALxb4j4RSi2zP3/Q==
+SHA1-Digest: 1E9JvLF8RouOZDLjutanoVGkQJQ=
+SHA256-Digest: h4AIzIrBxfRAcVYuDj/hdhz01FgoWcMt3L3N1d6qN7Q=
+
+Name: chrome/content/noscript/FrameScript.jsm
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: s+VtD2rFHTMFe8unIGbtTg==
+SHA1-Digest: pHjAfDZXZyO177TatFYedmjj+JA=
+SHA256-Digest: 2tF6E5UB/fs3vwDUCWysLrsZn1glC5HPsdBqBhiF5x4=
+
+Name: chrome/content/noscript/html5_events
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: nF1Nd9LW3/T7XV4cSAsvFg==
+SHA1-Digest: Wbz7dR3TMbyam/TebrnGqAwQ+48=
+SHA256-Digest: 8yCeIgBFycYFKbq6hErVB8fbvCz6FSzpMKuMpP4ejoo=
+
+Name: chrome/content/noscript/HTTPS.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: /cyzmqBLYicfneXwqYSozA==
+SHA1-Digest: jFe3JSw478qy3wXJiNrtEOqf8yQ=
+SHA256-Digest: utlIKXkvCRarxVZo4SO8s9Z96wi3hPn9m0gYfhcPY9A=
+
+Name: chrome/content/noscript/iaUI.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 0SdkYz81P3l9vNhECHS91A==
+SHA1-Digest: hIrg9dryyyU0LBsLLYE7x2MfiHY=
+SHA256-Digest: KUgQZd3a8pZH+9fJ17j4wg52SaNx9Be0l7MFU5hG0+4=
+
+Name: chrome/content/noscript/importer.jsm
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: AWnybz+hGEgkww3VlFxD4w==
+SHA1-Digest: vV/i4cBl6Qs5UzSe4yaiD1+pyv0=
+SHA256-Digest: 9/HOHWehb2ckkcoE4wBvBwXdBH31rErokjRy3SOjcdw=
+
+Name: chrome/content/noscript/InjectionChecker.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: tOqdVfvcvM7fkUR7nNrpnQ==
+SHA1-Digest: vumi6LY5MzEmmzPYF2qUEBBh6fo=
+SHA256-Digest: hLjxCwY2k56xdbnJ0wIfHXZBbbFSzEb5Tl8j8ETo1x0=
+
+Name: chrome/content/noscript/IO.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 2hAtbcIUWEd36yrZWO0hFw==
+SHA1-Digest: SqBGSdTuxg4bi8JdY6IsnTmx5qU=
+SHA256-Digest: PCJ6ypTz68WMfmtIbcNw6ioHSTU/ZTnhrudF09lgHLE=
+
+Name: chrome/content/noscript/IOUtil.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ztwN89MIzIaa84Jwou6AHA==
+SHA1-Digest: bX5rvZYnX7QdPi+m26CbqT/FJVM=
+SHA256-Digest: X5zKH7qQaoqo1CPx6ezz9fkawHP7EhbNC7bQhrlUYQI=
+
+Name: chrome/content/noscript/JSURL.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: hYO96QfbFW1bI1KEgrUzoQ==
+SHA1-Digest: vRSeGYpYTbUPtQaoGPB8LZJM2R0=
+SHA256-Digest: aXlYy6Rj/h8AZu8lhYIHUPVCbx2UzDZYZPw0jCNdee8=
+
+Name: chrome/content/noscript/Lang.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: bsdKcw+PtrA3pBYl0hwK9Q==
+SHA1-Digest: bugJLaFxuzKGJKEju09MQpVgOlA=
+SHA256-Digest: LiCkNFoColrlCA2Qvwjip0RCMa6QAmucgOxd811UkpU=
+
+Name: chrome/content/noscript/loader.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: l2ZnKvdfRx7K3m/fbe9ALQ==
+SHA1-Digest: EHIpbRAhwoW5JmtYavHFbuqySe4=
+SHA256-Digest: nwq3wAxL+4nP/PYhwStM2JvjmzjrrL0rZR/UImVICKU=
+
+Name: chrome/content/noscript/Main.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 5/L6lHvekPp3tQJEYpXUSQ==
+SHA1-Digest: BMAyWC8q/oy3Jz0Ao0QcttkE3+8=
+SHA256-Digest: OOQ5COfjCGD26e+sVG+wgrfltdaa7dTxAY8gsfgguL0=
+
+Name: chrome/content/noscript/MainChild.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: UIJAhQsz2yuOe5g5sXcqBQ==
+SHA1-Digest: 9DpMA2IKvIr14dMbgGbX9JPcVTc=
+SHA256-Digest: GixQpIZvD49cZLD1NpeDmLzZ22ZbPeWcxZycGPv19MI=
+
+Name: chrome/content/noscript/MainParent.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: a69ZYCflsHCyx+ll2PuiaQ==
+SHA1-Digest: VRpE1g8cH6ybsZ4hYYSkN7F9urc=
+SHA256-Digest: 0tQzdtUPjlHLiWFhZmujEakZ6bgtJaUiVTFmVOyiImE=
+
+Name: chrome/content/noscript/Membrane.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 4wHyeUqmVY86J9fdy1aqXQ==
+SHA1-Digest: dFCj9xR1wMwvTH4cpxKzXEjrn74=
+SHA256-Digest: hUessxTAzyTLTSUoXf3hrh6fVBOV85/95HsEiXGs93M=
+
+Name: chrome/content/noscript/MimeService.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 9gO+HuxtLEpY9FZTTOAL+w==
+SHA1-Digest: aIQdi2ovmFC0+yt/ooMtVcb9BE8=
+SHA256-Digest: 21tY1SzDlYHmMAP1/SrSBFWdfZSfPjva4PB++0rLx7k=
+
+Name: chrome/content/noscript/MimeServiceParent.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 3EoZ+lq+3Sxkx9Rs0nrsCA==
+SHA1-Digest: g14nJ8e3gNDkDRFqY0ijGXSQCfg=
+SHA256-Digest: TPdlJf8l/BDqI0JswB2ysNA2oPKqtkjcPqfIyLT8Ic4=
+
+Name: chrome/content/noscript/MSEInterception.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: E6YSoryH9cN/G+g6m6ZSVg==
+SHA1-Digest: 8s1mjp5jgYsvCjUWbjPgSs12TME=
+SHA256-Digest: a6TqQA3Neuo/e1knRsdFT38tSpUCDZ+jem75hvNoC3Q=
+
+Name: chrome/content/noscript/noscript.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: qzPRTgI+VyqPB1C44IjxpA==
+SHA1-Digest: qzAwQnsxTCGMVs+tcDS4j8v3byc=
+SHA256-Digest: Zs7xVRBqeuuP8hvelIwikFjZv5NnTSbDnBzFJRxgBVE=
+
+Name: chrome/content/noscript/noscript.xbl
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: mlFomy1P+DrECC7gUrkgZg==
+SHA1-Digest: 22P66R0UqDRI9jPe3pDfCCfTtH0=
+SHA256-Digest: uPqbcq/k/rrxt/Qrc1R918UQ8fmYrLTE7S6uay3tBKc=
+
+Name: chrome/content/noscript/NoScript_License.txt
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: NrUoK6LI7vWvTkknJ6hgfw==
+SHA1-Digest: uqtHOuEANw0yaB8FG+uGsIK+NXg=
+SHA256-Digest: 3A2vQyyEOI6QqmVtaChNZejpsuojPWSs2vvO3hQ325M=
+
+Name: chrome/content/noscript/noscriptBM.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: dJQS7NKz7c+NS3nngCDNOA==
+SHA1-Digest: /ottZtpuwwLfcC7Lj6c7U6+V+zg=
+SHA256-Digest: DUI+WhLnmxlPE4Dj6YFXBCSxjAbj7RjUIfdvWcGNcD0=
+
+Name: chrome/content/noscript/noscriptBMOverlay.xul
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: aXhUS7jXvNeb8gWencVFtw==
+SHA1-Digest: ZNPYutqQUp0KUVekLkMHIEkKqiw=
+SHA256-Digest: j9K746dUerEruCDDpE3QAYI3hIv7QYspoZ9PTTUXq+s=
+
+Name: chrome/content/noscript/noscriptOptions.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Z4JkMiZxkzBlkNlWIwL5YQ==
+SHA1-Digest: RPIpEoIDTQ/9ptm+4p87Us0g++g=
+SHA256-Digest: Aau+8NXSD7dtmkOLg/si2ySLXx3s612NnDB1q1oXfmY=
+
+Name: chrome/content/noscript/noscriptOptions.xul
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 1BTqVjqipbVFoSCSEeTefw==
+SHA1-Digest: T4a9uqQZ91qFBGu9ZTSJVgC9dro=
+SHA256-Digest: j915w6SDPP3zyP7Mbcd3D8RDgwtRTAuZoX8noGrvXr8=
+
+Name: chrome/content/noscript/noscriptOverlay-noStatusBar.xul
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: jBh2s9fKFv3Pz07euE5NLA==
+SHA1-Digest: CgQ7ycaqTmegMZg4kRka3jT0AXM=
+SHA256-Digest: /UcvGeAqYsGPBhJF8qMl9N5k9T6qEIl7eouY46LvytY=
+
+Name: chrome/content/noscript/noscriptOverlay.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ts+Aoe3FcSow0WeTn3UjcA==
+SHA1-Digest: Nl0W7Y0K7/zxffC+3M8xmgsdWfE=
+SHA256-Digest: 7evmM9fnEbwy0C8adiXCKBBmBFuz4d3cxTKnaIC3oP8=
+
+Name: chrome/content/noscript/noscriptOverlay.xul
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: W7W6mDVSmDxM+gBmd1n+OQ==
+SHA1-Digest: 9rJwJmGusy/Bg5cqKSJKvY1LaiI=
+SHA256-Digest: 4G7mCzActJthc/GQiB5yb4vZfgAjFmwSk6sevlMWP00=
+
+Name: chrome/content/noscript/PasteHandler.jsm
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 0g0JgYbNwMT6jiI5YLdWpg==
+SHA1-Digest: 9+hAI73FL2VCLvMr/TnnY50eY1A=
+SHA256-Digest: kgeGLn3AV5W06UdsRU+8pdoEMzdm6YfMu1aFIvp/5lk=
+
+Name: chrome/content/noscript/Plugins.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: rSGF5A3AGXt4e1GXxFKboA==
+SHA1-Digest: TYWN7GGZVcQ2DdL2qgLdHzAbzv4=
+SHA256-Digest: 34oYBp7NJ9e13Cy3UEqx2mHZuFLO/gdn1Zh/QvD3NFk=
+
+Name: chrome/content/noscript/Policy.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 4L1w6nvn0ObcAoNa4WUQVw==
+SHA1-Digest: EDaqKnFiszHvQ4/kGGFl7gOs+Wg=
+SHA256-Digest: veqQu3r+ujnfk35vxldNOEUPrE5tQb5hm/yZlOBFtJA=
+
+Name: chrome/content/noscript/Profiler.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: X0QuBLQkAydLZfJx5djdhA==
+SHA1-Digest: s7kDNyVGtgwoLIDgVBxScm1BARI=
+SHA256-Digest: ga9zlckhOQt7ZlD9Xb/hfEAMpti3ijqP9GV9g2snfS0=
+
+Name: chrome/content/noscript/RequestWatchdog.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: XG5fZsqgj1JkygBQUErAyQ==
+SHA1-Digest: DZs9i9nhj38XO72GaUftxylBj3w=
+SHA256-Digest: D8nbPJOAU58hUmgbSSmefMli+1nUGw8l2oeTaXdMhKY=
+
+Name: chrome/content/noscript/Restartless.jsm
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 8ZHMTFoyd4ItuGY+SdYPLw==
+SHA1-Digest: vTxNTw2OMriYZ1dr35epKXP9BYI=
+SHA256-Digest: anM7ey8hEuaYPkBpu4Rb3Z8/xRKnpST6CzuhwFREvBo=
+
+Name: chrome/content/noscript/ScriptlessBGThumbs.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: W+HEtUS6k5za++bSAdqagQ==
+SHA1-Digest: G97emYsx9q8EiY6knedB1wFa2KI=
+SHA256-Digest: XCMeDK9aeHCFPUpd2qhB9WyDlqSteQGLnO5UdqWsu/s=
+
+Name: chrome/content/noscript/ScriptSurrogate.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 9Cu3LcsK65I4J9XNl8jtgA==
+SHA1-Digest: dYrS5TMApx2pJTFYZvdWFIc+XJI=
+SHA256-Digest: fAUJd0SIjtCtchG44G0JIM7qv3YwjGyLphs2U9N7Zfw=
+
+Name: chrome/content/noscript/SiteUtils.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: iObXa5XBF1OfopGIzP2G6w==
+SHA1-Digest: cB/3O1RLwCvJ9GAC5x57cp8hJPA=
+SHA256-Digest: JzHXKz1yNeuGsxGTOiHANKsc8sREikJ26VJBQbXVt6U=
+
+Name: chrome/content/noscript/Strings.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: MyozOK29iSPfcDLHVkII2A==
+SHA1-Digest: ltYRJ4foksAWkorfCfZ+xKIH3mE=
+SHA256-Digest: qr1q0Xki8hUZ8OMDI9qQOiWXfRKgTM82An1DU2xvPYw=
+
+Name: chrome/content/noscript/SyntaxChecker.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Tb+QaEGtSY7gwUmV7ZRigw==
+SHA1-Digest: i8VN8gDpd1KonEnLoC4ysXnWbWU=
+SHA256-Digest: Mx6sVgxYz6qUGPFBQhgwNBKAF55KIfgGaT8Vl4XtoHU=
+
+Name: chrome/content/noscript/Thread.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: /bV3WjuAKnu6QZcj86Dz4w==
+SHA1-Digest: q1qyz4vRDEKkQurdgEFqdG3FAl8=
+SHA256-Digest: FwJjE0imYrPBCuRczRoN1ZXPn92oIZxRqfPWz2fydA8=
+
+Name: chrome/content/noscript/tree-copy.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: mNI3Z5R90TOmuMXA4ZvmYw==
+SHA1-Digest: vrTKbl7kvlvqSFIRpUSyDDhFFVQ=
+SHA256-Digest: KSxPmi/GpPmQSwnXH/MjZtTSwUq0EpVfpA8Jt9qfgmw=
+
+Name: chrome/content/noscript/UISync.jsm
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: b4X0k8GAr63TnqowApelxg==
+SHA1-Digest: 9v+jxTQjCtDuH/e/6HaAFo8w/Pc=
+SHA256-Digest: 3HMZpNGL9xVV+JJACyIcaRWYbIRatvTCI2zh3aw6qRI=
+
+Name: chrome/content/noscript/URIValidator.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: YFxdlTyr0DoYht9BPJjxgw==
+SHA1-Digest: YW3PmH2KYhx4nVKuJjhROY3xv4o=
+SHA256-Digest: Rh/BbBKzJLiuL+JFz2BfO/1zV63bS4cwYtCb1DxQJMI=
+
+Name: chrome/content/noscript/WebExt.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: MlkHSClb6V+3b411mNGZvA==
+SHA1-Digest: Pztdh11GEeaUKp7q5KSUNpXtZyA=
+SHA256-Digest: MLH83TSteOTBx6a3svb7cIMNc3STPTs8u4bMUN4MAqs=
+
+Name: chrome/content/noscript/WebGLInterception.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: a6Iu6S0GJO7/c8PHY39zeA==
+SHA1-Digest: EWcy3hAGdffIQ7JvZMo25grEogQ=
+SHA256-Digest: 3SPp/rvAcAWw/AY2U7HRQfgtIuoISAWZeXg8VczhNSk=
+
+Name: chrome/content/noscript/WinScript.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: vhpD/sMtH20AD9ldNl9aQQ==
+SHA1-Digest: i+LJ59NAhmROaKPkIZPibPOqqfI=
+SHA256-Digest: JS9wdpUptTTaHgm8BHQsohjeRlRWhigraRpucybLZzk=
+
+Name: chrome/locale/ar/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: H1PKSAifSJINiJkmWT2kFQ==
+SHA1-Digest: /K3W0C89MEzSUSqYh0LrK/CWSho=
+SHA256-Digest: CZsH5S4TqgZLT97PdzgM+aUKEU1Ws38Rbh5fe2fygdA=
+
+Name: chrome/locale/ar/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 2U1f7LU5hk/vfNIujT1Xlg==
+SHA1-Digest: IVtee+zisGP2mSOY6J0sEobtjzs=
+SHA256-Digest: q8lZFjPEZ/r2xg6bO2wBdXHAe0aIruuO+gSR+84D5zQ=
+
+Name: chrome/locale/ar/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: yc6qbSo89koPtt5tSl+ZhQ==
+SHA1-Digest: 6DI1mqoVsx0OyVXVRIg+0PoZMHk=
+SHA256-Digest: IwO9FJRLXhKbMcQDMAsUPCEY2htKX9NFftlJQezTjx0=
+
+Name: chrome/locale/be-BY/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: +89rwtXZOfrQwhjW+7AhvQ==
+SHA1-Digest: 5W2yJAiktdXKrCVe+2M/0/dYgbw=
+SHA256-Digest: g//4vJGZ8Gzpi+F4dVraUvduymyA/lJv/FWAXSkZe5c=
+
+Name: chrome/locale/be-BY/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: a0Iyz/fbEgVb4sgDw2NEKg==
+SHA1-Digest: ifO/B5MkylnaNFkGWh11rExXJrc=
+SHA256-Digest: Km+Pkolfe4M2uEJ5P+IDN7oyl7hLq3SVF0pCzsq69D8=
+
+Name: chrome/locale/be-BY/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: FymUmD6hvANM/gX6oeFj2w==
+SHA1-Digest: 2laDWd2CkiE/0SOIVDWwPzkp6Wo=
+SHA256-Digest: gexf5o7CAmtEcGCcM5eO3uKO7OOhqNIUEDM0iHG4twM=
+
+Name: chrome/locale/bg-BG/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: f6zhTDFvZpey1Q+6kaC5PA==
+SHA1-Digest: sNaAoiFjfluUFYT3NJO8pa0cBr4=
+SHA256-Digest: 6740MI1Cg1lwZAhv9N8itevanKuMxU3IG1Cy9Kkvs9g=
+
+Name: chrome/locale/bg-BG/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: On5tl1eyO7jGFqP2ZqoyrA==
+SHA1-Digest: 7Q/dwLbEnIjWTrQuteRUlzuweDU=
+SHA256-Digest: tFtVHJ/ktMoDoCl16gqsMYMcGWyusz+E2FTbsrvoEes=
+
+Name: chrome/locale/bg-BG/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: hoNDl0XnK2mHluU4PdEmxg==
+SHA1-Digest: MIrwKK/Rtt3gqM35sZbuatCIayY=
+SHA256-Digest: D4ExiNp9baXa9B4+hsQOc/wGsFOl9n6DbbUeBim6DL8=
+
+Name: chrome/locale/bn-IN/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: qrhfTzVSvcCE931BTILOYg==
+SHA1-Digest: P0fryPQLGhuFt0wFxXF3+YEEv2U=
+SHA256-Digest: 9cEFxtzutFREKs+he03Nui+sQSyWmbKR7sChJoA+gjc=
+
+Name: chrome/locale/bn-IN/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: F0d4Ik0rdLXo2QbfKzskQQ==
+SHA1-Digest: hqrjaUrKCLlj3CSWKlzp1CnW0rY=
+SHA256-Digest: eAjNfkMm5btyS0gIW1eRmgnQfeecGfWuIIxhl+qnEXY=
+
+Name: chrome/locale/bn-IN/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: lQp8YOyxyUmxKWfFBbrL+A==
+SHA1-Digest: 2/4o4YF2mkIpjUK/+KPMuoN61Oo=
+SHA256-Digest: HAEvRXW+mn6/xukeXJ0WZwzpISRcFaf0nRqEKcxXAL4=
+
+Name: chrome/locale/ca-AD/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: UKFgmCzaZmkBDhCKAX85hg==
+SHA1-Digest: kflYT0pG5PkXqcxExu1I32CKtmU=
+SHA256-Digest: 9lPk2vhVBFlaB0euZrdG4+AHbNRICeT2Dpg9QkheabE=
+
+Name: chrome/locale/ca-AD/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: VwCw/FgnNJDQ6xHnQD9/yQ==
+SHA1-Digest: SIzlGpAPawDey8Ed/oeg3HX17yI=
+SHA256-Digest: ahgBzv6+FRyqKbBOlf316g2+5fAKahqU6kHF55ObjAw=
+
+Name: chrome/locale/ca-AD/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: yf6zNmAtEIMd7m5Ok/vE9g==
+SHA1-Digest: Fgo09p4vT2aSjAxLomriywwotrk=
+SHA256-Digest: FZcMJaEcsxwHlz44iBfSdCDqqqi8ATnKXv3PsCDxU/4=
+
+Name: chrome/locale/cs-CZ/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ZohfG1V9zYBVGXp6Yg7Bfw==
+SHA1-Digest: uvHG2IX5kUIz3oj8KZ9WeopZNvk=
+SHA256-Digest: 2ZydfWtv4/xAbsz0whNy1m7o1ZvetfOQI5bm98GTWSc=
+
+Name: chrome/locale/cs-CZ/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: lJnTe7TBV+Ed6ND9VsJDzw==
+SHA1-Digest: 2LsudJj/x4HIFcUufVaUNOm4pqQ=
+SHA256-Digest: YJoPwgzrWNytO5/5F2MVdTA4h9xeEQzRHSvL1Qbavnc=
+
+Name: chrome/locale/cs-CZ/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ZQSn4Hqjp7HBmClwRBVnxg==
+SHA1-Digest: os7eqHw+OshvzlncEYZgZeKFvzE=
+SHA256-Digest: QhyP+2r37DIvq04nMga9VyYc18QR4r1gesr8CMMuyro=
+
+Name: chrome/locale/cy-GB/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: MXEXlCoWk2aroypJvAqimw==
+SHA1-Digest: QJMBA6MQxw4D8NcGjgbaRU5RMn8=
+SHA256-Digest: x5MjjJzBMaoOHuPvSa57Kj6f51NOF4h8LJqY6EZWAfE=
+
+Name: chrome/locale/cy-GB/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 2GMOb8XfWA7b8lLietM1wA==
+SHA1-Digest: nW60p9VfTApX8lJKQPZ0q2cGca4=
+SHA256-Digest: GEgLZj1VPCL5yycwaSTLHB4Gt8sCgWI55gJlEnXVITQ=
+
+Name: chrome/locale/cy-GB/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: OvQCCDBXtO563Oq1tnNCuA==
+SHA1-Digest: HlIYQJHBpKaWMpwLsynVJ6og3gU=
+SHA256-Digest: OJX8MExfdzBc/X9suc+7I+xMyvoJvk4XhG83Xl2yYgw=
+
+Name: chrome/locale/da/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: DrzXOK58me0lcL/k9sdprw==
+SHA1-Digest: pbxJdqyMQHZfqpXhtN51RN56DUM=
+SHA256-Digest: e5lOd8eaPOviTDvcWczuo0NCdMeNiRGc9+vfRZVW3W4=
+
+Name: chrome/locale/da/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: R7wsUtn3urzVR3jdG1czfw==
+SHA1-Digest: 1loNqC1eoY01snEcFLjjb2qqk0E=
+SHA256-Digest: RSElhgzyFq4u7Vi4APfg42VVFvuADQ4B9cWHtlqmql8=
+
+Name: chrome/locale/da/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: GT4TkKi58qri7UKJrn04Gw==
+SHA1-Digest: PopBTSMk+2tghsjLdLkaWXrrYAM=
+SHA256-Digest: DwroelTeEKQEIWzegjHzoVTp//YPV61U40b9Y5XjCHk=
+
+Name: chrome/locale/de/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 6IOkbstO9aSpxtpNTM+PGQ==
+SHA1-Digest: UvqiVC7ZhZNpetUZ3sD5OmBHshI=
+SHA256-Digest: DUF5gLFokgSA5458U7GEqYT68Gujlf0TGO8h/DHVcPY=
+
+Name: chrome/locale/de/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: JHFKmi5yHWkV/hzwRb7C7Q==
+SHA1-Digest: Xsk1gWU7YJVB7qJe26C4G2tmPyw=
+SHA256-Digest: xlDZ5H+slVjyxnKMRxbWFPwXVPUvmM6td+6AoVCghQE=
+
+Name: chrome/locale/de/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: h2tpAyxUYDHfZX0ERbBuXA==
+SHA1-Digest: Tj2PGnoDafwxOxZb2RNMNJZ+9tc=
+SHA256-Digest: LgVwi7+4ZgeTvpZtuAWUg9Ms4XP/D+5tsVPkIEfqLUc=
+
+Name: chrome/locale/el/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: BF1Mg7Q6eTCuWBsgxaBcCA==
+SHA1-Digest: FzzY/kDgk9oB/yfhbthUH+3K+p0=
+SHA256-Digest: og/I26jifCUCQouL6sYdt6POVJTcCpbdWTEQTRfz0yU=
+
+Name: chrome/locale/el/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 9osQ/NFDJXl1RR9beZVFZw==
+SHA1-Digest: rgwybGubdVnPcLAV6M99xn99W34=
+SHA256-Digest: LyGgnsDTUeBYpDNyycg57vJ9yYF60xXg8uaFkVZrlsI=
+
+Name: chrome/locale/el/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: A/q9G4KcKD2PTXCq5S5iwA==
+SHA1-Digest: Hatkut+2NECHRpfm/BYVeJiDcNk=
+SHA256-Digest: 9CaXLz1nbNj4DqPNoSQmETy1EvR5AS7KhrFeZgEKk3o=
+
+Name: chrome/locale/en-GB/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: +CSdXzAU9jS9h21t8241Jg==
+SHA1-Digest: HUexKIcNtXuADoCrQga0QJQJMlw=
+SHA256-Digest: Sj/7BUrfvKlTIID8TWpPNCsDBIRodyRLwuLQ+hoMp1U=
+
+Name: chrome/locale/en-GB/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: eIumWJPAcAA+g4k+xV8eMA==
+SHA1-Digest: LjgTyELXCiQjiIxSuhzp0sfPmi8=
+SHA256-Digest: Si/yEcvAu61qdZWqvBVb1N+IdtIMHVRW/G+CeYxaMNk=
+
+Name: chrome/locale/en-GB/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: QP/FmXAKDlfffh+lWjXW2w==
+SHA1-Digest: Nj+4nUtJoD97LlN54cJjACl6Wwk=
+SHA256-Digest: Jp32aSpL1W/8jdssNKu2SwuIa4/yKHkwmE70k0GyV58=
+
+Name: chrome/locale/en-US/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ZoKJKHADt2VViRef6nKdPA==
+SHA1-Digest: wPgAT8TTe+fOk2o/kzl27p7hiEA=
+SHA256-Digest: Sj65nMnALJAMd/V1qeJwKqUI+5qnuGWcIoAPISENkBk=
+
+Name: chrome/locale/en-US/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 1xplDcHrn5K0e9pP3cJCgQ==
+SHA1-Digest: zkYbOar+RtbXnuGkOa0siGjqsuo=
+SHA256-Digest: 52BLn0RR2tIF7YXjLSEFBJatSkzd65NBElWNK5+hTfg=
+
+Name: chrome/locale/en-US/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: CZ8M1LAPbCqZ8/Y3oauzCA==
+SHA1-Digest: GtYY21vVx85hnhzaVArX02q55rA=
+SHA256-Digest: aEBM65tg8315ZBwdaJdufqUb7QB5R4NPKlzH95BMxXQ=
+
+Name: chrome/locale/eo/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: S/Z7AzGHaDJ0/rChoZDFrw==
+SHA1-Digest: wImWq9Q0F9cVLKYccfgHDGULZUw=
+SHA256-Digest: DHLeBRSiIHFw3HydqFrHhMcOoIC+ziqIYLNC7jrx414=
+
+Name: chrome/locale/eo/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: D3sT7KUTsmH3KdLLb6hpEA==
+SHA1-Digest: iYUMIHFWrHxuw6oOsh6BIhTplKc=
+SHA256-Digest: bWTYV3sTgWDwykCHaS+aAYazIVYePou5gi8wh6+eEqs=
+
+Name: chrome/locale/eo/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: K99GqN4Ib/RBgjToXE6UOg==
+SHA1-Digest: NslegE6Q6HVCQbPvBH+4TCak78s=
+SHA256-Digest: 6idd0PZpd3AVlrkPrrdWWedfliiZ7XaqKOlr/PDpQNI=
+
+Name: chrome/locale/es-AR/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 8KW0EyIf3MaZi7NoI2wXtQ==
+SHA1-Digest: OdCbf6/mUi60G84lQxF9xvdj2i4=
+SHA256-Digest: sJR+OWzZICSFIlFKTReOonlk4ttAWzNfGx1d4e/8uU8=
+
+Name: chrome/locale/es-AR/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: FCXVDo0DPFc4f9ZUaf/VAw==
+SHA1-Digest: OcenHi1ESyFtK0n3EWORumundJY=
+SHA256-Digest: k8RLk+DlfUOTwfMwTIZN21MRlean/e/Yce/pfHBGvnE=
+
+Name: chrome/locale/es-AR/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 0AL+YlaW5VpWkG46RPL+Gw==
+SHA1-Digest: 6dI9hyb14CtyOz5lyxxPnc5rRiM=
+SHA256-Digest: p7Q15HQsr9VWC5RSUS3vheuHHHQpiH/1bMBaaqGfhZU=
+
+Name: chrome/locale/es-CL/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 9gezd3zNEEndj84MC/WpsQ==
+SHA1-Digest: bANkMTYDxZWaaM8hLQZ3kFpkazo=
+SHA256-Digest: Au/e7ll4qHzZzc78CaFDlYIB50nS8DWTp1I6L/2Shnk=
+
+Name: chrome/locale/es-CL/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 9zGMdTehqTkFc7XF86/s/g==
+SHA1-Digest: 8jvjykVoKcYBwJt+UNxDZFFJ4oY=
+SHA256-Digest: O2ETyZbzXTOTAbGXGmPvP/NQ+Gg4Rm/M7EZ+F8PvPgk=
+
+Name: chrome/locale/es-CL/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: QP/FmXAKDlfffh+lWjXW2w==
+SHA1-Digest: Nj+4nUtJoD97LlN54cJjACl6Wwk=
+SHA256-Digest: Jp32aSpL1W/8jdssNKu2SwuIa4/yKHkwmE70k0GyV58=
+
+Name: chrome/locale/es-ES/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: BXvY0gQZ1ZiZM1wdsfQRIg==
+SHA1-Digest: VfTz8hfRFURHfliKGnVqXQxXFks=
+SHA256-Digest: 8ha49gMtX2/24xZX8EyS67200flRazBx56ZhBHvp/1g=
+
+Name: chrome/locale/es-ES/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: kEYuz84mjlW9TY0+mregTA==
+SHA1-Digest: QA75DJY5RdOynEt294fJ5s1xKpw=
+SHA256-Digest: oe+7KCJ/U8bgCcyjteprS2TO1zLZcWkCjNlTpZ7CAq4=
+
+Name: chrome/locale/es-ES/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: +8AU/KTj6vjTjBE1S78I6A==
+SHA1-Digest: 3+oG4Ph7qFyVByOcawLcqoL9Vzw=
+SHA256-Digest: Ox+1Z4pijwPsAOZk+u8eS+BMC7juWKWpeFhIeemig1k=
+
+Name: chrome/locale/et-EE/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 9BwVV5d6YStKdj0qkZqA4Q==
+SHA1-Digest: tLipgYuD6A9JdnK6tunUWzslLaM=
+SHA256-Digest: L2agPsc3QnCsZ3WbuDwoMRe/Bi8QfxckWVKGLUlbcgU=
+
+Name: chrome/locale/et-EE/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: COJkq+TIV5/otiVFaoonyQ==
+SHA1-Digest: Fy6yXnBXQOUmP2fVLs3pDhFnLAI=
+SHA256-Digest: 5gIxUaEAsXv9i5V+4Wxbv/r86HM2jysRWxb7doZTRwg=
+
+Name: chrome/locale/et-EE/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: rxHLWcrpSUulgTTrO1vqPA==
+SHA1-Digest: qtOYlqQUzfeOxHXPhHoemGxXZCY=
+SHA256-Digest: Y7Bq1o7XCi0mK5XXxzex9ll5o2trIXuXlW0FM3tydnY=
+
+Name: chrome/locale/eu/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: CqIZnweKuwvypJIIBYeupA==
+SHA1-Digest: f2/STGGGc0EN5ASWPXXelE41f0g=
+SHA256-Digest: lPO/vAzcDeCkuYALsR+5iFspcA4sYczD0UB9N+QP1Do=
+
+Name: chrome/locale/eu/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: KLOdg4lnTp6SCUq+t532mQ==
+SHA1-Digest: deuvyvQTGOKnT8cLfGAU5JM5q9E=
+SHA256-Digest: w22e+yPMF9uEzaetOJLaEgQxY+2n7OEQtAXMiojCQKo=
+
+Name: chrome/locale/eu/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Et0vWb56EGwqyO4W2Kcu4g==
+SHA1-Digest: +yGbzkSg1YVVpdBWFAVx8P8Tlnw=
+SHA256-Digest: yLuCVv/jlHGTX6syr5gNzaES4rg0dwJlHtlJV3+M3/E=
+
+Name: chrome/locale/fa-IR/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: CRleqD8ui9NDjS6bxlO3aw==
+SHA1-Digest: azpjHw2wj68uxic90eEifEP6hdk=
+SHA256-Digest: C04AXzOMuvkYYsV7hn1WH34AB6OZRHPsWXsl3iHa+E8=
+
+Name: chrome/locale/fa-IR/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: G4gbU/90iGJO01AhrEjZDg==
+SHA1-Digest: ARM5t2RsaHQVHgbrW6H50vQNwtw=
+SHA256-Digest: lcHfRX/w9BpJrsPhe2ZmTbO40Jms/tX230D95jcR+O8=
+
+Name: chrome/locale/fa-IR/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: h95q04R3M5qJphPBDgBjEw==
+SHA1-Digest: pgb+e9Vdxvl01mAUG13j6d0l8vU=
+SHA256-Digest: p6q8IUhVtJFxlpcADWYtcBwlyUCu4nhKqvOL+1mqmk4=
+
+Name: chrome/locale/fi/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: bf8b0UUoDNAIE+xB6rCjJw==
+SHA1-Digest: zn4bfaSGlqZv6201f53lOwwUGig=
+SHA256-Digest: Fr62q552jpDAKvGvq/rP1K3RbU429SVXS316mnnSv2E=
+
+Name: chrome/locale/fi/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: N3d754gV7X1LcreZPbakeA==
+SHA1-Digest: cx2DiG9LlJeoBrKvNJU8irI8La0=
+SHA256-Digest: roX2dJA87b3SkeCaeJlqsuEMWl2TDxQ5/kzw9vDoN8I=
+
+Name: chrome/locale/fi/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: W9DkCOmjx0rHe4g4VW+3Hw==
+SHA1-Digest: FlotcegAzgMdQvY3zz49Q/qFCYM=
+SHA256-Digest: 12qxmBfINwn2a6GbEyxE8acE+K3WoRSigH8wOkDkI00=
+
+Name: chrome/locale/fr/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: +QJInwOz5QuNlYyPZhtf9g==
+SHA1-Digest: /jz7SZgj4l8NBAXZxNUV6YvNmq0=
+SHA256-Digest: 1QCCcmUGrhJXBcL1vVNkoYDwBFkK9+i3ZNwHUj+X/Vk=
+
+Name: chrome/locale/fr/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ddBOh06QxsLw3xyHIGoWSA==
+SHA1-Digest: fmCHjhUGFx8hzgrp/TIElP+Zx2A=
+SHA256-Digest: hwc5hhpE9b9ouzZXe/J7jtnnB0ZbbVQvyN1PpesQ0l4=
+
+Name: chrome/locale/fr/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: QSK3y/AA+jvfQ6K35tOPNA==
+SHA1-Digest: 8afaaPEYTO0BVQZNgPtohONX8X4=
+SHA256-Digest: AfcwSiyzysltYjE4NP1ypte3Z8yF0lOHiaPcNBZKUwg=
+
+Name: chrome/locale/gl-ES/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Hfd5dQI1GI1c7kpJ6mf4ig==
+SHA1-Digest: LU8wXSphmmd7qv/nXZxsmy5/VZ8=
+SHA256-Digest: yacfb07d8bxtYPxL3+/F393oiZX8bF/K70AgIL39NTg=
+
+Name: chrome/locale/gl-ES/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: d8afwErhDhB6ZGku1ZiQSA==
+SHA1-Digest: uNuRuMbO1LTaJSeHEUo7iZ+ALgk=
+SHA256-Digest: zbAuuSA+css6rVrTu/JfuaZl9/rbbtqppCs+a2CkL8k=
+
+Name: chrome/locale/gl-ES/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 8stLsT0WGzmH4qRFcDGp2g==
+SHA1-Digest: mhqbObtTFcMJmtqGClLpt/LNwZE=
+SHA256-Digest: DTzBt0iZrNRgnvfTdbdfg6pNf1ryI+Yt5nzJQT8ltys=
+
+Name: chrome/locale/he-IL/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: AYqLJ4TnQ2CvsXJGolWr1Q==
+SHA1-Digest: s6RAVGXfmmTceVFCjTgg1rFDnr8=
+SHA256-Digest: 0oDlQcEE5TTKwRx7JJVX/q4F9FQg78wnLPiHVWOo4Bw=
+
+Name: chrome/locale/he-IL/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: TBPadXyBEtMI5iCl+VRTlw==
+SHA1-Digest: ybnbl1KtExxeO1lmUsmE8OoDjZo=
+SHA256-Digest: oVyYRgGML39e03x88wP+LWIjsXq4pD1b68nXP6Jgbkw=
+
+Name: chrome/locale/he-IL/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: jb7Pk48eGYo20s3+Y45uBQ==
+SHA1-Digest: kw6n+H3tXZgMKj7Ditic4nEFUw8=
+SHA256-Digest: uvuL5Nypb9OFeavxQ1ePhh/ZyTkx5GCQoFzgjRFJglU=
+
+Name: chrome/locale/hr-HR/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Rc55SBCw09JoulETHfySpw==
+SHA1-Digest: wV5mzFilGjLReuYFadHBNBuVZ4k=
+SHA256-Digest: GTOC/VYjOgzNvTlLMj3Xe4H3b8Hp/thwhw9PzNb4484=
+
+Name: chrome/locale/hr-HR/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: vcnyBzZbkgd0iur05jJLng==
+SHA1-Digest: sxv6rFAKNblaL2wIIoXHIcoqVqc=
+SHA256-Digest: AgfQCieWd1pLBVffTHaCzl47gBWLNrYV755YA+1PwhY=
+
+Name: chrome/locale/hr-HR/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 4Dz0Sces9f00qBhsAZL6/A==
+SHA1-Digest: SGs+Fp+lAShR7E2rVvqA7QOCMgA=
+SHA256-Digest: oKOEnf5fCdhpmW5GiSL92Pj9nFXEqKATN1Z6FYKEu0s=
+
+Name: chrome/locale/hsb/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Vt1vthMN/qcBznPAuUhJPw==
+SHA1-Digest: t5wMEPVua4wuGwBHf97L7FLdbwo=
+SHA256-Digest: fcoAxTwCK29HOwBsBBJ6wOHexDnXaqPz9BD4tLdoiIM=
+
+Name: chrome/locale/hsb/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: wtE0rCHBsXs351FkFRQpiw==
+SHA1-Digest: 4bFdXhKBuMRGCHTHppgYphkh/PM=
+SHA256-Digest: TahyLHJRvk05o2Lf2EOIK/jyUrTu9WQzlN2B+27ViLY=
+
+Name: chrome/locale/hsb/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: q/b1/QkLSpKnqpWGYfb+8Q==
+SHA1-Digest: Rho5W9w9+K5OYgoW+u3adAeQo1o=
+SHA256-Digest: avTV21Btm6BJ61GspQ+dCPjl2jlRvUYfTtmq63Ts2Xo=
+
+Name: chrome/locale/hu-HU/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 6NzsPuDmHvMxkv/PMXkSyw==
+SHA1-Digest: vZzf9pMQ/01ovCpCdaHSAOBoH/o=
+SHA256-Digest: dsebe/iGpQ5N4lcWbKlZo1C66Iw1P2Jkaf7HHpYtQSA=
+
+Name: chrome/locale/hu-HU/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: tMqWfth8jfmr++x1iVIjcQ==
+SHA1-Digest: e4ClYrpz2B4Fk5Iad0zrSaNPsbs=
+SHA256-Digest: KOIEaVc/+RIj+ENPPTktlgNT6Ly3KxUqtUn/NLNjvJo=
+
+Name: chrome/locale/hu-HU/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: JInVFA4SDRjsMmUc2pinJw==
+SHA1-Digest: 5wKfRsWj4cPf6UqKQ5QOMp3OKQg=
+SHA256-Digest: ntgngxpGEpmwXO+J9y7CJjxOzRPoMT8GmjdfjMlV1WQ=
+
+Name: chrome/locale/id-ID/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: dIBzeuFCGHkI+bwy+WQWVg==
+SHA1-Digest: f98lOBm8U6bwxWqz/51Ntq5SNxw=
+SHA256-Digest: hKvL4u2hMuglNLtK5JN9JKCDMuAhpLu86KlQcX7Agks=
+
+Name: chrome/locale/id-ID/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: pjwjOCmlq8IOJpqlL03pzQ==
+SHA1-Digest: /eBGLOjY491GOPwV4TYFZrKq72o=
+SHA256-Digest: w/CZxPoCuE6m+XjkxTurImtNm1V/kPmAp1hhPjFZU+4=
+
+Name: chrome/locale/id-ID/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: K11SJXlrD2oK1dVH9UDf9g==
+SHA1-Digest: /9HT5W6lGw9URqV2kmkmtc3tetU=
+SHA256-Digest: sJHKWaO7i/j34lqs+6yxTVY6E+vfazTcT8SkhePgGJY=
+
+Name: chrome/locale/it/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: szDseo8MxbOjW6+DPGnYRw==
+SHA1-Digest: AXC2nbKZGSkqbC8aIXiPvcMJImc=
+SHA256-Digest: M8aFexond3EqjkZUyz9hGbXsEq5a93y3pLB1F6ViPbY=
+
+Name: chrome/locale/it/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: d03Iv4lBgvOkoaAsO0991Q==
+SHA1-Digest: G5JshftKhyyU3E73TAEOWSkusZs=
+SHA256-Digest: Lop6Fp+AgzlucRRR24/MhaMJMQXGWmpOCs1DEK7Pt2o=
+
+Name: chrome/locale/it/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: BiVf3r8pFuU455fYwCBkFw==
+SHA1-Digest: a7v+FOXRlZKf1ByfkP8jLcHEeWk=
+SHA256-Digest: 4AISh/ag2i8Yr1olIqopywlYPpuYOx8V8hQF/Z3F3BE=
+
+Name: chrome/locale/ja-JP/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: izSJ0LVy5QeQc1ZnNAYc3g==
+SHA1-Digest: sta5MoQ0XEGJhUl65YPJ5hdtt1A=
+SHA256-Digest: 5WtVw5cLO0au1XxeaII7h6FgMqOzyNOqgJPwhyz2b/A=
+
+Name: chrome/locale/ja-JP/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 6ONfOrgoRUhp0uTWERDosw==
+SHA1-Digest: pW4hQvPvdtly43Zb4PPo2gV09Dw=
+SHA256-Digest: ptH4Yp4uiWG2YDBHxZK6zsZgbI+usYZxNWcjgusf8TY=
+
+Name: chrome/locale/ja-JP/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: a1gDYiLBbDmaZRUDjY0rfQ==
+SHA1-Digest: ZNx9R4ns9Pb0OUPYgUbDFylyJ7k=
+SHA256-Digest: 1N4Pev8pF4zFGTg9r1OgYF4NiMlHbwfdPcnHuq30rT8=
+
+Name: chrome/locale/kk-KZ/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Pwhp59mc3uryK2XdsGBkeg==
+SHA1-Digest: BmojPYZwczyr7siGSTqMj6PRlG8=
+SHA256-Digest: uoFj0scjIAVDcN/9vLd7qMcvIu9cNYl5HKNsmnZG65Y=
+
+Name: chrome/locale/kk-KZ/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: cQwz8tWjNRF5tQPx02QTvw==
+SHA1-Digest: APSg0ashzFftU+yXQ8RXQZvGuR8=
+SHA256-Digest: I9lgKM7VvABUL2z9prC7yZEgulTzMp/SBx06boF42L0=
+
+Name: chrome/locale/kk-KZ/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 1hTry8cyvchu3IEmTmhqqQ==
+SHA1-Digest: BWs/bEhLLZqXv+seod3VWVYQDEo=
+SHA256-Digest: FptV9e/wEdjySxJbSsNpAHAz/p3J7Zl2p2hmbRGntL4=
+
+Name: chrome/locale/km-KH/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: arC5tu88LG5dzNvh3JzUpg==
+SHA1-Digest: mWY8HPNe6NqhGrPI3JdngLbbah4=
+SHA256-Digest: SOJhlYwtUV5oQGdv2JBzHH6JL0xAIKU1De9rO8eCUY4=
+
+Name: chrome/locale/km-KH/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: +UL1C61lY/xANfQRqkhfvQ==
+SHA1-Digest: HUoje2dQ1eT1XveYPsss06Fjtdo=
+SHA256-Digest: ZxheaBRhSJi+42EAGtGvziIDCGiOyK+uOapk+uJFklw=
+
+Name: chrome/locale/km-KH/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: QP/FmXAKDlfffh+lWjXW2w==
+SHA1-Digest: Nj+4nUtJoD97LlN54cJjACl6Wwk=
+SHA256-Digest: Jp32aSpL1W/8jdssNKu2SwuIa4/yKHkwmE70k0GyV58=
+
+Name: chrome/locale/ko-KR/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: UbEUA1rLa2BQWzMR0P1Ekg==
+SHA1-Digest: 44MXu+9gzxhh8ayl4eczJepe1W4=
+SHA256-Digest: m4y83twIYwCuBJTOL7lIoS/ekc6aO7vq2wbJB2GycTQ=
+
+Name: chrome/locale/ko-KR/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: iLtdMIFmCSdEK35XwIFSBQ==
+SHA1-Digest: JV1c3BixKKypTCVhZF4B+WP54+Q=
+SHA256-Digest: o7Sb/qHenHQCal7rgVDaJ7ibVhHUMrtFw93NtqyHLOk=
+
+Name: chrome/locale/ko-KR/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 5W7sHdnExiPFD7eA/CXdcw==
+SHA1-Digest: pp74TNV1gPPRFvzo+sqtht1bp0I=
+SHA256-Digest: LaUPicIsDxQhzOzLF5loVtN55mKcZZ75JEVQUPMszzs=
+
+Name: chrome/locale/lt/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: v9lKh/yScY1EQW73mFr1uw==
+SHA1-Digest: OXJotNTKa+qW3KH2xglglsfyXps=
+SHA256-Digest: 3Db0Z+GGylf6p5PvpiU725smiOylagH8hyG2L1WhuvU=
+
+Name: chrome/locale/lt/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ytdpFOZFzmVPOqMV60IRLg==
+SHA1-Digest: RdguwjPMy8meCbLb49gS/mgOHks=
+SHA256-Digest: pcQAdLE07xUgSd/dqMEqnDzcsaUEmhMH1U/p4naz3KA=
+
+Name: chrome/locale/lt/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: jBHT38IRXAMehyGCrRPrrg==
+SHA1-Digest: mJWPsIs6HV/crEaPO01TQmiYrSg=
+SHA256-Digest: mg4Cqb37K4GWeAf5CVNeu2oZj48nhVNzH6vJcUdvLWk=
+
+Name: chrome/locale/mk-MK/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: sRTwduQrLC2elm6/tMrrYg==
+SHA1-Digest: FK2I4LKVCMG61glufAEd4Xu3AHo=
+SHA256-Digest: qLbEHCgiOHpYhr+3cIWPlm13WxU40bYch6q8Qa12ZhU=
+
+Name: chrome/locale/mk-MK/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ylFzkYydGEHLX1+J4XQMNw==
+SHA1-Digest: 3x3eaCmAt9TBULWWwISQyrgpFwM=
+SHA256-Digest: +R8+OFXpsi1THXudfsO4d38i1uYQcFI8Ez9/IiIHO7s=
+
+Name: chrome/locale/mk-MK/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: jI8rRBovIPTac+ktFjJFJA==
+SHA1-Digest: hGS0Vyk3mXbPwfvK50hP0IzUBjs=
+SHA256-Digest: N2r+P7YEn0N5xzzQEXCY8NSzf/TxcrUZMITG50+Pz/U=
+
+Name: chrome/locale/ms-MY/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 28gVoE/v1KgD+hLErzqy3A==
+SHA1-Digest: cfSmI7vUD8EMK3m2vZPKZpYFDPU=
+SHA256-Digest: pUrEVF8U4TJU/Or6IWVA2ZK23ZdwOZXaca+xcERRqJ8=
+
+Name: chrome/locale/ms-MY/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: gzu/sYHq8wAmajcefv9fww==
+SHA1-Digest: V7RJMw2G3PzkJQDn13tbXXauxXI=
+SHA256-Digest: se4ImTB3ovX2OyF+gyzJdUrLNiwRhx698YQcBDRfH/U=
+
+Name: chrome/locale/ms-MY/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: pu2mAKh4NQQaLZUeeQQsuA==
+SHA1-Digest: Ji5AliCrnZzAqpgzcLgj1NoME5U=
+SHA256-Digest: 77L7/Q1LEIJ+iqpGNYwCzSIIruJ6yHOvMToZSyLwVlg=
+
+Name: chrome/locale/nb-NO/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: vUI3CZaZlcKs3sNWkRembw==
+SHA1-Digest: wVO4Zccxj/r0+ZVVvg8Y4t2tE90=
+SHA256-Digest: p1+Rmsw9SvFmcaXpYdL+5gXLpWsvYndCCgClVs3wwuQ=
+
+Name: chrome/locale/nb-NO/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: qmKAsO1qYTziQ7G0RGHMsw==
+SHA1-Digest: XLNMeOXVt8yjMGZ6mP39Qf9hbbM=
+SHA256-Digest: yS4pSWDvJ3cRInLROOuEGA5oBCst9CPl30Cda09S1io=
+
+Name: chrome/locale/nb-NO/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: hEAqGqUJbCyitQ02pKOM9g==
+SHA1-Digest: gNM3Vs2LIDW7k+lWSblXq0E+op0=
+SHA256-Digest: 4TvfijYT7S9C7bdxbmAo2NRR6oJBeWGZoHKjLdrv/xs=
+
+Name: chrome/locale/nl/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: IL6Os5f6Eq6wF3SF7RSMYg==
+SHA1-Digest: ocnQh9+4tavoFD6kFCm1NX/oBRY=
+SHA256-Digest: ugqpp/m6s4FFu96B/Gwnn3Eo+2Egn4dwewfLooRMUtA=
+
+Name: chrome/locale/nl/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: evFADt+3V/QHsWw2XY6iVQ==
+SHA1-Digest: gdZrf4uUNETUfB+EZidQzN1+WHI=
+SHA256-Digest: uJtF0UZIXmZdtBU4Rd9h1KXb/74fkWm6207SRzhwLBM=
+
+Name: chrome/locale/nl/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 2smuk9FUoTWNtjgxFS1d7Q==
+SHA1-Digest: LxO+XDYXy2e2j4XyIrt4EzLYlSc=
+SHA256-Digest: C3MKJKEcu5cD5UuUgcmlmP442DfI32GDK7v9N/K6tvI=
+
+Name: chrome/locale/pl/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Uql5SPnPNu3hkYRzqIljEQ==
+SHA1-Digest: I1Att5q7dUDdAIbhroTZi1FZ0os=
+SHA256-Digest: SzoR7JZmHRL/OJtz0TQG7UDVnxd8Y2E4f0Sw/eI0cBw=
+
+Name: chrome/locale/pl/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 4pOKAH/IZVtNqyC8F/g+uA==
+SHA1-Digest: Qq1G43q/bNKrEErzVTPBJILdE5s=
+SHA256-Digest: wmTiGyBqII+HL+Bq6fNTaR8rv5qdQG5Jyz2jXtJpWBE=
+
+Name: chrome/locale/pl/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 5K+TDT7X8FxlP1Kw98tHEg==
+SHA1-Digest: ET6zSsnqQukB0aiEBGzVv2nW6IM=
+SHA256-Digest: EudX4BLezkSg2BPG/1R2dsRQpnHJu2OSvHl7Lph5eXI=
+
+Name: chrome/locale/pt-BR/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: UmO5kXFLjjKk5w6EKCZHVQ==
+SHA1-Digest: P9ocXE7IK6wNPXiIr51c2D+MoXs=
+SHA256-Digest: EBLxujlksYGtH3yGkIen3RyjLtJfQjJLkW5rW91TtMQ=
+
+Name: chrome/locale/pt-BR/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: PLGvk54og6EyIQgWn2YvPA==
+SHA1-Digest: NcQ9Yuqs33W33L3MiQZnDzZ+C7Y=
+SHA256-Digest: me5AhwhJLzZgZdd5BZDziwmpwzd+ttmZljOuNIcmXmo=
+
+Name: chrome/locale/pt-BR/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: uQYCa9+dSGFPrkNoi9ZjLA==
+SHA1-Digest: fui0pcq8tjeTVcd0AwsgpkW9knM=
+SHA256-Digest: MZueILjrqIS4zgAOobeIhfyoAWRYzl/9g6x4pwVFe/g=
+
+Name: chrome/locale/pt-PT/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: s6ho5LRsvRJRFA7mcyHvhw==
+SHA1-Digest: F5Gzudwcvj9tdqcBsxGr0efxB6Y=
+SHA256-Digest: 9bxsf3eHStOUUuzp35sK30CmeGeeMXXdRj+tzsKsj20=
+
+Name: chrome/locale/pt-PT/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: blLSk1kzXHsmW5EZQVxmtw==
+SHA1-Digest: eUYHYbviLa4zCYw7ibMDaL+nUYo=
+SHA256-Digest: wpDUh9AICsDScmWzvBmFBlRsjC+LdyRTcpF/2oX5SG8=
+
+Name: chrome/locale/pt-PT/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: hXHrlQAqv63bPakGIYEc5Q==
+SHA1-Digest: GgB13LKg16EatfkhWM9kTxXyeMM=
+SHA256-Digest: AnNpV4xAYciUETbhUjdCDliHzkMtXG9zgRFbe3SEC9I=
+
+Name: chrome/locale/ro/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ilHOAJFL6Bf7eqa5Shcjgg==
+SHA1-Digest: 2lcDUg+dqYSX7FOY4prf39S61Uk=
+SHA256-Digest: LJ9UbUGXOBq7T0ZEH2N8L4tS1NHapwlQct7bsqKJUIM=
+
+Name: chrome/locale/ro/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: i0sLtIoVAqPDLWt5kkhecg==
+SHA1-Digest: Yjz2+gGjR9uaL/UvWJ6W+Pxzk7g=
+SHA256-Digest: erTGwZJG+qDxxLF2bbKJeek5x2Iucph2SooXSU2j+2U=
+
+Name: chrome/locale/ro/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: KP3Ol3CPFfbDBN+iRiUrtw==
+SHA1-Digest: vOXXFTge6zyVKxC6a+D+Nkhsr1A=
+SHA256-Digest: xPkgaYe5HfUdSJZBCQQ81rlmvnG4KZ2HPKcNSWh0lEY=
+
+Name: chrome/locale/ru-RU/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: VsiZXvHvwkTZxFP6GMyijg==
+SHA1-Digest: xyqr0DbphSybwqbSZvhPCInLzTI=
+SHA256-Digest: tiBf2wy3PJsUIpU2M4v+J5xzQH3/rJu+0RiIkjLatos=
+
+Name: chrome/locale/ru-RU/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: jB21usZBNIGJ9zOBHYFfbA==
+SHA1-Digest: XgSRAOb9ii5jBj5vdId6WW/I/I4=
+SHA256-Digest: i+zbdyL3aevw3mEBUq7GZzcRS8rlvFqsX4wHw3CuaDE=
+
+Name: chrome/locale/ru-RU/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: eHwJPmJC0f/Fs4oGjJ/PVw==
+SHA1-Digest: s3g723rGtfC3HhfFrpOqwEDdj/s=
+SHA256-Digest: ObdECT6VNpeRLrc2TYmvkVfvcOUx5G8JAdVnQRQzyAI=
+
+Name: chrome/locale/sk-SK/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: DTOsXNuXy02Z+OeTxo6reQ==
+SHA1-Digest: l4ysX3tnwlN4hCoasmYaODXXcoA=
+SHA256-Digest: c/R2coGZLAsEkgqXo0FTmndTSzE59w70XIeDnX+C7bE=
+
+Name: chrome/locale/sk-SK/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 5AVgTT4RV0lGr5Pg28edJQ==
+SHA1-Digest: 5K8N447EIS+mpbebx6ilYwIWhDM=
+SHA256-Digest: RIKBXZakFo3MwSDykDzncSXCPgSi+nybv1/K+Wxv7NI=
+
+Name: chrome/locale/sk-SK/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: u40X+ONY3NpmRNtNHIV0MQ==
+SHA1-Digest: CRpnMkmBXjqu0J5b2OOQNXYDvgE=
+SHA256-Digest: K40URBsebDaTFr10b3RoqmLq9JuQGnqTIheuuS5d1+4=
+
+Name: chrome/locale/sl-SI/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: +Fp1n7MCKptDGPk4N5ekwg==
+SHA1-Digest: vyVw61FTz5MIKLbhdN0RhokcOFQ=
+SHA256-Digest: fmBgCpDkaopoAx2hHc7xMTasuC6Zonip7O96Q/VFy/c=
+
+Name: chrome/locale/sl-SI/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 7oQqCidq4YqPaSiccsCAAw==
+SHA1-Digest: +5O1aoHNnMmzeSU0r8dUSqAhNjs=
+SHA256-Digest: H3tNvsBYBJzqmlNu6t5DHq+BRTPjvW94HxAF0rvoRO0=
+
+Name: chrome/locale/sl-SI/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 8UR6eGM49h6rR1g58PsAJA==
+SHA1-Digest: 4WBX7GbGXB0cEzsnNqniCUhfXDE=
+SHA256-Digest: hkFJXhpi4S+Z30eqJzTqC/gfShsXp/w3sZ8hLUmKtL8=
+
+Name: chrome/locale/sr-RS/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ArWtVmqV5m/TENtQxzog3g==
+SHA1-Digest: pzRQpOrfox3yFbjBJA7q9RxkUCI=
+SHA256-Digest: mjObGIW3TAyXeZUB7UOvAITtoAnwhDRWQseyyAyqWQk=
+
+Name: chrome/locale/sr-RS/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: TbMyln75+odFQFAlUBzCXg==
+SHA1-Digest: MDl+Hz4Yr3cXKYQpgZJ4oFmRxe4=
+SHA256-Digest: gCvHdUz2vSd8w3FlFkUzmChJggNrhxmdHfrQlQvYgP0=
+
+Name: chrome/locale/sr-RS/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: R7qjNI1sctQOaEELCW3aPA==
+SHA1-Digest: 0g5kjBBz5T5O/QnJ/vWYDHyYQOQ=
+SHA256-Digest: wVdclXBomcFKerTCA2/0jlZrDwK9APErqVJ41IwzZKo=
+
+Name: chrome/locale/sr/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 3egQPOWjhe4oIgIaplqajQ==
+SHA1-Digest: 4M+KBXnUlLkFiRm5/VCk5JcVYg0=
+SHA256-Digest: uew1UkLb1XFGvbfiNj85Lwhs99T7KUja/OQhHnxhqZI=
+
+Name: chrome/locale/sr/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: bmFZyWKqlSP0E/kxhjAAng==
+SHA1-Digest: HWChgJ27GtLoH89heRMhWHXuqaA=
+SHA256-Digest: CW25ABPPYhHxa9Ox8P07qTKA5kz84EiwjuEI0YB9fJ8=
+
+Name: chrome/locale/sr/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: o0jGlTyP1EqtrDWOoUbCWg==
+SHA1-Digest: bHjibEMx7a8sYd2cPgaZ1BqLVkc=
+SHA256-Digest: 8q/J3TL8MAPCC1o4jsoxkd701yGDBLWFsfqec2p37H4=
+
+Name: chrome/locale/sv-SE/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: bwgJ5Z7Js12HC2H3F5yp3A==
+SHA1-Digest: DZdGzRyvtAVDdd+ieOShWPb/K/w=
+SHA256-Digest: KyB3GeXhm7MpYnlpyd2TetVUI5zIVDqhsWLQ8/jOQqI=
+
+Name: chrome/locale/sv-SE/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: j5FTljNS2rzJL3prfzOMrA==
+SHA1-Digest: bfTiSbiXYjIWuQGJPMmZJeAgf4k=
+SHA256-Digest: 4RNAl29NxeeJvAQRYtBcqyBOZRy6Ic+w4n5ctS4J98E=
+
+Name: chrome/locale/sv-SE/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 8NSTEhjbNsg+f+6msGOk0w==
+SHA1-Digest: OxaqRO2BfywQiNjI7QMNzHuLQg4=
+SHA256-Digest: 9Rr1/1MI3CzUV3I+1KjW7RcAfz5cqzjfCShGjDn9qeA=
+
+Name: chrome/locale/te-IN/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ZoKJKHADt2VViRef6nKdPA==
+SHA1-Digest: wPgAT8TTe+fOk2o/kzl27p7hiEA=
+SHA256-Digest: Sj65nMnALJAMd/V1qeJwKqUI+5qnuGWcIoAPISENkBk=
+
+Name: chrome/locale/te-IN/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: TtOo762skWbBup/kVFM7bg==
+SHA1-Digest: eONaiEsXjXN0sl2CV/kiFJUhrTY=
+SHA256-Digest: rbJTYqsvrpf4z+KR+OkZXi1DmvKxYefeLp5ZkrhWxMI=
+
+Name: chrome/locale/te-IN/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: QP/FmXAKDlfffh+lWjXW2w==
+SHA1-Digest: Nj+4nUtJoD97LlN54cJjACl6Wwk=
+SHA256-Digest: Jp32aSpL1W/8jdssNKu2SwuIa4/yKHkwmE70k0GyV58=
+
+Name: chrome/locale/th/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: eypIbD8OKD0tEP4O64ZZ4g==
+SHA1-Digest: E9iNrmms3GPVPG83auLwHZhc3Yk=
+SHA256-Digest: 9D+xpeTdbtuzSAP7lPBeI2Rbnn+tWaMj+W0erMLHoks=
+
+Name: chrome/locale/th/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: H0jpRs6MmBDvLsrAAJM/rw==
+SHA1-Digest: f65mZ98QKDi8dsZ9RxFCUW3kPVs=
+SHA256-Digest: Tyr67UtSl92ZB9om93RCv/7LYwLrPAZxYbcIlMa3E54=
+
+Name: chrome/locale/th/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: NzVoVshcHgW0f3LRvQRuPA==
+SHA1-Digest: bf1hx1Q0HDzNKDry8AAAuHiUR6o=
+SHA256-Digest: /Br3lKiof8r1KFZk6eue6jnfwtKHenosy/9iGCiwJS4=
+
+Name: chrome/locale/tr/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: KbBsReUK3st7rNTqOHe4LQ==
+SHA1-Digest: fyquCmWmcvO+XAQZEpRKesve1qE=
+SHA256-Digest: +BvGoM2Uzt/zMoFHc2Dh4KLwS9Ian8V7qtjeqEXvtEk=
+
+Name: chrome/locale/tr/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 3IQFz5cp59haBdLN9oev2A==
+SHA1-Digest: GtRTSIOUtCp/kEZFGmJLeA6bp6U=
+SHA256-Digest: EpGjzMDI1v5l0WPAOtK5asvo8NV5IEuqj2TjwHSLXBA=
+
+Name: chrome/locale/tr/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ot1hLB9DoW71PyiXyFkVww==
+SHA1-Digest: dczb+WKyFxrcqGAkzPi12qxuqY0=
+SHA256-Digest: 16SU3B6YUoWR/uuzKajJVAJRSdn1bpC3/gPpcwGlqus=
+
+Name: chrome/locale/uk/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: fDaihgpC54MKtv6HB+zWwg==
+SHA1-Digest: YBc/+0+tXAETxynjV0pXTEt27sU=
+SHA256-Digest: XCyLpQmQ/r1cn3QCEl1S0MeNBbvuHW1HNgNkTUR57Wc=
+
+Name: chrome/locale/uk/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: +DmcSlze2BqrGiyYtPm6uQ==
+SHA1-Digest: HVS0G2qzH5Z/6nKK5Bu6dJelb/s=
+SHA256-Digest: YLs7+/8YVfeUS0itA8D9rT0ejut/9q4v4tRq8CozLTw=
+
+Name: chrome/locale/uk/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: qpdNhUWpcL8gzBoSroACPQ==
+SHA1-Digest: 5ferDUbNbx2gZhsm6n6u3rsClLc=
+SHA256-Digest: 08sNKxqeWPAa0WRD4gq6o3LIMWE1n2tl9VUBWOE3Ldw=
+
+Name: chrome/locale/vi/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: oZD3KvYI7IFj9Of/X8rBXQ==
+SHA1-Digest: jJ2uCXM0ppagHEC8Zga3rBAHiKY=
+SHA256-Digest: Eo8pavp/LLFAmLmDmC4HIwkXqltgOWoDFlVYGjZyWyw=
+
+Name: chrome/locale/vi/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: O9bmJyRHGWSuFkQQgW+6bg==
+SHA1-Digest: B5XTwXX2e8dloL1FCBapaxgIEKc=
+SHA256-Digest: lR8QAAbbyTrh0Vj1gFfJLNNi6PFqW/fN3LGpE3uF5ng=
+
+Name: chrome/locale/vi/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Vyua3WALJO3EUT5tmqMY9Q==
+SHA1-Digest: BWXzlOeddOOnUDV7tBGbgtCgZwQ=
+SHA256-Digest: 4+CiDT1LhixTnekebgxQWWKxr9ohc7mJuaY4d9kL0CI=
+
+Name: chrome/locale/zh-CN/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 0Ys3EBssgf4cIC6mjb60hQ==
+SHA1-Digest: sjSFXUWhoyS0AL/uEOcWbEWXZiA=
+SHA256-Digest: dMo62pPWxlebjT/0pY3GT7rU4eA5UXqmMTSdLOmR57g=
+
+Name: chrome/locale/zh-CN/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: +J1kwMk8mVzy/LxON0kxxw==
+SHA1-Digest: ABJSuHMZBSjhjcj6ninU+ajqEO0=
+SHA256-Digest: MujbjSR5NPjLjbrNcKr8Shk8AHvkHAMttgrGxkid/6E=
+
+Name: chrome/locale/zh-CN/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: zfgTg2f+Qm5pcEXiTfs4jQ==
+SHA1-Digest: x9GEl7JhTNKAUoIXOaJupBRF4pY=
+SHA256-Digest: yRkj0LHITRJ+OCjrMuLTaO885Vx1svH4DsDC+3s2eBc=
+
+Name: chrome/locale/zh-TW/noscript/about.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: qwt33RzCUTiTXZvmcHDf8A==
+SHA1-Digest: 0ezRfaXTFlZHSTxEUFVH9gh3mvU=
+SHA256-Digest: LsbfLUS5jH8GhNHBVHJV10xWOTlcIH54q1eRTULDxik=
+
+Name: chrome/locale/zh-TW/noscript/noscript.dtd
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 3YmM5dhrCgUJ9nZjt/bMxA==
+SHA1-Digest: NYcTVgiACwoiQsTTJ0s5Azi4BB4=
+SHA256-Digest: Q6w7t5g6jMnLtvtk9YJ+jAs7oQYgH6D+Y1erqzvbkVc=
+
+Name: chrome/locale/zh-TW/noscript/noscript.properties
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: t0xF0hHxMmdB18iuEE4cyQ==
+SHA1-Digest: 3QXYyZytAEzFTVho3145Ye5rFOo=
+SHA256-Digest: qy5ppekHqAL3YZi5+3NofGxedMhxaLb34xS8k9cddWo=
+
+Name: chrome/skin/classic/noscript/abe16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 0f+bdIdPfO1uFdtXgFBbhA==
+SHA1-Digest: RB623q5qAo65/aMou6xvwUMqi+U=
+SHA256-Digest: G0dLXK5WFX4wiX5JODClH2tyYQDqX9LXybRiiNGoVcg=
+
+Name: chrome/skin/classic/noscript/about.css
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 1MPIjHChh9OWf9aWdVMmyg==
+SHA1-Digest: 5lk9kwULwBF3gR7uiAnzoFF9/jU=
+SHA256-Digest: /hCxJ2MT9a9mq6oHXcudiVdRMbeb+4R/LZZCN2U9WFA=
+
+Name: chrome/skin/classic/noscript/block.wav
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: SCJJyOYc5akoQVFI56ilkg==
+SHA1-Digest: za5cmy/DJGXu9DW+Co/WxBtUpkA=
+SHA256-Digest: tu7j6yFQgWkF8heOtEgbTlqrkmZQsPctx+Z2dDRYrqE=
+
+Name: chrome/skin/classic/noscript/browser.css
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: D8HX5TmXFrDK1/EQZFrtYQ==
+SHA1-Digest: DzJMQq4BfmoDeiE5VLwL9TD6WKE=
+SHA256-Digest: /ssGFWdeXUUjsQ+cE3k8SYPxKHWIGgQRsuujGHtd4jc=
+
+Name: chrome/skin/classic/noscript/clearclick16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: TWQDE/JsNJRVOlWnBHFP4g==
+SHA1-Digest: XsrxYjqTKj9b1JCgG4HyVUUzj34=
+SHA256-Digest: qs0IZY0rpzJI/qV5J04SrKyxnKI+RlvCTqxgDyZ9ZHQ=
+
+Name: chrome/skin/classic/noscript/close.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: TkLZGXGKw4XYQY3+bT0MtA==
+SHA1-Digest: tznx4NpA9+9lriTn0rAqkEpWdJ8=
+SHA256-Digest: ILTWy/i9Xet+dc457XAj0vNTp4cF40PtRY+p5Lu2As8=
+
+Name: chrome/skin/classic/noscript/console16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: PAK2Xy8ruVh0NFyfOd0wQg==
+SHA1-Digest: c7Bl2/EInjObDE44sleeUFby6A4=
+SHA256-Digest: nyqIUCmFUYv2CnlBr+tqvaG3VAYrB1soU8Zb6U7/VLM=
+
+Name: chrome/skin/classic/noscript/content.css
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: aLMp2piT40CZx9itXLnJQA==
+SHA1-Digest: rcg7GeeTSRscbqD9i0bNnzLlkvw=
+SHA256-Digest: AbpHGcgLb+kRsJGnwFEktk7uzpZOCcBY74+YBdrKVGs=
+
+Name: chrome/skin/classic/noscript/ef-no16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: jJTPkF2tPRZ2dcBcqyPsag==
+SHA1-Digest: s317Fbkaj/E9ucnjtyD561eFj6M=
+SHA256-Digest: HBoIN1LKjTzM6xb0Rgok798+eXnqQYY+ygCWWqNiTlo=
+
+Name: chrome/skin/classic/noscript/ef16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Rqe/Tc0UM1BU2XmUkJht6g==
+SHA1-Digest: sdMWRMgZNPyd/32/cBIROVowYaU=
+SHA256-Digest: XRPBuCdiO5S4ukgObOqzM5NyRymwKZN2EGGcILCNz2g=
+
+Name: chrome/skin/classic/noscript/emb16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: CMe0tPLNKuX+skyDU2um+w==
+SHA1-Digest: xJnZ9yX4etJAtu0xuaD9H69AZuk=
+SHA256-Digest: NFaIS9AM5/J2Hk7pwTMLMVAqsrLZtmndt3AfI/f8MZ0=
+
+Name: chrome/skin/classic/noscript/embed-no16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: cU45j7BMCURITH0nHCzOwg==
+SHA1-Digest: WXFW1BuRCbzWPcS7sfv71rVY9gA=
+SHA256-Digest: 4BN1HtuttUvI34SQSYHiNRKHcFocb72Y4E4wM2PjL5w=
+
+Name: chrome/skin/classic/noscript/embed16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: KULnY5e+8KI/mqQazSmLIQ==
+SHA1-Digest: pvP2VYjt64aOK9zVZZ6T9e+M09A=
+SHA256-Digest: roKJTgUmlRgMK6mIlENgyxM58mto41zyHAutMVJpCcQ=
+
+Name: chrome/skin/classic/noscript/faq16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: MpUKBKC453oz9QY8MhBBIQ==
+SHA1-Digest: +EjhrthD7OBY11S16UyQ1f6EEuQ=
+SHA256-Digest: YnLR1j4+BvfLwpxhy4rw6kD3ZVcjXGGhKemS19k9hZs=
+
+Name: chrome/skin/classic/noscript/flash16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 2IpsSirB1gG7wqLwcrXYMQ==
+SHA1-Digest: lr/3auKH5yCcj3LyVegycONxnCk=
+SHA256-Digest: 5YWL2qsKxHTYlvMx+BhpFY12Gz4zrUEAAR7nQCj2YUs=
+
+Name: chrome/skin/classic/noscript/flash32.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: JwLF0gihiQIOEecRQaSqcw==
+SHA1-Digest: z8FAd1a5h1mcCt8W6hCtiYL+ldw=
+SHA256-Digest: UjMN+zZ006uqHANdT36KpF5ztAgYn8NoPX8X/llI9gM=
+
+Name: chrome/skin/classic/noscript/folder_closed.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 4ef9Iz5mrAT2zygkVmeTXw==
+SHA1-Digest: 6PH7XQbXtVW2ed4k+tIbc9+vPJI=
+SHA256-Digest: KtsVo9cqx9FZSvXByKFgtwS+ATpA7L0NNJv1iBGrL80=
+
+Name: chrome/skin/classic/noscript/folder_open.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: X6JVyiimYkimzxeroFPFLA==
+SHA1-Digest: WJoJe9XfZ3zjDrapRQxMyJnTbMc=
+SHA256-Digest: I8gUrNC+c6tqOycPIg93X/5CWdFzW0WpjCw+aUFkffE=
+
+Name: chrome/skin/classic/noscript/font.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: +TiQ5UAQGwDFRfmoD/u7Og==
+SHA1-Digest: Or6k6bN7ELAIIhyMaa+fMnSPM8Q=
+SHA256-Digest: bLGzy4WgiDbnb6xb7WfFYkm1L59Lxy0mMcvn4PKVaVM=
+
+Name: chrome/skin/classic/noscript/glb-emb16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: N+LGGn6ydTJNVSkyLr/x9A==
+SHA1-Digest: MdE1+cAzk7lRtzPGui46jGki9nY=
+SHA256-Digest: pbDyp3wm2aCAEt3nQ+Ly5TmFc7NYWlLDwW/VK5sllfk=
+
+Name: chrome/skin/classic/noscript/glb-no16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 6krWUZjF2Z/5kjMR1w+hDg==
+SHA1-Digest: 2jLhGclozC/YpblZ2cJQunl3AQA=
+SHA256-Digest: lXjmx8IUhQ+NoNoXAEQYHJ/4Y/gQPtgxvMDF8wr4Im8=
+
+Name: chrome/skin/classic/noscript/glb16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: M/zJCYV0NKNnGDHp8NOm7A==
+SHA1-Digest: 8pVzthWEQ4DebIR5hCIAnpHrtmc=
+SHA256-Digest: K90GUM6KRPSwKzWLLz+8oSn3ZYaA1nAQCOE2njTcv2s=
+
+Name: chrome/skin/classic/noscript/https16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: tQhBG7kV7PMrGplWRPZ/0Q==
+SHA1-Digest: wetnhKHS7U3IviBXlN5QrMMUQBo=
+SHA256-Digest: Eu0OHP8LLuqZooqkceOqxeEf781WITMkmi0Aj4zm4M0=
+
+Name: chrome/skin/classic/noscript/ia.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: BW45jkS+1GVUP0+ktkxpDg==
+SHA1-Digest: AqtXi1oSu0JKRaJ8qJ/hO08rYOg=
+SHA256-Digest: xUf15v65GBd/giLfuA4qSNZucPSMkvSTcYzkcPaWFaU=
+
+Name: chrome/skin/classic/noscript/icon24.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: qkqpz7b/dF+TP3nxGESiPg==
+SHA1-Digest: gWBiFN8s6OO9VpUdYAGb3PQhppM=
+SHA256-Digest: E+c0Ud2jt/LJYsmmLkEbROCUVvcaLfw0Y7BwudGreQk=
+
+Name: chrome/skin/classic/noscript/icon32.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: TyT13x7d2ICAOf5/jYmrSQ==
+SHA1-Digest: PXFMgKtLr5ZBMdDGutZF99U+1r8=
+SHA256-Digest: xoqGNUsUMRMi2D6qHK5U6mg5wZJXzjz32jMELSeUGXY=
+
+Name: chrome/skin/classic/noscript/icon64.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 9Nyu7MseegFNNFM6Fho+NQ==
+SHA1-Digest: 8u76tleuKt2aS2ruFeQf4kMZA0w=
+SHA256-Digest: hcC93v9Tr297SCSnmEHfys8YkkroiHCSs4ohycNBPEE=
+
+Name: chrome/skin/classic/noscript/icon80.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: dBC2O310i72jx/quDynuSw==
+SHA1-Digest: 0nGihMU+0lIdq39JYBdlNZ9iPIQ=
+SHA256-Digest: q3nbuON73TbuVJ8ePuNqaFIXyQt5/8PwQZBMTmZ80jU=
+
+Name: chrome/skin/classic/noscript/inactive-emb16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Hq35ZRPbDBi/E+z4m3KyKw==
+SHA1-Digest: hstCFcFJLr36IHrbBhFFM9YK01M=
+SHA256-Digest: aYJ3P+4PVeeKE4XV7QhQJN0VKRxnlqDbgks3wrfKPgg=
+
+Name: chrome/skin/classic/noscript/inactive-glb16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: m0imn5W+oosnl107Nw4f+g==
+SHA1-Digest: NdapM14Hdlg/QJCBpsgrwtTMUY8=
+SHA256-Digest: R6JkaKZivrYjoRS8U8pGg1OsZFr59YzoNvJHo5wBcuk=
+
+Name: chrome/skin/classic/noscript/inactive-no-emb16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: fMpFvXo5WabRchDkRa4rvw==
+SHA1-Digest: LWHu0/qUMQ2VVvhIYQRyyS4436c=
+SHA256-Digest: TvWzveTqG8Mi6M6FiP/if4ryS+73unOz/w5wzH2slHo=
+
+Name: chrome/skin/classic/noscript/inactive-no16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: R1dXxebA7ySOzkAtP1cRGQ==
+SHA1-Digest: ZkFAxpzL8JthezttTm30Hbvm8Bw=
+SHA256-Digest: qvXuDbhVvAB6LqG2PWwZgZe8NeMHcMS4JzKhJEFV3fE=
+
+Name: chrome/skin/classic/noscript/inactive-prt16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: mQ3YgCDL44fkAqu9B8CumA==
+SHA1-Digest: YPY60PNmFHcnuBCnOVODEPxhq6w=
+SHA256-Digest: rHcDUnR/5tD0efKwNYPAzpc7gGWMMqTwpgZddWKDBW8=
+
+Name: chrome/skin/classic/noscript/inactive-yes16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: vIzZMJL8Nsof7Cca0u2kPw==
+SHA1-Digest: 0mJfLrwltFMaNv/EwNHbkpGPao4=
+SHA256-Digest: WeCjQtOTD4tZOTmqcM8ySo7d3GUbBcLXI16H2ZwKLVY=
+
+Name: chrome/skin/classic/noscript/inactive-yu16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: TFM92jGymhmMyPu/kO67hw==
+SHA1-Digest: eWCzmsCA1mmkjl4b1Q0klWMpkaw=
+SHA256-Digest: 0ozluQStaC27ADjxYoI+CuBDnf4+ewV7bDPYvpb+RIU=
+
+Name: chrome/skin/classic/noscript/java16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: l5UDE65EnU4P8X1TRbYeCw==
+SHA1-Digest: oHzM1JgDo2Jt7XT7zF06wKQGWcw=
+SHA256-Digest: 7Lff/zR2zMxNC88GcUssE6/xWBxVSNFzKLRBrMCKkKU=
+
+Name: chrome/skin/classic/noscript/java32.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: kSJVrI964eUW2o8xFmiPLw==
+SHA1-Digest: S8vRlvXg5ZrbqqCUmDq0OR8eMfI=
+SHA256-Digest: 4IlvmjhGDRtyVN459Xr0KKCEFt1zQFrx4NYzR2T4Wp4=
+
+Name: chrome/skin/classic/noscript/mobile.css
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: OCrfctAyT5DYZ6cu8H86Vg==
+SHA1-Digest: CelWssvyrxk8yP4ZatWluE4nU8U=
+SHA256-Digest: 1TqKXVBqg+ZUcfJQT5u/EZvjrXVdXoqp1tFikz7SMnA=
+
+Name: chrome/skin/classic/noscript/no-emb16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Fj3cPAlpjn9O832ZYQO/Jg==
+SHA1-Digest: NFJ1+8JIuRUw151rkgVeSpMJMGc=
+SHA256-Digest: vkNcjFQgwTYTJ2s9DClZ6RsC+/Jo3uTHfMudsS2S0SM=
+
+Name: chrome/skin/classic/noscript/no16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: gF7wFJgdhwKZB043kabTqg==
+SHA1-Digest: wsJg1UJA8GphN3T2pQNQMXrJXXw=
+SHA256-Digest: vid8nbHQ7YO1ZjLJ+Cj8FvAPJZTk7C5cPKPn5EG2FEw=
+
+Name: chrome/skin/classic/noscript/options.css
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 5w8XPppFGwnUYj7pN0oBnw==
+SHA1-Digest: Dk97HTts5IJXzikKI9HT+sQGWAQ=
+SHA256-Digest: fHOu9djBSlpOIzl4YqhsAh6qcNMpDg5L+VMR3LmVGl8=
+
+Name: chrome/skin/classic/noscript/prt16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: XsdDzRdnzfektDPVxv1I5Q==
+SHA1-Digest: dHcupNg1iu8GKTQnf/sGdy2yFsk=
+SHA256-Digest: 4JimTywoJtJN2aA7nnO1AnAWK9By/X/r8cPi14sxOTc=
+
+Name: chrome/skin/classic/noscript/redirect16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: z/a8dZt2Sz9Wrfe9w7TBew==
+SHA1-Digest: tlCeze/q3jK2eGYzY0QOnrAqwjw=
+SHA256-Digest: 5E1JiZQDCRma0ZIAIuU6gksla7fzSfHW4zUG/Z4LFms=
+
+Name: chrome/skin/classic/noscript/revtemp16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: OAleBT8i+szAuEBNr53K7w==
+SHA1-Digest: auU/g7Q5HU1T8YIxIqjSxDg3G+8=
+SHA256-Digest: RoRZ9ESGM5szqLHKU9o+UkgimOeLsoJNy/iS/ctdEzY=
+
+Name: chrome/skin/classic/noscript/somelight16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: sNyoXggVSSeqfpdTv6Hp/w==
+SHA1-Digest: sdIy9gGO3Pbu22wY3veyDtkjD1Q=
+SHA256-Digest: f5TJQtDPn5rlsw65/ShBX08PCv7wjbFvfIWIKPLQSbE=
+
+Name: chrome/skin/classic/noscript/somelight32.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: Au+xOTpCkxWNbNW4lumbCQ==
+SHA1-Digest: n8TRra7qvQ158d0J3y9nGt/MpKU=
+SHA256-Digest: K1EjDp0E8ut7q+CdyWhizOA2bSJO/4F52ftgiGVd9RU=
+
+Name: chrome/skin/classic/noscript/subprt16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: sgsF83Gi2DNMeVl7fUv7xg==
+SHA1-Digest: +CJm4XGeyWtqP9eyyxWoqK1K+8k=
+SHA256-Digest: lRfmvpBDF8X29+KWybCXT5yfnYRTKbC+iKzVg8n7Ssg=
+
+Name: chrome/skin/classic/noscript/temp16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: z0q06ZGVudt+Vl0n9UO6Eg==
+SHA1-Digest: IY2adCJpHRyjgnEy6mL4z/z35Gw=
+SHA256-Digest: 9kIyJfkG2jh721YSt/Mq8kwig629athmAOVSDiv+pAc=
+
+Name: chrome/skin/classic/noscript/unsafe-reload16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 33iqjAKVgpb7C5Bm+zKXSg==
+SHA1-Digest: Jlr8lKCf/uNheGEinVeDA7d5xlc=
+SHA256-Digest: wSbWntDiFaDOAOddyJfDaR9TItYGfHTLxTEj4cNCjOI=
+
+Name: chrome/skin/classic/noscript/untrusted-glb16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: mDLS86jeeVn50JRTuMG94A==
+SHA1-Digest: 1sijE/rZb6vR+S1yfA0zV15zpOI=
+SHA256-Digest: 7ObpyHxsf6nf6GVNXuXJe/RzkHAB5vf76nXJfIS3FNY=
+
+Name: chrome/skin/classic/noscript/untrusted16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: JEsRIdBt3iwhan6FLkhZ8Q==
+SHA1-Digest: 4SCHyq35CqfBK1SDH7WhaLbTo3M=
+SHA256-Digest: hsDhzhJEPebWTDTf+LAF6G4vPvkvkdu8qXlJg5RrNgc=
+
+Name: chrome/skin/classic/noscript/webgl16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: VRUPaIbuURynZaPMR0ZAVA==
+SHA1-Digest: 3mQrEiQJRdKBWPRP2SSE2IAadmo=
+SHA256-Digest: SMKB4rFraurwHUn4mF/X0pj59s20L97mRamW5qRNhZI=
+
+Name: chrome/skin/classic/noscript/webgl32.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 3iPpUsRRcJY9f+4xznrRhw==
+SHA1-Digest: C//hQnK6q0MVEcBFUIIOJRYbRGA=
+SHA256-Digest: aOjlFiu4UAkrYtxgExTJ8RgHZ4zf0ZrgfTPk8sXkqZk=
+
+Name: chrome/skin/classic/noscript/xss16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 54Jqi87vh4HZLf5YZOrl6A==
+SHA1-Digest: ajw3R0AR/lFuuqozv7ZYSsmpXds=
+SHA256-Digest: oFucPltQA4SYHVPFOqHik0nMWY74dL9uTe5wagzLCdo=
+
+Name: chrome/skin/classic/noscript/yes16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: RiOPi9ZQo/Jard0RJNa5VA==
+SHA1-Digest: LHEhz56GvyeX92yncOWI8SjcwwE=
+SHA256-Digest: Ku6pNnHMitqev944T2tdTqouy0dyzMWCYwhdo1G08Z0=
+
+Name: chrome/skin/classic/noscript/yu-emb16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: NImpOQglqYFcQP4qNSEpuw==
+SHA1-Digest: fJswbEf+m5sFdsH6FulUwbSCg+Y=
+SHA256-Digest: jgv1aLqz2ottcbjGypsaoimr6/lxmlTIDkjjIdqrJFk=
+
+Name: chrome/skin/classic/noscript/yu-glb16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: t7oGXbU21pSQcM+6HALzIA==
+SHA1-Digest: No95oIvE24q4zxCbceG0sqYwicg=
+SHA256-Digest: eZGrHWl1CfIYN4E5EDHiG+6tIgmhW9QNELFgxtRoZQI=
+
+Name: chrome/skin/classic/noscript/yu16.png
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: ImfjT+MqVzHN5Z7QA1531w==
+SHA1-Digest: 5HFWvY/aoPIbBCkqSI/KUQNCnyA=
+SHA256-Digest: VGBSMY5DQQbW/S6v6cRPi1CVQCO2+xEg5vPpeg33bs4=
+
+Name: components/noscriptService.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: 5mbtxCh/gYJQPSBRlm0U0A==
+SHA1-Digest: CST2HsndXBM/v2zddWR+BmatjQc=
+SHA256-Digest: FubbbfI8QhFMnn08UJD+yX/vqryAEooOFBNSl21wcSY=
+
+Name: defaults/preferences/noscript.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: uNRD7y0Zz3bZMQeZCJmETg==
+SHA1-Digest: pK3XVgH0ukdlRh8wxPo9JkpBcuE=
+SHA256-Digest: t7c71Cw9ev/cY+hRThSu9XUCL9gyK10eGh3ysJ/Kqgo=
+
+Name: webextension/legacy.js
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: o805XUj35LTfFs9yGeX5OQ==
+SHA1-Digest: ebwP0IzjCllGfmG9i6AAB4dXTXk=
+SHA256-Digest: 4dCaJOQ2kzjJi9ZdYQK5mK94FbhAmTHXlmQ00C4ON2w=
+
+Name: webextension/manifest.json
+Digest-Algorithms: MD5 SHA1 SHA256
+MD5-Digest: vptFQQI2f/Z7n2n0uG+8ZQ==
+SHA1-Digest: e9HjmPmlzAmqTjEpwIEvCzpktrw=
+SHA256-Digest: 29/J5kp5BT1qkqA6Os1YPWLcGouHhKysiGlKwb6reSE=
+
diff --git a/extensions/noscript/META-INF/mozilla.rsa b/extensions/noscript/META-INF/mozilla.rsa
new file mode 100644
index 0000000..4be9b30
--- /dev/null
+++ b/extensions/noscript/META-INF/mozilla.rsa
Binary files differ
diff --git a/extensions/noscript/META-INF/mozilla.sf b/extensions/noscript/META-INF/mozilla.sf
new file mode 100644
index 0000000..6bb5930
--- /dev/null
+++ b/extensions/noscript/META-INF/mozilla.sf
@@ -0,0 +1,5 @@
+Signature-Version: 1.0
+MD5-Digest-Manifest: lrLHUStdXPfJvg5LCNvgWA==
+SHA1-Digest-Manifest: Yp1TatXDVX89UPgLn+rGUi7Lvs4=
+SHA256-Digest-Manifest: qE5WvSxVlQkHgNnaCIcTmJZpgnk3Ne9xsQB9LjqSakw=
+
diff --git a/extensions/noscript/NoScript_License.txt b/extensions/noscript/NoScript_License.txt
new file mode 100644
index 0000000..ab6ab8f
--- /dev/null
+++ b/extensions/noscript/NoScript_License.txt
@@ -0,0 +1,17 @@
+NoScript - a Firefox extension for whitelist driven safe JavaScript execution
+Copyright (C) 2004-2014 Giorgio Maone - g.maone@informaction.com
+
+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 2 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, write to the
+Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
diff --git a/extensions/noscript/bootstrap.js b/extensions/noscript/bootstrap.js
new file mode 100644
index 0000000..9f1235e
--- /dev/null
+++ b/extensions/noscript/bootstrap.js
@@ -0,0 +1,64 @@
+var { utils: Cu, interfaces: Ci } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+let moduleURL = `chrome://noscript/content/Restartless.jsm?${Math.random() }.${Date.now()}`;
+let customizeStyle = "chrome://noscript/skin/browser.css";
+let module = {};
+
+function startup(data, reason) {
+ Cu.import(moduleURL, module);
+ module.startup(data, reason === APP_STARTUP); // Do whatever initial startup stuff you need to do
+
+ if (module.loadIntoWindow) {
+ forEachOpenWindow(module.loadIntoWindow);
+ }
+ Services.wm.addListener(WindowListener);
+}
+
+function shutdown(data, reason) {
+ if (reason === APP_SHUTDOWN)
+ return;
+
+ Services.wm.removeListener(WindowListener);
+
+ if (module.unloadFromWindow) forEachOpenWindow(module.unloadFromWindow);
+
+
+ module.shutdown(data);
+
+ Cu.unload(moduleURL);
+ Services.obs.notifyObservers(null, "chrome-flush-caches", null);
+}
+function install(data, reason) { }
+function uninstall(data, reason) { }
+
+function forEachOpenWindow(todo) // Apply a function to all open browser windows
+{
+ var windows = Services.wm.getEnumerator("navigator:browser");
+ while (windows.hasMoreElements())
+ todo(windows.getNext().QueryInterface(Ci.nsIDOMWindow));
+}
+var WindowListener =
+{
+ onOpenWindow: function(xulWindow)
+ {
+ var window = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindow);
+ function onWindowLoad()
+ {
+ window.removeEventListener("DOMContentLoad",onWindowLoad);
+ let doc = window.document;
+ if (doc.documentElement.getAttribute("windowtype") == "navigator:browser") {
+ module.loadIntoWindow(window, true);
+ } else if(window.location.href === "chrome://global/content/customizeToolbar.xul") {
+ let root = doc.documentElement;
+ let styleNode = doc.createProcessingInstruction("xml-stylesheet",`href="${customizeStyle}" type="text/css"`);
+ doc.insertBefore(styleNode, root);
+ }
+ }
+ window.addEventListener("DOMContentLoaded", onWindowLoad);
+ },
+ onCloseWindow: function(xulWindow) { },
+ onWindowTitleChange: function(xulWindow, newTitle) { }
+};
diff --git a/extensions/noscript/chrome.manifest b/extensions/noscript/chrome.manifest
new file mode 100644
index 0000000..c8cdddc
--- /dev/null
+++ b/extensions/noscript/chrome.manifest
@@ -0,0 +1,62 @@
+content noscript chrome/content/noscript/
+
+skin noscript classic/1.0 chrome/skin/classic/noscript/
+
+# Work around for breakages caused by the .NET Framework Assistant
+override chrome://dotnetassistant/content/bootstrap.xul data:text/xml,<lame/>
+
+# Localization
+locale noscript ar chrome/locale/ar/noscript/
+locale noscript be-BY chrome/locale/be-BY/noscript/
+locale noscript bg-BG chrome/locale/bg-BG/noscript/
+locale noscript bn-IN chrome/locale/bn-IN/noscript/
+locale noscript ca-AD chrome/locale/ca-AD/noscript/
+locale noscript cs-CZ chrome/locale/cs-CZ/noscript/
+locale noscript cy-GB chrome/locale/cy-GB/noscript/
+locale noscript da chrome/locale/da/noscript/
+locale noscript de chrome/locale/de/noscript/
+locale noscript el chrome/locale/el/noscript/
+locale noscript en-GB chrome/locale/en-GB/noscript/
+locale noscript en-US chrome/locale/en-US/noscript/
+locale noscript eo chrome/locale/eo/noscript/
+locale noscript es-AR chrome/locale/es-AR/noscript/
+locale noscript es-CL chrome/locale/es-CL/noscript/
+locale noscript es-ES chrome/locale/es-ES/noscript/
+locale noscript et-EE chrome/locale/et-EE/noscript/
+locale noscript eu chrome/locale/eu/noscript/
+locale noscript fa-IR chrome/locale/fa-IR/noscript/
+locale noscript fi chrome/locale/fi/noscript/
+locale noscript fr chrome/locale/fr/noscript/
+locale noscript gl-ES chrome/locale/gl-ES/noscript/
+locale noscript he-IL chrome/locale/he-IL/noscript/
+locale noscript hr-HR chrome/locale/hr-HR/noscript/
+locale noscript hsb chrome/locale/hsb/noscript/
+locale noscript hu-HU chrome/locale/hu-HU/noscript/
+locale noscript id-ID chrome/locale/id-ID/noscript/
+locale noscript it chrome/locale/it/noscript/
+locale noscript ja-JP chrome/locale/ja-JP/noscript/
+locale noscript kk-KZ chrome/locale/kk-KZ/noscript/
+locale noscript km-KH chrome/locale/km-KH/noscript/
+locale noscript ko-KR chrome/locale/ko-KR/noscript/
+locale noscript lt chrome/locale/lt/noscript/
+locale noscript mk-MK chrome/locale/mk-MK/noscript/
+locale noscript ms-MY chrome/locale/ms-MY/noscript/
+locale noscript nb-NO chrome/locale/nb-NO/noscript/
+locale noscript nl chrome/locale/nl/noscript/
+locale noscript pl chrome/locale/pl/noscript/
+locale noscript pt-BR chrome/locale/pt-BR/noscript/
+locale noscript pt-PT chrome/locale/pt-PT/noscript/
+locale noscript ro chrome/locale/ro/noscript/
+locale noscript ru-RU chrome/locale/ru-RU/noscript/
+locale noscript sk-SK chrome/locale/sk-SK/noscript/
+locale noscript sl-SI chrome/locale/sl-SI/noscript/
+locale noscript sr chrome/locale/sr/noscript/
+locale noscript sr-RS chrome/locale/sr-RS/noscript/
+locale noscript sv-SE chrome/locale/sv-SE/noscript/
+locale noscript te-IN chrome/locale/te-IN/noscript/
+locale noscript th chrome/locale/th/noscript/
+locale noscript tr chrome/locale/tr/noscript/
+locale noscript uk chrome/locale/uk/noscript/
+locale noscript vi chrome/locale/vi/noscript/
+locale noscript zh-CN chrome/locale/zh-CN/noscript/
+locale noscript zh-TW chrome/locale/zh-TW/noscript/
diff --git a/extensions/noscript/chrome/content/noscript/ABE.g b/extensions/noscript/chrome/content/noscript/ABE.g
new file mode 100644
index 0000000..a6fe7f6
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/ABE.g
@@ -0,0 +1,55 @@
+grammar ABE;
+
+options {
+ language=JavaScript;
+ output=AST;
+}
+
+tokens {
+ T_ACTION;
+ T_METHODS;
+}
+
+ruleset : rule* EOF ;
+rule : subject predicate+ -> subject predicate+ ;
+predicate : action methods? origin? -> T_ACTION action T_METHODS methods? origin? ;
+methods : (method+ | ALL) ;
+method : (HTTPVERB | SUB | inclusion) ;
+inclusion : INC (LPAR (INC_TYPE COMMA)* INC_TYPE? RPAR)? ;
+origin : T_FROM oresources ;
+subject : T_SITE resources ;
+oresources: (oresource+ | ALL) ;
+resources : (resource+ | ALL) ;
+oresource: resource | 'SELF' | 'SELF+' | 'SELF++' ;
+resource : REGEXP | GLOB | URI | LOCATION ;
+action : A_DENY | A_LOGOUT | A_SANDBOX | A_ACCEPT ;
+
+T_SITE : ('Site' | 'Request') ;
+T_FROM : ('f' | 'F') 'rom' ;
+A_DENY : 'Deny' ;
+A_LOGOUT : 'Logout' | 'Anon' 'ymize'? ;
+A_SANDBOX : 'Sandbox' ;
+A_ACCEPT : 'Accept' ;
+
+fragment URI_START : 'a'..'z' | '0'..'9' ;
+fragment URI_PART : 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '-' | '.' |
+ '[' | ']' | ':' | '/' | '@' | '~' | ';' | ',' |
+ '?' | '&' | '=' | '%' | '#' ;
+LOCATION : 'LOCAL' ;
+URI : URI_START URI_PART+ ;
+GLOB : (URI_START | '*' | '.') (URI_PART | '*')* ;
+REGEXP : '^' ~'\n'+ ;
+
+ALL : 'ALL' ;
+SUB : 'SUB' ;
+INC : 'INC' 'LUSION'? ;
+HTTPVERB : 'GET' | 'POST' | 'PUT' | 'HEAD' | 'PATCH' | 'DELETE' | 'TRACE' | 'OPTIONS';nsI
+INC_TYPE : 'A'..'Z' ('A'..'Z' | 'A'..'Z' '_' 'A'..'Z')+ ;
+
+
+COMMA : ',' ;
+LPAR : '(' ;
+RPAR : ')' ;
+
+WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;} ;
+COMMENT : '#' ~'\n'* {$channel=HIDDEN;} ;
diff --git a/extensions/noscript/chrome/content/noscript/ABE.js b/extensions/noscript/chrome/content/noscript/ABE.js
new file mode 100644
index 0000000..de4523f
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/ABE.js
@@ -0,0 +1,1540 @@
+var org = { antlr: { runtime: { tree: {} } } }; // work-around for an antlr scoping bug
+
+INCLUDE('antlr', 'ABEParser', 'ABELexer', 'Lang');
+
+var ABE = {
+ RULES_CHANGED_TOPIC: "abe:rules-changed",
+ FLAG_CALLED: 0x01,
+ FLAG_CHECKED: 0x02,
+
+ SITE_RULESET_LIFETIME: 12 * 60 * 60000, // 12 hours
+ maxSiteRulesetSize: 8192,
+ maxSiteRulesetTime: 16000,
+ enabled: false,
+ siteEnabled: false,
+ allowRulesetRedir: false,
+ skipBrowserRequests: true,
+
+ BROWSER_URI: IOS.newURI("chrome://browser/content/", null, null),
+ LOAD_BACKGROUND: Ci.nsIChannel.LOAD_BACKGROUND,
+ LOAD_INITIAL_DOCUMENT_URI: Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI,
+ SANDBOX_KEY: "abe.sandbox",
+ localRulesets: [],
+ _localMap: null,
+ _siteRulesets: null,
+
+ init: function(prefParent) {
+ const ps = this.prefService = Cc["@mozilla.org/preferences-service;1"]
+ .getService(Ci.nsIPrefService).QueryInterface(Ci.nsIPrefBranch);
+ ABEStorage.init(ps.getBranch(prefParent+ "ABE."));
+ DoNotTrack.init(ps.getBranch(prefParent+ "doNotTrack."));
+ },
+
+ dispose() {
+ ABEStorage.dispose();
+ WAN.enabled = false;
+ },
+
+ siteMap: Object.create(null),
+
+ get disabledRulesetNames() {
+ return this.rulesets.filter(function(rs) { return rs.disabled; })
+ .map(function(rs) { return rs.name; }).join(" ");
+ },
+ set disabledRulesetNames(names) {
+ var rs;
+ for (rs of this.rulesets) rs.disabled = false;
+ if (names) try {
+ for (var name of names.split(/\s+/)) {
+ rs = this.localMap[name] || this.siteMap[name];
+ if (rs) rs.disabled = true;
+ }
+ } catch(e) {}
+
+ return names;
+ },
+
+ get localMap() {
+ if (this._localMap) return this._localMap;
+ this._localMap = Object.create(null);
+ for (let rs of this.localRulesets) {
+ this._localMap[rs.name] = rs;
+ }
+ return this._localMap;
+ },
+
+ get siteRulesets() {
+ if (this._siteRulesets) return this._siteRulesets;
+ this._siteRulesets = [];
+ for (let name in this.siteMap) {
+ let rs = this.siteMap[name];
+ if (rs && !rs.empty) this._siteRulesets.push(rs);
+ }
+ this._siteRulesets.sort(function(r1, r2) { return r1.name > r2.name; });
+ return this._siteRulesets;
+ },
+
+ get rulesets() {
+ return this.localRulesets.concat(this.siteRulesets);
+ },
+
+ clear: function() {
+ this.localRulesets = [];
+ this.refresh();
+ },
+
+ refresh: function() {
+ this.siteMap = Object.create(null);
+ this._siteRulesets = null;
+ },
+
+ createRuleset: (name, source, timestamp) => new ABERuleset(name, source, timestamp || Date.now()),
+
+ parse: function(name, source, timestamp) {
+ try {
+ var rs = typeof name === "string" ? this.createRuleset(name, source, timestamp) : name;
+ if (rs.site) {
+ this.putSiteRuleset(rs);
+ } else {
+ this.addLocalRuleset(rs);
+ }
+ return rs;
+ } catch(e) {
+ this.log(e);
+ }
+ return false;
+ },
+
+ storeRuleset: function(name, source) {
+ if (this.localMap[name] === source) return false;
+ ABEStorage.saveRuleset(name, source);
+ ABEStorage.persist();
+ ABEStorage.loadRules();
+ return true;
+ },
+
+ addLocalRuleset: function(rs) {
+ this.localRulesets.push(rs);
+ this._localMap = null;
+ },
+
+ putSiteRuleset: function(rs) {
+ this.siteMap[rs.name] = rs;
+ this._siteRulesets = null;
+ },
+
+ restoreJSONRules: function(data) {
+ if (!data.length) return;
+ try {
+ ABEStorage.clear();
+ for (let rs of data) {
+ ABEStorage.saveRuleset(rs.name, rs.source);
+ }
+ } catch(e) {
+ ABE.log("Failed to restore configuration: " + e);
+ }
+ },
+
+ resetDefaults: function() {
+ ABEStorage.clear();
+ this.clear();
+ },
+
+
+ checkPolicy: function(origin, destination, type) {
+ try {
+ return this.checkRequest(new ABERequest(new ABEPolicyChannel(origin, destination, type)));
+ } catch(e) {
+ ABE.log(e);
+ return false;
+ }
+ },
+
+ checkRequest: function(req) {
+ if (!this.enabled)
+ return false;
+
+ const channel = req.channel;
+ const loadFlags = channel.loadFlags;
+
+ var browserReq = req.originURI.schemeIs("chrome") && !req.external;
+
+ if (browserReq &&
+ (
+ this.skipBrowserRequests &&
+ ((loadFlags & this.LOAD_BACKGROUND) ||
+ !req.isDoc && req.origin == ABE.BROWSER_URI.spec && !req.window)
+ )
+ ) {
+ if (this.consoleDump) this.log("Skipping low-level browser request for " + req.destination);
+ return false;
+ }
+
+ if (this.localRulesets.length == 0 && !this.siteEnabled)
+ return null;
+
+ if (this.deferIfNeeded(req))
+ return false;
+
+ if (DoNotTrack.enabled) DoNotTrack.apply(req);
+
+ var t;
+ if (this.consoleDump) {
+ this.log("Checking #" + req.serial + ": " + req.destination + " from " + req.origin + " - " + loadFlags);
+ t = Date.now();
+ }
+
+ try {
+ var res = new ABERes(req);
+ var rs;
+ for (rs of this.localRulesets) {
+ if (this._check(rs, res)) break;
+ }
+
+ if (!(browserReq || res.fatal) &&
+ this.siteEnabled && channel instanceof Ci.nsIHttpChannel &&
+ !ABE.reqData(channel).preflght &&
+ req.destinationURI.schemeIs("https") &&
+ req.destinationURI.prePath != req.originURI.prePath &&
+ !(this.skipBrowserRequests && req.originURI.schemeIs("chrome") && !req.window) // skip preflight for window-less browser requests
+ ) {
+
+ var name = this._host2name(req.destinationURI.host);
+ if (!(name in this.siteMap)) {
+ ABE.log("Preflight for " + req.origin + ", " + req.destination + ", " + loadFlags);
+ this.downloadRuleset(name, req.destinationURI);
+ }
+
+ rs = this.siteMap[name];
+ if (rs && Date.now() - rs.timestamp > this.SITE_RULESET_LIFETIME)
+ rs = this.downloadRuleset(name, req.destinationURI);
+
+ if (rs) this._check(rs, res);
+ }
+ } finally {
+ if (this.consoleDump) this.log(req.destination + " Checked in " + (Date.now() - t));
+ req.checkFlags |= this.FLAG_CHECKED;
+ }
+ return res.lastRuleset && res;
+ },
+
+ _check: function(rs, res) {
+ var action = rs.check(res.request);
+ if (action) {
+ action = action.toLowerCase();
+ let outcome = (res.request.channel instanceof ABEPolicyChannel)
+ ? (action === "deny" ? ABERes.FATAL : ABERes.SKIPPED)
+ : ABEActions[action](res.request);
+ if (outcome !== ABERes.SKIPPED) {
+ let r = rs.lastMatch;
+ this.log(r);
+ this.log(res.request + ' matches "' + r.lastMatch + '"');
+ (res.rulesets || (res.rulesets = [])).push(rs);
+ res.lastRuleset = rs;
+ return res.fatal = outcome === ABERes.FATAL;
+ }
+ }
+ return false;
+ },
+
+ deferIfNeeded: function(req) {
+ var host = req.destinationURI.host;
+ if (!(req.canDoDNS && req.deferredDNS) ||
+ DNS.isIP(host) ||
+ DNS.isCached(host) ||
+ req.channel.redirectionLimit === 0 || req.channel.status !== 0
+ )
+ return false;
+
+ ABE.reqData(req.channel).deferred = true;
+
+ if (ChannelReplacement.runWhenPending(req.channel, function() {
+ try {
+
+ if (req.channel.status !== 0) return;
+
+ if ((req.channel instanceof Ci.nsITransportEventSink)
+ && req.isDoc && !(req.subdoc || req.dnsNotified)) try {
+ Thread.asap(function() {
+ if (!req.dnsNotified) {
+ ABE.log("DNS notification for " + req.destination);
+ req.dnsNotified = true; // unexplicable recursions have been reported...
+ req.channel.onTransportStatus(null, 0x804b0003, 0, 0); // notify STATUS_RESOLVING
+ }
+ });
+ } catch(e) {}
+
+ req.replace(false, null, function(replacement) {
+ ABE.log(host + " not cached in DNS, deferring ABE checks after DNS resolution for request " + req.serial);
+
+ DNS.resolve(host, 0, function(dnsRecord) {
+ req.dnsNotified = true; // prevents spurious notifications
+ replacement.open();
+ });
+ });
+
+ } catch(e) {
+ ABE.log("Deferred ABE checks failed: " + e);
+ }
+ })) {
+ ABE.log(req.serial + " not pending yet, will check later.")
+ }
+
+ return true;
+ },
+
+ reqData(req, remove = false) {
+ return IOUtil.reqData(req, "net.noscript/ABE.channelData", remove);
+ },
+
+ isDeferred: function(chan) {
+ return !!ABE.reqData(chan).deferred;
+ },
+
+ hasSiteRulesFor: function(host) {
+ return this._host2Name(host) in this.siteMap;
+ },
+
+
+ _host2name: function(host) {
+ return "." + host;
+ },
+
+ isSubdomain: function(parentHost, childHost) {
+ if (parentHost.length > childHost.length) return false;
+ parentHost = "." + parentHost;
+ childHost = "." + childHost;
+ return parentHost == childHost.substring(childHost.length - parentHost.length);
+ },
+
+ _downloading: {},
+ _abeContentTypeRx: /^application\/|\babe\b|^text\/plain$/i,
+ downloadRuleset: function(name, uri) {
+ var host = uri.host;
+
+ var downloading = this._downloading;
+
+ if (host in downloading) {
+ ABE.log("Already fetching rulesets for " + host);
+ }
+
+ var ts = Date.now();
+
+ var ctrl = {
+ _r: true,
+ set running(v) { if (!v) delete downloading[host]; return this._r = v; },
+ get running() { return this._r; },
+ startTime: ts,
+ maxTime: ABE.maxSiteRulesetTime
+ };
+
+ var elapsed;
+
+ try {
+ downloading[host] = true;
+
+ this.log("Trying to fetch rules for " + host);
+
+ uri = uri.clone();
+ uri.scheme = "https";
+ uri["path" in uri ? "path" : "pathQueryRef"] = "/rules.abe";
+
+ var xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
+ xhr.mozBackgroundRequest = true;
+ xhr.open("GET", uri.spec, true); // async if we can spin our own event loop
+
+ var channel = xhr.channel; // need to cast
+ ABE.reqData(channel).preflight = true;
+
+ if (channel instanceof Ci.nsIHttpChannel && !this.allowRulesetRedir)
+ channel.redirectionLimit = 0;
+
+ if (channel instanceof Ci.nsICachingChannel)
+ channel.loadFlags |= channel.LOAD_BYPASS_LOCAL_CACHE_IF_BUSY; // see bug 309424
+
+
+ xhr.addEventListener("readystatechange", function() {
+ switch(xhr.readyState) {
+ case 2:
+ if (xhr.status >= 400) {
+ ABE.log("Early abort with status " + xhr.status + " for ruleset at " + uri.spec);
+ break;
+ }
+ return;
+ case 3:
+ var size = xhr.responseText.length; // todo: use https://developer.mozilla.org/En/Using_XMLHttpRequest#Monitoring_progress
+ if (size > ABE.maxSiteRulesetSize) {
+ ABE.log("Ruleset at " + uri.spec + " too big: " + size + " > " + ABE.maxSiteRulesetSize);
+ break;
+ }
+ return;
+ case 4:
+ // end
+ ctrl.running = false;
+ return;
+ default: // 0, 1
+ return;
+ }
+ xhr.abort();
+ ctrl.running = false;
+ }, false);
+
+
+ var send = function() {
+ xhr.send(null);
+ return Thread.spin(ctrl);
+ };
+
+ if (send()) {
+ var size = 0;
+ try {
+ size = xhr.responseText.length;
+ } catch(e) {}
+ ABE.log("Ruleset at " + uri.spec + " timeout: " + size + " chars received in " + ctrl.elapsed + "ms");
+ xhr.abort();
+ return false;
+ }
+
+ if (xhr.channel != channel && xhr.channel) // shouldn't happen, see updateRedirectChain()...
+ this._handleDownloadRedirection(channel, xhr.channel);
+
+ if (xhr.status != 200)
+ throw new Error("Status: " + xhr.status);
+
+ if (!this._abeContentTypeRx.test(xhr.channel.contentType))
+ throw new Error("Content-type: " + xhr.channel.contentType);
+
+ var source = xhr.responseText || '';
+
+ elapsed = Date.now() - ts;
+ if (source) ABE.log("Fetched ruleset for "+ host + " in " + elapsed + "ms");
+
+ return this.parse(name, source);
+ } catch(e) {
+ elapsed = elapsed || Date.now() - ts;
+ this.log("Can't fetch " + uri.spec + " (" + elapsed + "ms elapsed)");
+ this.log(e.message);
+ } finally {
+ if (!(name in this.siteMap)) this.parse(name, '');
+ else this.siteMap[name].timestamp = ts;
+ ctrl.running = false;
+ }
+
+ return false;
+ },
+
+
+ isSandboxed(channel) {
+ return ABE.reqData(channel).sandboxed;
+ },
+ setSandboxed(channel, sandboxed = true) {
+ ABE.reqData(channel).sandboxed = sandboxed;
+ },
+
+ get cspHeaderValue() {
+ delete this.cspHeaderValue;
+ let prefs = ABEStorage.prefs;
+ let delim;
+ try {
+ delim = prefs.getCharPref("cspHeaderDelim") || "ABE";
+ } catch (e) {
+ delim = `ABE${Math.random().toString().replace(".", "-")}`;
+ prefs.setCharPref("cspHeaderDelim", delim);
+ }
+ let value = `${delim}; child-src 'self'; object-src 'none'; script-src 'none'; ${delim};`;
+ return (this.cspHeaderValue = value);
+ },
+ enforceSandbox(channel, enforcing) {
+ const CSP = "Content-Security-Policy";
+ let value = this.cspHeaderValue;
+ try {
+ let currentPolicy = channel.getResponseHeader(CSP);
+ if (currentPolicy.includes(value)) {
+ if (enforcing) {
+ return true;
+ }
+ channel.setResponseHeader(CSP, currentPolicy.replace(value, ''), false);
+ return false;
+ }
+ } catch (e) {}
+ if (enforcing) {
+ try {
+ channel.setResponseHeader(CSP, value, true);
+ return true;
+ }catch(e) {
+ Cu.reportError(e);
+ }
+ }
+ return false;
+ },
+ handleSandbox(channel) {
+ this.enforceSandbox(channel, this.isSandboxed(channel));
+ },
+
+ updateRedirectChain: function(oldChannel, newChannel) {
+ this._handleDownloadRedirection(oldChannel, newChannel);
+
+ var redirectChain = this.getRedirectChain(oldChannel);
+ redirectChain.push(oldChannel.URI);
+ ABE.reqData(newChannel).redirectChain = redirectChain;
+ },
+
+ getRedirectChain: function(channel) {
+ var rc = ABE.reqData(channel).redirectChain;
+ if (!rc) {
+ var origin = ABERequest.getOrigin(channel);
+ rc = origin ? [origin] : [];
+ rc.wrappedJSObject = rc;
+ };
+ return rc;
+ },
+
+ getOriginalOrigin: function(channel) {
+ var rc = this.getRedirectChain(channel);
+ return rc.length && rc[0] || null;
+ },
+
+ _handleDownloadRedirection: function(oldChannel, newChannel) {
+ if (!ABE.reqData(oldChannel).preflight) return;
+
+ var uri = oldChannel.URI;
+ var newURI = newChannel.URI;
+
+ if (uri.spec !== newURI.spec && // redirected, check if it same path and same domain or upper
+ (uri.filePath !== newURI.filePath ||
+ !(newURI.schemeIs("https") && this.isSubdomain(newURI.host, uri.host))
+ )
+ ) {
+ var msg = "Illegal ABE rule redirection " + uri.spec + " -> " + newURI.spec;
+ ABE.log(msg);
+ oldChannel.cancel(NS_BINDING_ABORTED);
+ throw new Error(msg);
+ }
+
+ ABE.reqData(oldChannel).preflight = true;
+ },
+
+
+ consoleDump: false,
+ log: function(msg) {
+ if (this.consoleDump) {
+ if (msg.stack) msg = msg.message + "\n" + msg.stack;
+ dump("[ABE] " + msg + "\n");
+ }
+ }
+}
+
+function ABERes(req) {
+ this.request = req;
+}
+ABERes.SKIPPED = 0;
+ABERes.DONE = 1;
+ABERes.FATAL = 2;
+
+ABERes.prototype = {
+ rulesets: null,
+ lastRuleset: null,
+ fatal: false
+}
+
+var ABEActions = {
+ accept: function(req) {
+ return ABERes.DONE;
+ },
+ deny: function(req) {
+ IOUtil.abort(req.channel, true);
+ return ABERes.FATAL;
+ },
+
+ _idempotentMethodsRx: /^(?:GET|HEAD|OPTIONS)$/i,
+ anonymize: function(req) {
+ var channel = req.channel;
+ let cookie;
+ try {
+ cookie = channel.getRequestHeader("Cookie");
+ } catch(e) {
+ cookie = '';
+ }
+ IOUtil.anonymizeChannel(channel);
+ let anonURI = IOUtil.anonymizeURI(req.destinationURI.clone(), cookie);
+ let idempotent = this._idempotentMethodsRx.test(channel.requestMethod);
+ if (idempotent && anonURI.spec === req.destinationURI.spec &&
+ ABE.reqData(channel).anon) {// already anonymous
+ return ABERes.SKIPPED;
+ }
+
+ req.replace(
+ idempotent ? null : "GET",
+ anonURI,
+ function(replacement) {
+ let channel = replacement.channel;
+ ABE.reqData(channel).anon = true;
+ IOUtil.anonymizeChannel(channel);
+ replacement.open();
+ },
+ true
+ );
+
+ return ABERes.DONE;
+ },
+
+ sandbox: function(req) {
+ ABE.setSandboxed(req.channel);
+ return ABERes.DONE;
+ }
+}
+
+
+function ABERuleset(name, source, timestamp) {
+ this.name = name;
+ this.site = name.indexOf(".") !== -1;
+ this.source = source;
+ this.empty = !source;
+ this.timestamp = timestamp || Date.now();
+ if (!this.empty) {
+ try {
+ // dirty hack
+ var self = this;
+ org.antlr.runtime.BaseRecognizer.prototype.emitErrorMessage = function(msg) {
+ // we abort immediately to prevent infinite loops
+ var m = msg.match(/^line (\d+)/i, msg);
+ if (m) throw new Error(msg, parseInt(m[1]), self.name); // TODO: error console reporting w/ line num
+ throw new Error(msg)
+ };
+
+ this._init(new ABEParser(new org.antlr.runtime.CommonTokenStream(
+ new ABELexer(new org.antlr.runtime.ANTLRStringStream(source))))
+ .ruleset().getTree());
+ } catch(e) {
+ if (this.errors) this.errors.push(e.message)
+ else this.errors = [e.message];
+ }
+ }
+}
+
+ABERuleset.prototype = {
+ site: false,
+ empty: false,
+ errors: null,
+ disabled: false,
+ rules: [],
+ expires: 0,
+
+ _init: function(tree) {
+ var rule = null,
+ predicate = null,
+ accumulator = null,
+ history = [],
+ rules = [];
+
+ walk(tree);
+
+ if (!this.errors) this.rules = rules;
+ rule = predicate = accumulator = history = null;
+
+
+ function walk(tree) {
+ var node, t;
+ for (var j = 0, l = tree.getChildCount(); j < l; j++) {
+ node = tree.getChild(j);
+ examine(node);
+ walk(node.getTree());
+ }
+ }
+
+ function examine(node) {
+ var t = node.getToken();
+
+ switch(t.type) {
+ case ABEParser.T_SITE:
+ case ABEParser.EOF:
+ if (rule) commit();
+ if (t.type == ABEParser.T_SITE) {
+ rule = { destinations: [], predicates: [] };
+ accumulator = rule.destinations;
+ }
+ break;
+ case ABEParser.T_ACTION:
+ if (rule) {
+ rule.predicates.push(predicate = { actions: [], methods: [], origins: [] });
+ accumulator = predicate.actions;
+ }
+ break;
+ case ABEParser.T_METHODS:
+ accumulator = predicate.methods;
+ break;
+ case ABEParser.INC:
+ if (!("inclusions" in predicate)) predicate.inclusions = [];
+ break;
+ case ABEParser.INC_TYPE:
+ if ("inclusions" in predicate) predicate.inclusions.push(node.getText());
+ break;
+ break;
+ case ABEParser.T_FROM:
+ accumulator = predicate.origins;
+ break;
+ case ABEParser.COMMENT:
+ case ABEParser.COMMA:
+ case ABEParser.LPAR: case ABEParser.RPAR:
+ break;
+ default:
+ if (accumulator) accumulator.push(node.getText());
+ }
+ }
+
+ function commit() {
+ rules.push(new ABERule(rule.destinations, rule.predicates));
+ rule = null;
+ }
+ },
+
+ lastMatch: null,
+ check: function(req) {
+ if (this.disabled) return '';
+
+ var res;
+ for (var r of this.rules) {
+ res = r.check(req);
+ if (res) {
+ this.lastMatch = r;
+ return res;
+ }
+ }
+ return '';
+ }
+}
+
+function ABERule(destinations, predicates) {
+ this.destinations = destinations.join(" ");
+ this.destination = new AddressMatcher(destinations.filter(this._destinationFilter, this).join(" "));
+ this.predicates = predicates.map(ABEPredicate.create);
+}
+
+ABERule.prototype = {
+ local: false,
+
+ allDestinations: false,
+ lastMatch: null,
+ _destinationFilter: function(s) {
+ switch(s) {
+ case "SELF":
+ return false; // this is illegal, should we throw an exception?
+ case "LOCAL":
+ return !(this.local = true);
+ case "ALL":
+ return !(this.allDestinations = true);
+ }
+ return true;
+ },
+
+ check: function(req) {
+ if (!req.failed &&
+ (this.allDestinations ||
+ this.destination && this.destination.test(req.destination, req.canDoDNS, false) ||
+ this.local && req.localDestination)
+ ) {
+ for (var p of this.predicates) {
+ if (p.match(req)) {
+ this.lastMatch = p;
+ return p.action;
+ }
+ if (req.failed) break;
+ }
+ }
+ return '';
+ },
+
+ toString: function() {
+ var s = "Site " + this.destinations + "\n" + this.predicates.join("\n");
+ this.toString = function() { return s; };
+ return s;
+ }
+}
+
+function ABEPredicate(p) {
+ this.action = p.actions[0];
+
+ switch(this.action) {
+ case "Accept":
+ this.permissive = true;
+ break;
+ case "Logout": case "Anon":
+ this.action = 'Anonymize';
+ break;
+ }
+
+ var methods = p.methods;
+
+ if ("inclusions" in p) {
+ this.inclusion = true;
+
+ // rebuild method string for cosmetic reasons
+ let incMethod = "INCLUSION";
+ let ii = p.inclusions;
+ let j = ii.length;
+ if (j) {
+ incMethod += "(" + ii.join(", ") + ")";
+ let its = [];
+ let map = this._inclusionTypesMap;
+ while (j-- > 0) {
+ let i = ii[j];
+ if (i in map) {
+ let t = map[i];
+ if (typeof t === "number") its.push(t);
+ else its.push.apply(its, t);
+ } else its.push(0);
+ }
+ this.inclusionTypes = its;
+ } else {
+ this.inclusionTypes = null;
+ }
+
+ methods = p.methods.concat(incMethod);
+ }
+
+ this.methods = methods.join(" ");
+
+ if (this.methods.length) {
+ this.allMethods = false;
+ var mm = p.methods.filter(this._methodFilter, this);
+ if (mm.length) this.methodRx = new RegExp("^\\b(?:" + mm.join("|") + ")\\b$", "i");
+ }
+ this.origins = p.origins.join(" ");
+ if (p.origins.length) {
+ this.allOrigins = false;
+ if (this.permissive) { // if Accept any, accept browser URLs
+ p.origins.push("^(?:chrome|resource):");
+ }
+ this.origin = new AddressMatcher(p.origins.filter(this._originFilter, this).join(" "));
+ }
+}
+ABEPredicate.create = function(p) { return new ABEPredicate(p); };
+ABEPredicate.prototype = {
+ permissive: false,
+
+ subdoc: false,
+ self: false,
+ sameDomain: false,
+ sameBaseDomain: false,
+ local: false,
+
+ allMethods: true,
+ allOrigins: true,
+
+ methodRx: null,
+ origin: null,
+
+ inclusion: false,
+ inclusionTypes: null,
+
+ get _inclusionTypesMap() {
+ delete this.__proto__._inclusionTypesMap;
+ const CP = Ci.nsIContentPolicy;
+ let map = {
+ CSS: CP.TYPE_STYLESHEET,
+ DOCUMENT: CP.TYPE_DOCUMENT, // placeholder, should never happen for inclusions
+ DTD: CP.TYPE_DTD,
+ FONT: CP.TYPE_FONT,
+ IMAGE: [CP.TYPE_IMAGE, CP.TYPE_IMAGESET],
+ MEDIA: CP.TYPE_MEDIA,
+ OBJ: [CP.TYPE_OBJECT, CP.TYPE_OBJECT_SUBREQUEST],
+ OBJSUB: CP.TYPE_OBJECT_SUBREQUEST,
+ OTHER: [CP.TYPE_OTHER],
+ SCRIPT: CP.TYPE_SCRIPT,
+ SUBDOC: CP.TYPE_SUBDOCUMENT,
+ UNKNOWN: CP.TYPE_OTHER,
+ XHR: [CP.TYPE_XMLHTTPREQUEST, CP.TYPE_FETCH],
+ };
+ let mappedTypes = new Set();
+ for (let k in map) {
+ let v = map[k];
+ if (Array.isArray(v)) {
+ for (let t of v) mappedTypes.add(t);
+ } else {
+ mappedTypes.add(v);
+ }
+ }
+
+ let cpTypes = Object.keys(CP).filter(k => k.startsWith("TYPE_") && !k.startsWith("TYPE_INTERNAL_"));
+ for (let key of cpTypes) {
+ let name = key.substring(5);
+ if (!(name in map)) {
+ let type = CP[key];
+ map[name] = type;
+ if (!mappedTypes.has(type)) map.OTHER.push(type);
+ }
+ }
+ return (this.__proto__._inclusionTypesMap = map);
+ },
+
+ _methodFilter: function(m) {
+ switch(m) {
+ case "SUB":
+ return !(this.subdoc = true);
+ case "ALL":
+ return !(this.allMethods = true);
+ }
+ return true;
+ },
+
+ _originFilter: function(s) {
+ switch(s) {
+ case "SELF":
+ return !(this.self = true);
+ case "SELF+":
+ return !(this.sameDomain = true);
+ case "SELF++":
+ return !(this.sameBaseDomain = true);
+ case "LOCAL":
+ return !(this.local = true);
+ case "ALL":
+ return !(this.allOrigins = true);
+ }
+ return true;
+ },
+
+ match: function(req) {
+ return (this.allMethods || this.subdoc && req.isSubdoc ||
+ this.inclusion && req.isOfType(this.inclusionTypes) ||
+ this.methodRx && this.methodRx.test(req.method)) &&
+ (this.allOrigins ||
+ this.self && req.isSelf ||
+ this.sameDomain && req.isSameDomain ||
+ this.sameBaseDomain && req.isSameBaseDomain ||
+ (this.permissive
+ ? req.matchAllOrigins(this.origin)
+ : req.matchSomeOrigins(this.origin)) || this.local && req.localOrigin
+ );
+ },
+
+ toString: function() {
+ var s = this.action;
+ if (this.methods) s += " " + this.methods;
+ if (this.origins) s += " from " + this.origins;
+ this.toString = function() { return s; };
+ return s;
+ }
+}
+
+function ABEPolicyChannel(origin, destination, type) {
+ this.originURI = origin;
+ this.URI = destination;
+ this.type = type;
+}
+ABEPolicyChannel.prototype = {
+ requestMethod: "GET",
+ cancelled: false,
+ loadFlags: 0,
+ cancel: function() {
+ this.cancelled = true;
+ }
+}
+
+function ABERequest(channel) {
+ this._init(channel);
+}
+
+ABERequest.serial = 0;
+
+ABERequest.getOrigin = function(channel) {
+ let u = ABE.reqData(channel).origin;
+ return (u instanceof Ci.nsIURI) ? u : null;
+},
+ABERequest.getLoadingChannel = function(window) {
+ return window && ("__loadingChannel__" in window) && window.__loadingChannel__;
+},
+
+ABERequest.storeOrigin = function(channel, originURI) {
+ ABE.reqData(channel).origin = originURI;
+},
+
+ABERequest.clear = function(channel, window) {
+ // fille me as needed
+}
+
+ABERequest.count = 0;
+
+
+ABERequest.prototype = Lang.memoize({
+ external: false,
+ failed: false,
+ checkFlags: 0,
+ deferredDNS: true,
+ replaced: false,
+ dnsNotified: false,
+
+ _init: function(channel) {
+ this.serial = ABERequest.serial++;
+ this.channel = channel;
+ this.method = channel.requestMethod;
+ this.destinationURI = IOUtil.unwrapURL(channel.URI);
+ this.destination = this.destinationURI.spec;
+ this.destinationDomain = this.destinationURI.host;
+
+ this.early = channel instanceof ABEPolicyChannel;
+ this.isDoc = !!(channel.loadFlags & channel.LOAD_DOCUMENT_URI);
+
+ if (this.isDoc) {
+ var w = this.window;
+ if (w) try {
+ w.__loadingChannel__ = channel;
+ } catch (e) {}
+ }
+
+ var ou = ABERequest.getOrigin(channel);
+ if (ou) {
+ this.originURI = ou;
+ this.origin = ou.spec;
+ this.replaced = true;
+ } else {
+ if (this.early) ou = channel.originURI;
+ else {
+ let loadInfo = channel.loadInfo;
+ if (loadInfo) {
+ let principal = loadInfo.triggeringPrincipal || loadInfo.loadingPrincipal;
+ ou = principal && (principal.URI || principal.originNoSuffix || principal.origin);
+ } else {
+ dump(`loadInfo is null for channel ${channel.name}\n`);
+ }
+ }
+
+ if (ou) {
+ if (ou.spec) {
+ ou = IOUtil.unwrapURL(ou);
+ this.origin = ou.spec;
+ } else {
+ this.origin = ou;
+ try {
+ ou = IOS.newURI(ou, null, null);
+ } catch (e) {
+ ou = ABE.BROWSER_URI;
+ }
+ }
+ } else {
+ ou = ABE.BROWSER_URI;
+ }
+
+ ABERequest.storeOrigin(channel, this.originURI = ou);
+ }
+ },
+
+ replace: function(newMethod, newURI, callback, forceInternal) {
+ new ChannelReplacement(this.channel, newURI, newMethod)
+ .replace(!forceInternal && (newMethod || newURI), callback);
+ return true;
+ },
+
+ isBrowserURI: function(uri) {
+ return uri.schemeIs("chrome") || uri.schemeIs("resource") || uri.schemeIs("about") || uri.schemeIs("moz-extension");
+ },
+
+ isLocal: function(uri, all) {
+ return DNS.isLocalURI(uri, all);
+ },
+
+ isOfType: function(types) {
+ if (types === null) return this.type !== Ci.nsIContentPolicy.TYPE_DOCUMENT;
+ return (typeof types === "number")
+ ? this.type === types
+ : types.indexOf(this.type) !== -1;
+ },
+
+ _checkLocalOrigin: function(uri) {
+ try {
+ return !this.failed && uri && (this.isBrowserURI(uri) || this.isLocal(uri, true)); // we cache external origins to mitigate DNS rebinding
+ } catch(e) {
+ ABE.log("Local origin DNS check failed for " + uri.spec + ": " + e);
+ try {
+ if (this.destinationURI.host == uri.host) {
+ this.channel.cancel(NS_ERROR_UNKNOWN_HOST);
+ this.failed = true;
+ }
+ } catch(e) {
+ }
+ return false;
+ }
+ },
+
+ _checkSelf: function(originURI) {
+ return originURI && (this.isBrowserURI(originURI) || originURI.prePath == this.destinationURI.prePath);
+ },
+
+ _checkSameDomain: function(originURI) {
+ try {
+ return originURI && this.isBrowserURI(originURI) || originURI.host == this.destinationDomain;
+ } catch(e) {}
+ return false;
+ },
+
+ _checkSameBaseDomain: function(originURI) {
+ try {
+ return originURI && this.isBrowserURI(originURI) || IOUtil.TLDService.getBaseDomainFromHost(originURI.host) == this.destinationBaseDomain;
+ } catch(e) {}
+ return false;
+ },
+
+ matchAllOrigins: function(matcher) {
+ var canDoDNS = this.canDoDNS;
+ return (canDoDNS && matcher.netMatching) ?
+ this.redirectChain.every((uri) => matcher.testURI(uri, canDoDNS, true))
+ : this.redirectChain.every(matcher.testURI, matcher)
+ ;
+ },
+
+ matchSomeOrigins: function(matcher) {
+ var canDoDNS = this.canDoDNS;
+ return (canDoDNS && matcher.netMatching)
+ ? this.redirectChain.some(uri => matcher.testURI(uri, canDoDNS, false))
+ : this.redirectChain.some(matcher.testURI, matcher)
+ ;
+ },
+
+ toString: function() {
+ var s = "{" + this.method + " " + this.destination + " <<< " +
+ this.redirectChain.reverse().map(function(uri) { return uri.spec; })
+ .join(", ") + " - " + this.type + "}";
+ this.toString = function() { return s; }
+ return s;
+ }
+},
+// lazy properties
+{
+ canDoDNS: function() {
+ return (this.channel instanceof Ci.nsIChannel) && // we want to prevent sync DNS resolution for resources we didn't already looked up
+ IOUtil.canDoDNS(this.channel);
+ },
+ localOrigin: function() {
+ return this.canDoDNS && this.redirectChain.every(this._checkLocalOrigin, this);
+ },
+ localDestination: function() {
+ try {
+ return !this.failed && this.canDoDNS && this.isLocal(this.destinationURI, false);
+ } catch(e) {
+ ABE.log("Local destination DNS check failed for " + this.destination + " from "+ this.origin + ": " + e);
+ this.channel.cancel(NS_ERROR_UNKNOWN_HOST);
+ this.failed = true;
+ return false;
+ }
+ },
+ isSelf: function() {
+ return this._checkSelf(this.originURI) && this.redirectChain.every(this._checkSelf, this);
+ },
+ isSameDomain: function() {
+ return this.isSelf || this.redirectChain.every(this._checkSameDomain, this);
+ },
+ isSameBaseDomain: function() {
+ return this.isSameDomain || this.redirectChain.every(this._checkSameBaseDomain, this);
+ },
+
+ destinationBaseDomain: function() {
+ try {
+ return IOUtil.TLDService.getBaseDomainFromHost(this.destinationDomain);
+ } catch(e) {}
+ return this.destinationDomain;
+ },
+
+ isSubdoc: function() {
+ if (this.isDoc) {
+ var w = this.window;
+ return (w != w.top);
+ }
+ var channel = this.channel;
+ return !!(channel.loadFlags & channel.LOAD_CALL_CONTENT_SNIFFERS);
+ },
+ redirectChain: function() {
+ return ABE.getRedirectChain(this.channel);
+ },
+
+ window: function() {
+ return IOUtil.findWindow(this.channel);
+ },
+
+ type: function() {
+ try {
+ return this.early ? this.channel.type : this.channel.loadInfo.externalContentPolicyType ||
+ PolicyState.extract(this.channel).contentType;
+ } catch(e) {
+ ABE.log("Error retrieving type of " + this.destination + ": " + e); // should happen for favicons only
+ }
+ return Ci.nsIContentPolicy.TYPE_OTHER;
+ }
+
+}
+); // end memoize
+
+
+var ABEStorage = {
+ _updating: true,
+ _dirty: true,
+ init: function(prefs) {
+ this.prefs = prefs;
+ if (!prefs.getIntPref("migration")) try {
+ prefs.setIntPref("migration", 1);
+ this._migrateLegacyFiles();
+ } catch (e) {}
+ this.loadRules();
+ for (let k of prefs.getChildList("", {})) this.observe(prefs, null, k);
+ prefs.addObserver("", this, true);
+ },
+ dispose() {
+ try {
+ this.prefs.removeObserver("", this, true);
+ } catch (e) {
+ }
+ },
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
+ observe: function(prefs, topic, name) {
+ if (typeof ABE === "undefined") {
+ prefs.removeObserver("", this, true);
+ return;
+ }
+ switch(name) {
+ case "wanIpAsLocal":
+ WAN.enabled = prefs.getBoolPref(name);
+ break;
+ case "wanIpCheckURL":
+ WAN.checkURL = prefs.getCharPref(name);
+ break;
+ case "localExtras":
+ DNS.localExtras = AddressMatcher.create(prefs.getCharPref(name));
+ break;
+ case "enabled":
+ case "siteEnabled":
+ case "allowRulesetRedir":
+ case "skipBrowserRequests":
+ ABE[name] = prefs.getBoolPref(name);
+ break;
+ case "disabledRulesetNames":
+ ABE[name] = prefs.getCharPref(name);
+ break;
+ default:
+ if (!this._updating && name.indexOf("rulesets.") === 0) {
+ this._updating = this._dirty = true;
+ Thread.asap(this.loadRules, this);
+ }
+ }
+ },
+
+ get _rulesetPrefs() { return this.prefs.getChildList("rulesets", {}); },
+ clear: function() {
+ const prefs = this.prefs;
+ const keys = this._rulesetPrefs;
+ for (let j = keys.length; j-- > 0;) {
+ let k = keys[j];
+ if (prefs.prefHasUserValue(k)) {
+ dump("Resetting ABE ruleset " + k + "\n");
+ try {
+ prefs.clearUserPref(k);
+ } catch(e) { dump(e + "\n") }
+ }
+ }
+ },
+
+ loadRules: function() {
+ this._updating = false;
+ if (!this._dirty) return;
+ this._dirty = false;
+
+ const keys = this._rulesetPrefs;
+ keys.sort();
+ const prefs = this.prefs;
+ var disabled = ABE.disabledRulesetNames;
+ ABE.clear();
+ for (let j = 0, len = keys.length; j < len; j++) {
+ let k = keys[j];
+ ABE.parse(k.replace("rulesets.", ""), COMPAT.getStringPref(prefs, k));
+ }
+ ABE.disabledRulesetNames = disabled;
+ OS.notifyObservers(ABE, ABE.RULES_CHANGED_TOPIC, null);
+ },
+
+ saveRuleset: function(name, source) {
+ COMPAT.setStringPref(this.prefs, "rulesets." + name, source);
+ },
+
+ persist: function() {
+ ABE.prefService.savePrefFile(null);
+ },
+
+ _migrateLegacyFiles: function() {
+ var ret = 0;
+ try {
+ var dir = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
+ dir.append("ABE");
+ dir.append("rules");
+
+ if (dir.exists()) {
+
+ dump("Migrating legacy ABE ruleset files... ")
+
+ var entries = dir.directoryEntries;
+ while(entries.hasMoreElements()) {
+ let f = entries.getNext();
+ if (f instanceof Ci.nsIFile) {
+ let fname = f.leafName;
+ if (/^[^\.\s]*\.abe$/i.test(fname)) {
+ try {
+ this.saveRuleset(fname.replace(/\.abe$/i, ''), IO.readFile(f));
+ ret++;
+ } catch(e) {
+ dump(e + "\n");
+ }
+ }
+ }
+ }
+ this.persist();
+ }
+ dump(ret + " migrated.\n")
+ } catch(e) {
+ dump("Error migrating legacy ABE ruleset files: " + e + "\n");
+ }
+ return ret;
+ }
+}
+
+var WAN = {
+ IP_CHANGE_TOPIC: "abe:wan-iface-ip-changed",
+ ip: null,
+ ipMatcher: null,
+ fingerprint: '',
+ findMaxInterval: 86400000, // 1 day
+ checkInterval: 14400000, // 4 hours
+ fingerInterval: 900000, // 1/4 hour
+ checkURL: "https://secure.informaction.com/ipecho/",
+ lastFound: 0,
+ lastCheck: 0,
+ skipIfProxied: true,
+ noResource: false,
+ logging: true,
+ fingerprintLogging: false,
+ fingerprintUA: "Mozilla/5.0 (ABE, https://noscript.net/abe/wan)",
+ fingerprintHeader: "X-ABE-Fingerprint",
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
+
+ log: function(msg) {
+ var cs = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
+ return (this.log = function(msg) {
+ if (this.logging) cs.logStringMessage("[ABE WAN] " + msg);
+ })(msg);
+
+ },
+
+ _enabled: false,
+ _timer: null,
+ _observing: false,
+ get enabled() {
+ return this._enabled;
+ },
+ set enabled(b) {
+ if (!IPC.parent) return false;
+
+ if (this._timer) this._timer.cancel();
+ if (b) {
+ const t = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ t.initWithCallback({
+ notify: function() { WAN._periodic() },
+ context: null
+ }, this.checkInterval, t.TYPE_REPEATING_SLACK);
+ this._timer = t;
+ Thread.delay(this._periodic, 1000, this, [this._enabled != b]);
+ if (!this._observing) {
+ this._observing = true;
+ OS.addObserver(this, "network:offline-status-changed", true);
+ OS.addObserver(this, "wake_notification", true);
+ }
+ } else {
+ this._timer = this.ip = this.ipMatcher = null;
+ if (this._observing) {
+ this._observing = false;
+ OS.removeObserver(this, "network:offline-status-changed");
+ OS.removeObserver(this, "wake_notification");
+ }
+ }
+ return (this._enabled = b);
+ },
+ _observingHTTP: false,
+
+ observe: function(subject, topic, data) {
+
+ if (!this.enabled) return;
+
+ switch(topic) {
+ case "wake_notification":
+ if (!this._observingHTTP) OS.addObserver(this, "http-on-examine-response", true);
+ return;
+ case "http-on-examine-response":
+ OS.removeObserver(this, "http-on-examine-response");
+ this._observingHTTP = false;
+ break;
+ case "network:offline-status-changed":
+ if (data === "online")
+ break;
+ default:
+ return;
+ }
+
+ this._periodic(true);
+ },
+
+ _periodic: function(forceFind) {
+ if (forceFind) this.lastFound = 0;
+
+ var t = Date.now();
+ if (forceFind ||
+ t - this.lastFound > this.findMaxInterval ||
+ t - this.lastCheck > this.checkInterval) {
+ this.findIP(this._findCallback);
+ } else if (this.fingerprint) {
+ this._takeFingerprint(this.ip, this._fingerprintCallback);
+ }
+ this.lastCheck = t;
+ },
+
+ _findCallback: function(ip) {
+ WAN._takeFingerprint(ip);
+ },
+ _fingerprintCallback: function(fingerprint, ip) {
+ if (fingerprint != WAN.fingerprint) {
+ WAN.log("Resource reacheable on WAN IP " + ip + " changed!");
+ if (ip == WAN.ip) WAN._periodic(true);
+ }
+ },
+
+ _takeFingerprint: function(ip, callback) {
+ if (!ip) {
+ this.log("Can't fingerprint a null IP");
+ return;
+ }
+ var url = "http://" + (ip.indexOf(':') > -1 ? "[" + ip + "]" : ip);
+ var xhr = this._createAnonXHR(url);
+ var ch = xhr.channel;
+ ch.setRequestHeader("User-Agent", this.fingerprintUA, false);
+ ch.loadFlags = ch.loadFlags & ~ch.LOAD_ANONYMOUS; // prevents redirect loops on some routers
+ var self = this;
+ xhr.addEventListener("readystatechange", function() {
+
+ if (xhr.readyState == 4) {
+
+ var fingerprint = '';
+ try {
+ const ch = xhr.channel;
+
+ if (!ch.status) fingerprint =
+ xhr.status + " " + xhr.statusText + "\n" +
+ (xhr.getAllResponseHeaders() + "\n" + xhr.responseText)
+ .replace(/\d/g, '').replace(/\b[a-f]+\b/gi, ''); // remove decimal and hex noise
+ } catch(e) {
+ self.log(e);
+ }
+
+ if (self.fingerprintLogging)
+ self.log("Fingerprint for " + url + " = " + fingerprint);
+
+ if (fingerprint && /^\s*Off\s*/i.test(xhr.getResponseHeader(self.fingerprintHeader)))
+ fingerprint = '';
+
+ if (callback) callback(fingerprint, ip);
+ self.fingerprint = fingerprint;
+ }
+ }, false);
+ xhr.send(null);
+
+ },
+
+ _createAnonXHR: function(url, noproxy) {
+ var xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
+ xhr.mozBackgroundRequest = true;
+ xhr.open("GET", url, true);
+ const ch = xhr.channel;
+ const proxyInfo = noproxy && IOUtil.getProxyInfo(ch);
+ if (!proxyInfo || proxyInfo.type == "direct" || proxyInfo.host && DNS.isLocalHost(proxyInfo.host)) {
+ if ((ch instanceof Ci.nsIHttpChannel)) {
+ // cleanup headers
+ this._requestHeaders(ch).forEach(function(h) {
+ if (h != 'Host') ch.setRequestHeader(h, '', false); // clear header
+ });
+ }
+ ch.loadFlags = ch.LOAD_BYPASS_CACHE | ch.LOAD_ANONYMOUS;
+ } else xhr = null;
+ return xhr;
+ },
+
+ _callbacks: null,
+ _finding: false,
+ findIP: function(callback) {
+ if (callback) (this._callbacks = this._callbacks || []).push(callback);
+ if (IOS.offline) {
+ this._findIPDone(null, "offline");
+ return;
+ }
+ if (this._finding) return;
+ this._finding = true;
+ var sent = false;
+ try {
+ var xhr = this._createAnonXHR(this.checkURL,this.skipIfProxied);
+ if (xhr) {
+ let self = this;
+ xhr.addEventListener("readystatechange", function() {
+ if (xhr.readyState == 4) {
+ let ip = null;
+ if (xhr.status == 200) {
+ ip = xhr.responseText.replace(/\s+/g, '');
+ if (!/^[\da-f\.:]+$/i.test(ip)) ip = null;
+ }
+ self._findIPDone(ip, xhr.responseText);
+ }
+ }, false);
+ xhr.send(null);
+ this.log("Trying to detect WAN IP...");
+ sent = true;
+ }
+ } catch(e) {
+ this.log(e + " - " + e.stack)
+ } finally {
+ this._finding = sent;
+ if (!sent) this._findIPDone(null);
+ }
+ },
+
+ _findIPDone: function(ip) {
+ let ipMatcher = AddressMatcher.create(ip);
+ if (!ipMatcher) ip = null;
+ if (ip) {
+ try {
+ if (this._callbacks) {
+ for (let cb of this._callbacks) cb(ip);
+ this._callbacks = null;
+ }
+ } catch(e) {
+ this.log(e);
+ }
+
+ if (ip != this.ip) {
+ OS.notifyObservers(this, this.IP_CHANGE_TOPIC, ip);
+ }
+
+ this.ip = ip;
+ this.ipMatcher = ipMatcher;
+ this.lastFound = Date.now();
+
+ this.log("Detected WAN IP " + ip);
+ } else {
+ this.lastFound = 0;
+ this.fingerprint = '';
+ this.log("WAN IP not detected!");
+ }
+
+ this._finding = false;
+ },
+
+
+ _requestHeaders: function(ch) {
+ var hh = [];
+ if (ch instanceof Ci.nsIHttpChannel)
+ ch.visitRequestHeaders({
+ visitHeader: function(name, value) { hh.push(name); }
+ });
+ return hh;
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/ABELexer.js b/extensions/noscript/chrome/content/noscript/ABELexer.js
new file mode 100644
index 0000000..e4f811e
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/ABELexer.js
@@ -0,0 +1,1378 @@
+// $ANTLR 3.1.1 ABE.g 2017-07-26 00:44:40
+
+var ABELexer = function(input, state) {
+// alternate constructor @todo
+// public ABELexer(CharStream input)
+// public ABELexer(CharStream input, RecognizerSharedState state) {
+ if (!state) {
+ state = new org.antlr.runtime.RecognizerSharedState();
+ }
+
+ (function(){
+ }).call(this);
+
+ this.dfa8 = new ABELexer.DFA8(this);
+ this.dfa11 = new ABELexer.DFA11(this);
+ ABELexer.superclass.constructor.call(this, input, state);
+
+
+};
+
+org.antlr.lang.augmentObject(ABELexer, {
+ INC_TYPE: 11,
+ T_FROM: 14,
+ T__29: 29,
+ GLOB: 17,
+ HTTPVERB: 7,
+ T__28: 28,
+ A_LOGOUT: 21,
+ A_DENY: 20,
+ T_ACTION: 4,
+ SUB: 8,
+ T_METHODS: 5,
+ EOF: -1,
+ URI: 18,
+ T__30: 30,
+ INC: 9,
+ WS: 26,
+ LPAR: 10,
+ COMMA: 12,
+ URI_PART: 25,
+ A_SANDBOX: 22,
+ URI_START: 24,
+ ALL: 6,
+ A_ACCEPT: 23,
+ REGEXP: 16,
+ LOCATION: 19,
+ RPAR: 13,
+ T_SITE: 15,
+ COMMENT: 27
+});
+
+(function(){
+var HIDDEN = org.antlr.runtime.Token.HIDDEN_CHANNEL,
+ EOF = org.antlr.runtime.Token.EOF;
+org.antlr.lang.extend(ABELexer, org.antlr.runtime.Lexer, {
+ INC_TYPE : 11,
+ T_FROM : 14,
+ T__29 : 29,
+ GLOB : 17,
+ HTTPVERB : 7,
+ T__28 : 28,
+ A_LOGOUT : 21,
+ A_DENY : 20,
+ T_ACTION : 4,
+ SUB : 8,
+ T_METHODS : 5,
+ EOF : -1,
+ URI : 18,
+ T__30 : 30,
+ INC : 9,
+ WS : 26,
+ LPAR : 10,
+ COMMA : 12,
+ URI_PART : 25,
+ A_SANDBOX : 22,
+ URI_START : 24,
+ ALL : 6,
+ A_ACCEPT : 23,
+ REGEXP : 16,
+ LOCATION : 19,
+ RPAR : 13,
+ T_SITE : 15,
+ COMMENT : 27,
+ getGrammarFileName: function() { return "ABE.g"; }
+});
+org.antlr.lang.augmentObject(ABELexer.prototype, {
+ // $ANTLR start T__28
+ mT__28: function() {
+ try {
+ var _type = this.T__28;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:7:7: ( 'SELF' )
+ // ABE.g:7:9: 'SELF'
+ this.match("SELF");
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "T__28",
+
+ // $ANTLR start T__29
+ mT__29: function() {
+ try {
+ var _type = this.T__29;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:8:7: ( 'SELF+' )
+ // ABE.g:8:9: 'SELF+'
+ this.match("SELF+");
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "T__29",
+
+ // $ANTLR start T__30
+ mT__30: function() {
+ try {
+ var _type = this.T__30;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:9:7: ( 'SELF++' )
+ // ABE.g:9:9: 'SELF++'
+ this.match("SELF++");
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "T__30",
+
+ // $ANTLR start T_SITE
+ mT_SITE: function() {
+ try {
+ var _type = this.T_SITE;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:27:11: ( ( 'Site' | 'Request' ) )
+ // ABE.g:27:13: ( 'Site' | 'Request' )
+ // ABE.g:27:13: ( 'Site' | 'Request' )
+ var alt1=2;
+ var LA1_0 = this.input.LA(1);
+
+ if ( (LA1_0=='S') ) {
+ alt1=1;
+ }
+ else if ( (LA1_0=='R') ) {
+ alt1=2;
+ }
+ else {
+ var nvae =
+ new org.antlr.runtime.NoViableAltException("", 1, 0, this.input);
+
+ throw nvae;
+ }
+ switch (alt1) {
+ case 1 :
+ // ABE.g:27:14: 'Site'
+ this.match("Site");
+
+
+
+ break;
+ case 2 :
+ // ABE.g:27:23: 'Request'
+ this.match("Request");
+
+
+
+ break;
+
+ }
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "T_SITE",
+
+ // $ANTLR start T_FROM
+ mT_FROM: function() {
+ try {
+ var _type = this.T_FROM;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:28:11: ( ( 'f' | 'F' ) 'rom' )
+ // ABE.g:28:13: ( 'f' | 'F' ) 'rom'
+ if ( this.input.LA(1)=='F'||this.input.LA(1)=='f' ) {
+ this.input.consume();
+
+ }
+ else {
+ var mse = new org.antlr.runtime.MismatchedSetException(null,this.input);
+ this.recover(mse);
+ throw mse;}
+
+ this.match("rom");
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "T_FROM",
+
+ // $ANTLR start A_DENY
+ mA_DENY: function() {
+ try {
+ var _type = this.A_DENY;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:29:11: ( 'Deny' )
+ // ABE.g:29:13: 'Deny'
+ this.match("Deny");
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "A_DENY",
+
+ // $ANTLR start A_LOGOUT
+ mA_LOGOUT: function() {
+ try {
+ var _type = this.A_LOGOUT;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:30:11: ( 'Logout' | 'Anon' ( 'ymize' )? )
+ var alt3=2;
+ var LA3_0 = this.input.LA(1);
+
+ if ( (LA3_0=='L') ) {
+ alt3=1;
+ }
+ else if ( (LA3_0=='A') ) {
+ alt3=2;
+ }
+ else {
+ var nvae =
+ new org.antlr.runtime.NoViableAltException("", 3, 0, this.input);
+
+ throw nvae;
+ }
+ switch (alt3) {
+ case 1 :
+ // ABE.g:30:13: 'Logout'
+ this.match("Logout");
+
+
+
+ break;
+ case 2 :
+ // ABE.g:30:24: 'Anon' ( 'ymize' )?
+ this.match("Anon");
+
+ // ABE.g:30:31: ( 'ymize' )?
+ var alt2=2;
+ var LA2_0 = this.input.LA(1);
+
+ if ( (LA2_0=='y') ) {
+ alt2=1;
+ }
+ switch (alt2) {
+ case 1 :
+ // ABE.g:30:31: 'ymize'
+ this.match("ymize");
+
+
+
+ break;
+
+ }
+
+
+
+ break;
+
+ }
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "A_LOGOUT",
+
+ // $ANTLR start A_SANDBOX
+ mA_SANDBOX: function() {
+ try {
+ var _type = this.A_SANDBOX;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:31:11: ( 'Sandbox' )
+ // ABE.g:31:13: 'Sandbox'
+ this.match("Sandbox");
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "A_SANDBOX",
+
+ // $ANTLR start A_ACCEPT
+ mA_ACCEPT: function() {
+ try {
+ var _type = this.A_ACCEPT;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:32:11: ( 'Accept' )
+ // ABE.g:32:13: 'Accept'
+ this.match("Accept");
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "A_ACCEPT",
+
+ // $ANTLR start URI_START
+ mURI_START: function() {
+ try {
+ // ABE.g:34:20: ( 'a' .. 'z' | '0' .. '9' )
+ // ABE.g:
+ if ( (this.input.LA(1)>='0' && this.input.LA(1)<='9')||(this.input.LA(1)>='a' && this.input.LA(1)<='z') ) {
+ this.input.consume();
+
+ }
+ else {
+ var mse = new org.antlr.runtime.MismatchedSetException(null,this.input);
+ this.recover(mse);
+ throw mse;}
+
+
+
+
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "URI_START",
+
+ // $ANTLR start URI_PART
+ mURI_PART: function() {
+ try {
+ // ABE.g:35:20: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '-' | '.' | '[' | ']' | ':' | '/' | '@' | '~' | ';' | ',' | '?' | '&' | '=' | '%' | '#' )
+ // ABE.g:
+ if ( this.input.LA(1)=='#'||(this.input.LA(1)>='%' && this.input.LA(1)<='&')||(this.input.LA(1)>=',' && this.input.LA(1)<=';')||this.input.LA(1)=='='||(this.input.LA(1)>='?' && this.input.LA(1)<='[')||this.input.LA(1)==']'||this.input.LA(1)=='_'||(this.input.LA(1)>='a' && this.input.LA(1)<='z')||this.input.LA(1)=='~' ) {
+ this.input.consume();
+
+ }
+ else {
+ var mse = new org.antlr.runtime.MismatchedSetException(null,this.input);
+ this.recover(mse);
+ throw mse;}
+
+
+
+
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "URI_PART",
+
+ // $ANTLR start LOCATION
+ mLOCATION: function() {
+ try {
+ var _type = this.LOCATION;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:38:11: ( 'LOCAL' )
+ // ABE.g:38:13: 'LOCAL'
+ this.match("LOCAL");
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "LOCATION",
+
+ // $ANTLR start URI
+ mURI: function() {
+ try {
+ var _type = this.URI;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:39:11: ( URI_START ( URI_PART )+ )
+ // ABE.g:39:13: URI_START ( URI_PART )+
+ this.mURI_START();
+ // ABE.g:39:23: ( URI_PART )+
+ var cnt4=0;
+ loop4:
+ do {
+ var alt4=2;
+ var LA4_0 = this.input.LA(1);
+
+ if ( (LA4_0=='#'||(LA4_0>='%' && LA4_0<='&')||(LA4_0>=',' && LA4_0<=';')||LA4_0=='='||(LA4_0>='?' && LA4_0<='[')||LA4_0==']'||LA4_0=='_'||(LA4_0>='a' && LA4_0<='z')||LA4_0=='~') ) {
+ alt4=1;
+ }
+
+
+ switch (alt4) {
+ case 1 :
+ // ABE.g:39:23: URI_PART
+ this.mURI_PART();
+
+
+ break;
+
+ default :
+ if ( cnt4 >= 1 ) {
+ break loop4;
+ }
+ var eee = new org.antlr.runtime.EarlyExitException(4, this.input);
+ throw eee;
+ }
+ cnt4++;
+ } while (true);
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "URI",
+
+ // $ANTLR start GLOB
+ mGLOB: function() {
+ try {
+ var _type = this.GLOB;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:40:11: ( ( URI_START | '*' | '.' ) ( URI_PART | '*' )* )
+ // ABE.g:40:13: ( URI_START | '*' | '.' ) ( URI_PART | '*' )*
+ if ( this.input.LA(1)=='*'||this.input.LA(1)=='.'||(this.input.LA(1)>='0' && this.input.LA(1)<='9')||(this.input.LA(1)>='a' && this.input.LA(1)<='z') ) {
+ this.input.consume();
+
+ }
+ else {
+ var mse = new org.antlr.runtime.MismatchedSetException(null,this.input);
+ this.recover(mse);
+ throw mse;}
+
+ // ABE.g:40:37: ( URI_PART | '*' )*
+ loop5:
+ do {
+ var alt5=2;
+ var LA5_0 = this.input.LA(1);
+
+ if ( (LA5_0=='#'||(LA5_0>='%' && LA5_0<='&')||LA5_0=='*'||(LA5_0>=',' && LA5_0<=';')||LA5_0=='='||(LA5_0>='?' && LA5_0<='[')||LA5_0==']'||LA5_0=='_'||(LA5_0>='a' && LA5_0<='z')||LA5_0=='~') ) {
+ alt5=1;
+ }
+
+
+ switch (alt5) {
+ case 1 :
+ // ABE.g:
+ if ( this.input.LA(1)=='#'||(this.input.LA(1)>='%' && this.input.LA(1)<='&')||this.input.LA(1)=='*'||(this.input.LA(1)>=',' && this.input.LA(1)<=';')||this.input.LA(1)=='='||(this.input.LA(1)>='?' && this.input.LA(1)<='[')||this.input.LA(1)==']'||this.input.LA(1)=='_'||(this.input.LA(1)>='a' && this.input.LA(1)<='z')||this.input.LA(1)=='~' ) {
+ this.input.consume();
+
+ }
+ else {
+ var mse = new org.antlr.runtime.MismatchedSetException(null,this.input);
+ this.recover(mse);
+ throw mse;}
+
+
+
+ break;
+
+ default :
+ break loop5;
+ }
+ } while (true);
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "GLOB",
+
+ // $ANTLR start REGEXP
+ mREGEXP: function() {
+ try {
+ var _type = this.REGEXP;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:41:11: ( '^' (~ '\\n' )+ )
+ // ABE.g:41:13: '^' (~ '\\n' )+
+ this.match('^');
+ // ABE.g:41:17: (~ '\\n' )+
+ var cnt6=0;
+ loop6:
+ do {
+ var alt6=2;
+ var LA6_0 = this.input.LA(1);
+
+ if ( ((LA6_0>='\u0000' && LA6_0<='\t')||(LA6_0>='\u000B' && LA6_0<='\uFFFF')) ) {
+ alt6=1;
+ }
+
+
+ switch (alt6) {
+ case 1 :
+ // ABE.g:41:17: ~ '\\n'
+ if ( (this.input.LA(1)>='\u0000' && this.input.LA(1)<='\t')||(this.input.LA(1)>='\u000B' && this.input.LA(1)<='\uFFFF') ) {
+ this.input.consume();
+
+ }
+ else {
+ var mse = new org.antlr.runtime.MismatchedSetException(null,this.input);
+ this.recover(mse);
+ throw mse;}
+
+
+
+ break;
+
+ default :
+ if ( cnt6 >= 1 ) {
+ break loop6;
+ }
+ var eee = new org.antlr.runtime.EarlyExitException(6, this.input);
+ throw eee;
+ }
+ cnt6++;
+ } while (true);
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "REGEXP",
+
+ // $ANTLR start ALL
+ mALL: function() {
+ try {
+ var _type = this.ALL;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:43:11: ( 'ALL' )
+ // ABE.g:43:13: 'ALL'
+ this.match("ALL");
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "ALL",
+
+ // $ANTLR start SUB
+ mSUB: function() {
+ try {
+ var _type = this.SUB;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:44:11: ( 'SUB' )
+ // ABE.g:44:13: 'SUB'
+ this.match("SUB");
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "SUB",
+
+ // $ANTLR start INC
+ mINC: function() {
+ try {
+ var _type = this.INC;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:45:11: ( 'INC' ( 'LUSION' )? )
+ // ABE.g:45:13: 'INC' ( 'LUSION' )?
+ this.match("INC");
+
+ // ABE.g:45:19: ( 'LUSION' )?
+ var alt7=2;
+ var LA7_0 = this.input.LA(1);
+
+ if ( (LA7_0=='L') ) {
+ alt7=1;
+ }
+ switch (alt7) {
+ case 1 :
+ // ABE.g:45:19: 'LUSION'
+ this.match("LUSION");
+
+
+
+ break;
+
+ }
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "INC",
+
+ // $ANTLR start HTTPVERB
+ mHTTPVERB: function() {
+ try {
+ var _type = this.HTTPVERB;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:46:11: ( 'GET' | 'POST' | 'PUT' | 'HEAD' | 'PATCH' | 'DELETE' | 'TRACE' | 'OPTIONS' )
+ var alt8=8;
+ alt8 = this.dfa8.predict(this.input);
+ switch (alt8) {
+ case 1 :
+ // ABE.g:46:13: 'GET'
+ this.match("GET");
+
+
+
+ break;
+ case 2 :
+ // ABE.g:46:21: 'POST'
+ this.match("POST");
+
+
+
+ break;
+ case 3 :
+ // ABE.g:46:30: 'PUT'
+ this.match("PUT");
+
+
+
+ break;
+ case 4 :
+ // ABE.g:46:38: 'HEAD'
+ this.match("HEAD");
+
+
+
+ break;
+ case 5 :
+ // ABE.g:46:47: 'PATCH'
+ this.match("PATCH");
+
+
+
+ break;
+ case 6 :
+ // ABE.g:46:57: 'DELETE'
+ this.match("DELETE");
+
+
+
+ break;
+ case 7 :
+ // ABE.g:46:68: 'TRACE'
+ this.match("TRACE");
+
+
+
+ break;
+ case 8 :
+ // ABE.g:46:78: 'OPTIONS'
+ this.match("OPTIONS");
+
+
+
+ break;
+
+ }
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "HTTPVERB",
+
+ // $ANTLR start INC_TYPE
+ mINC_TYPE: function() {
+ try {
+ var _type = this.INC_TYPE;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:47:11: ( 'A' .. 'Z' ( 'A' .. 'Z' | 'A' .. 'Z' '_' 'A' .. 'Z' )+ )
+ // ABE.g:47:13: 'A' .. 'Z' ( 'A' .. 'Z' | 'A' .. 'Z' '_' 'A' .. 'Z' )+
+ this.matchRange('A','Z');
+ // ABE.g:47:22: ( 'A' .. 'Z' | 'A' .. 'Z' '_' 'A' .. 'Z' )+
+ var cnt9=0;
+ loop9:
+ do {
+ var alt9=3;
+ var LA9_0 = this.input.LA(1);
+
+ if ( ((LA9_0>='A' && LA9_0<='Z')) ) {
+ var LA9_2 = this.input.LA(2);
+
+ if ( (LA9_2=='_') ) {
+ alt9=2;
+ }
+
+ else {
+ alt9=1;
+ }
+
+ }
+
+
+ switch (alt9) {
+ case 1 :
+ // ABE.g:47:23: 'A' .. 'Z'
+ this.matchRange('A','Z');
+
+
+ break;
+ case 2 :
+ // ABE.g:47:34: 'A' .. 'Z' '_' 'A' .. 'Z'
+ this.matchRange('A','Z');
+ this.match('_');
+ this.matchRange('A','Z');
+
+
+ break;
+
+ default :
+ if ( cnt9 >= 1 ) {
+ break loop9;
+ }
+ var eee = new org.antlr.runtime.EarlyExitException(9, this.input);
+ throw eee;
+ }
+ cnt9++;
+ } while (true);
+
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "INC_TYPE",
+
+ // $ANTLR start COMMA
+ mCOMMA: function() {
+ try {
+ var _type = this.COMMA;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:50:11: ( ',' )
+ // ABE.g:50:13: ','
+ this.match(',');
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "COMMA",
+
+ // $ANTLR start LPAR
+ mLPAR: function() {
+ try {
+ var _type = this.LPAR;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:51:11: ( '(' )
+ // ABE.g:51:13: '('
+ this.match('(');
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "LPAR",
+
+ // $ANTLR start RPAR
+ mRPAR: function() {
+ try {
+ var _type = this.RPAR;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:52:11: ( ')' )
+ // ABE.g:52:13: ')'
+ this.match(')');
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "RPAR",
+
+ // $ANTLR start WS
+ mWS: function() {
+ try {
+ var _type = this.WS;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:54:11: ( ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' ) )
+ // ABE.g:54:14: ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' )
+ if ( (this.input.LA(1)>='\t' && this.input.LA(1)<='\n')||(this.input.LA(1)>='\f' && this.input.LA(1)<='\r')||this.input.LA(1)==' ' ) {
+ this.input.consume();
+
+ }
+ else {
+ var mse = new org.antlr.runtime.MismatchedSetException(null,this.input);
+ this.recover(mse);
+ throw mse;}
+
+ _channel=HIDDEN;
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "WS",
+
+ // $ANTLR start COMMENT
+ mCOMMENT: function() {
+ try {
+ var _type = this.COMMENT;
+ var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
+ // ABE.g:55:9: ( '#' (~ '\\n' )* )
+ // ABE.g:55:11: '#' (~ '\\n' )*
+ this.match('#');
+ // ABE.g:55:15: (~ '\\n' )*
+ loop10:
+ do {
+ var alt10=2;
+ var LA10_0 = this.input.LA(1);
+
+ if ( ((LA10_0>='\u0000' && LA10_0<='\t')||(LA10_0>='\u000B' && LA10_0<='\uFFFF')) ) {
+ alt10=1;
+ }
+
+
+ switch (alt10) {
+ case 1 :
+ // ABE.g:55:15: ~ '\\n'
+ if ( (this.input.LA(1)>='\u0000' && this.input.LA(1)<='\t')||(this.input.LA(1)>='\u000B' && this.input.LA(1)<='\uFFFF') ) {
+ this.input.consume();
+
+ }
+ else {
+ var mse = new org.antlr.runtime.MismatchedSetException(null,this.input);
+ this.recover(mse);
+ throw mse;}
+
+
+
+ break;
+
+ default :
+ break loop10;
+ }
+ } while (true);
+
+ _channel=HIDDEN;
+
+
+
+ this.state.type = _type;
+ this.state.channel = _channel;
+ }
+ finally {
+ }
+ },
+ // $ANTLR end "COMMENT",
+
+ mTokens: function() {
+ // ABE.g:1:8: ( T__28 | T__29 | T__30 | T_SITE | T_FROM | A_DENY | A_LOGOUT | A_SANDBOX | A_ACCEPT | LOCATION | URI | GLOB | REGEXP | ALL | SUB | INC | HTTPVERB | INC_TYPE | COMMA | LPAR | RPAR | WS | COMMENT )
+ var alt11=23;
+ alt11 = this.dfa11.predict(this.input);
+ switch (alt11) {
+ case 1 :
+ // ABE.g:1:10: T__28
+ this.mT__28();
+
+
+ break;
+ case 2 :
+ // ABE.g:1:16: T__29
+ this.mT__29();
+
+
+ break;
+ case 3 :
+ // ABE.g:1:22: T__30
+ this.mT__30();
+
+
+ break;
+ case 4 :
+ // ABE.g:1:28: T_SITE
+ this.mT_SITE();
+
+
+ break;
+ case 5 :
+ // ABE.g:1:35: T_FROM
+ this.mT_FROM();
+
+
+ break;
+ case 6 :
+ // ABE.g:1:42: A_DENY
+ this.mA_DENY();
+
+
+ break;
+ case 7 :
+ // ABE.g:1:49: A_LOGOUT
+ this.mA_LOGOUT();
+
+
+ break;
+ case 8 :
+ // ABE.g:1:58: A_SANDBOX
+ this.mA_SANDBOX();
+
+
+ break;
+ case 9 :
+ // ABE.g:1:68: A_ACCEPT
+ this.mA_ACCEPT();
+
+
+ break;
+ case 10 :
+ // ABE.g:1:77: LOCATION
+ this.mLOCATION();
+
+
+ break;
+ case 11 :
+ // ABE.g:1:86: URI
+ this.mURI();
+
+
+ break;
+ case 12 :
+ // ABE.g:1:90: GLOB
+ this.mGLOB();
+
+
+ break;
+ case 13 :
+ // ABE.g:1:95: REGEXP
+ this.mREGEXP();
+
+
+ break;
+ case 14 :
+ // ABE.g:1:102: ALL
+ this.mALL();
+
+
+ break;
+ case 15 :
+ // ABE.g:1:106: SUB
+ this.mSUB();
+
+
+ break;
+ case 16 :
+ // ABE.g:1:110: INC
+ this.mINC();
+
+
+ break;
+ case 17 :
+ // ABE.g:1:114: HTTPVERB
+ this.mHTTPVERB();
+
+
+ break;
+ case 18 :
+ // ABE.g:1:123: INC_TYPE
+ this.mINC_TYPE();
+
+
+ break;
+ case 19 :
+ // ABE.g:1:132: COMMA
+ this.mCOMMA();
+
+
+ break;
+ case 20 :
+ // ABE.g:1:138: LPAR
+ this.mLPAR();
+
+
+ break;
+ case 21 :
+ // ABE.g:1:143: RPAR
+ this.mRPAR();
+
+
+ break;
+ case 22 :
+ // ABE.g:1:148: WS
+ this.mWS();
+
+
+ break;
+ case 23 :
+ // ABE.g:1:151: COMMENT
+ this.mCOMMENT();
+
+
+ break;
+
+ }
+
+ }
+
+}, true); // important to pass true to overwrite default implementations
+
+org.antlr.lang.augmentObject(ABELexer, {
+ DFA8_eotS:
+ "\u000a\uffff",
+ DFA8_eofS:
+ "\u000a\uffff",
+ DFA8_minS:
+ "\u0001\u0044\u0001\uffff\u0001\u0041\u0007\uffff",
+ DFA8_maxS:
+ "\u0001\u0054\u0001\uffff\u0001\u0055\u0007\uffff",
+ DFA8_acceptS:
+ "\u0001\uffff\u0001\u0001\u0001\uffff\u0001\u0004\u0001\u0006\u0001"+
+ "\u0007\u0001\u0008\u0001\u0002\u0001\u0003\u0001\u0005",
+ DFA8_specialS:
+ "\u000a\uffff}>",
+ DFA8_transitionS: [
+ "\u0001\u0004\u0002\uffff\u0001\u0001\u0001\u0003\u0006\uffff"+
+ "\u0001\u0006\u0001\u0002\u0003\uffff\u0001\u0005",
+ "",
+ "\u0001\u0009\u000d\uffff\u0001\u0007\u0005\uffff\u0001\u0008",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ]
+});
+
+org.antlr.lang.augmentObject(ABELexer, {
+ DFA8_eot:
+ org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA8_eotS),
+ DFA8_eof:
+ org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA8_eofS),
+ DFA8_min:
+ org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA8_minS),
+ DFA8_max:
+ org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA8_maxS),
+ DFA8_accept:
+ org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA8_acceptS),
+ DFA8_special:
+ org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA8_specialS),
+ DFA8_transition: (function() {
+ var a = [],
+ i,
+ numStates = ABELexer.DFA8_transitionS.length;
+ for (i=0; i<numStates; i++) {
+ a.push(org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA8_transitionS[i]));
+ }
+ return a;
+ })()
+});
+
+ABELexer.DFA8 = function(recognizer) {
+ this.recognizer = recognizer;
+ this.decisionNumber = 8;
+ this.eot = ABELexer.DFA8_eot;
+ this.eof = ABELexer.DFA8_eof;
+ this.min = ABELexer.DFA8_min;
+ this.max = ABELexer.DFA8_max;
+ this.accept = ABELexer.DFA8_accept;
+ this.special = ABELexer.DFA8_special;
+ this.transition = ABELexer.DFA8_transition;
+};
+
+org.antlr.lang.extend(ABELexer.DFA8, org.antlr.runtime.DFA, {
+ getDescription: function() {
+ return "46:1: HTTPVERB : ( 'GET' | 'POST' | 'PUT' | 'HEAD' | 'PATCH' | 'DELETE' | 'TRACE' | 'OPTIONS' );";
+ },
+ dummy: null
+});
+org.antlr.lang.augmentObject(ABELexer, {
+ DFA11_eotS:
+ "\u0003\uffff\u0001\u0009\u0004\uffff\u0001\u0009\u000e\uffff\u0001"+
+ "\u0011\u0002\uffff\u0001\u0011\u0002\u002f\u0001\uffff\u0001\u0011\u0001"+
+ "\uffff\u0001\u0011\u0001\uffff\u0001\u0011\u0001\uffff\u0009\u0011\u0001"+
+ "\u003c\u0001\u002f\u0001\uffff\u0002\u0011\u0001\u0040\u0001\u0041\u0001"+
+ "\u0043\u0001\u0011\u0001\u0043\u0004\u0011\u0001\u004a\u0001\uffff\u0001"+
+ "\u0023\u0002\u0011\u0002\uffff\u0001\u0011\u0001\uffff\u0001\u0043\u0001"+
+ "\u0011\u0001\u0043\u0002\u0011\u0001\u0052\u0001\uffff\u0001\u0011\u0001"+
+ "\u0054\u0001\u0011\u0002\u0043\u0001\u0011\u0002\uffff\u0001\u0043\u0001"+
+ "\uffff\u0003\u0011\u0001\u0043\u0001\u0011\u0001\u0041",
+ DFA11_eofS:
+ "\u005b\uffff",
+ DFA11_minS:
+ "\u0001\u0009\u0002\u0041\u0001\u0023\u0004\u0041\u0001\u0023\u0002"+
+ "\uffff\u0006\u0041\u0006\uffff\u0001\u004c\u0002\uffff\u0001\u0042\u0002"+
+ "\u0023\u0001\uffff\u0001\u004c\u0001\uffff\u0001\u0043\u0001\uffff\u0001"+
+ "\u004c\u0001\uffff\u0001\u0043\u0001\u0054\u0001\u0053\u0002\u0054\u0002"+
+ "\u0041\u0001\u0054\u0001\u0046\u0001\u0041\u0001\u0023\u0001\uffff\u0001"+
+ "\u0045\u0004\u0041\u0001\u0054\u0001\u0041\u0001\u0043\u0001\u0044\u0001"+
+ "\u0043\u0001\u0049\u0001\u002b\u0001\uffff\u0001\u0023\u0001\u0054\u0001"+
+ "\u004c\u0002\uffff\u0001\u0055\u0001\uffff\u0001\u0041\u0001\u0048\u0001"+
+ "\u0041\u0001\u0045\u0001\u004f\u0001\u002b\u0001\uffff\u0001\u0045\u0001"+
+ "\u0041\u0001\u0053\u0002\u0041\u0001\u004e\u0002\uffff\u0001\u0041\u0001"+
+ "\uffff\u0001\u0049\u0001\u0053\u0001\u004f\u0001\u0041\u0001\u004e\u0001"+
+ "\u0041",
+ DFA11_maxS:
+ "\u0001\u007a\u0001\u0069\u0001\u0065\u0001\u007e\u0001\u0065\u0001"+
+ "\u006f\u0001\u006e\u0001\u0072\u0001\u007e\u0002\uffff\u0006\u005a\u0006"+
+ "\uffff\u0001\u004c\u0002\uffff\u0001\u0042\u0002\u007e\u0001\uffff\u0001"+
+ "\u004c\u0001\uffff\u0001\u0043\u0001\uffff\u0001\u004c\u0001\uffff\u0001"+
+ "\u0043\u0001\u0054\u0001\u0053\u0002\u0054\u0002\u0041\u0001\u0054\u0001"+
+ "\u0046\u0001\u005f\u0001\u007e\u0001\uffff\u0001\u0045\u0001\u0041\u0003"+
+ "\u005f\u0001\u0054\u0001\u005f\u0001\u0043\u0001\u0044\u0001\u0043\u0001"+
+ "\u0049\u0001\u005f\u0001\uffff\u0001\u007e\u0001\u0054\u0001\u004c\u0002"+
+ "\uffff\u0001\u0055\u0001\uffff\u0001\u005f\u0001\u0048\u0001\u005f\u0001"+
+ "\u0045\u0001\u004f\u0001\u002b\u0001\uffff\u0001\u0045\u0001\u005f\u0001"+
+ "\u0053\u0002\u005f\u0001\u004e\u0002\uffff\u0001\u005f\u0001\uffff\u0001"+
+ "\u0049\u0001\u0053\u0001\u004f\u0001\u005f\u0001\u004e\u0001\u005f",
+ DFA11_acceptS:
+ "\u0009\uffff\u0001\u000c\u0001\u000d\u0006\uffff\u0001\u0012\u0001"+
+ "\u0013\u0001\u0014\u0001\u0015\u0001\u0016\u0001\u0017\u0001\uffff\u0001"+
+ "\u0004\u0001\u0008\u0003\uffff\u0001\u0006\u0001\uffff\u0001\u0007\u0001"+
+ "\uffff\u0001\u0009\u0001\uffff\u0001\u0005\u000b\uffff\u0001\u000b\u000c"+
+ "\uffff\u0001\u000f\u0003\uffff\u0001\u000e\u0001\u0010\u0001\uffff\u0001"+
+ "\u0011\u0006\uffff\u0001\u0001\u0006\uffff\u0001\u0003\u0001\u0002\u0001"+
+ "\uffff\u0001\u000a\u0006\uffff",
+ DFA11_specialS:
+ "\u005b\uffff}>",
+ DFA11_transitionS: [
+ "\u0002\u0015\u0001\uffff\u0002\u0015\u0012\uffff\u0001\u0015"+
+ "\u0002\uffff\u0001\u0016\u0004\uffff\u0001\u0013\u0001\u0014"+
+ "\u0001\u0009\u0001\uffff\u0001\u0012\u0001\uffff\u0001\u0009"+
+ "\u0001\uffff\u000a\u0008\u0007\uffff\u0001\u0006\u0002\u0011"+
+ "\u0001\u0004\u0001\u0011\u0001\u0007\u0001\u000c\u0001\u000e"+
+ "\u0001\u000b\u0002\u0011\u0001\u0005\u0002\u0011\u0001\u0010"+
+ "\u0001\u000d\u0001\u0011\u0001\u0002\u0001\u0001\u0001\u000f"+
+ "\u0006\u0011\u0003\uffff\u0001\u000a\u0002\uffff\u0005\u0008"+
+ "\u0001\u0003\u0014\u0008",
+ "\u0004\u0011\u0001\u0017\u000f\u0011\u0001\u001a\u0005\u0011"+
+ "\u0006\uffff\u0001\u0019\u0007\uffff\u0001\u0018",
+ "\u001a\u0011\u000a\uffff\u0001\u0018",
+ "\u0001\u001c\u0001\uffff\u0002\u001c\u0005\uffff\u0010\u001c"+
+ "\u0001\uffff\u0001\u001c\u0001\uffff\u001d\u001c\u0001\uffff"+
+ "\u0001\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u0011\u001c"+
+ "\u0001\u001b\u0008\u001c\u0003\uffff\u0001\u001c",
+ "\u0004\u0011\u0001\u001e\u0015\u0011\u000a\uffff\u0001\u001d",
+ "\u000e\u0011\u0001\u0020\u000b\u0011\u0014\uffff\u0001\u001f",
+ "\u000b\u0011\u0001\u0022\u000e\u0011\u0008\uffff\u0001\u0021"+
+ "\u000a\uffff\u0001\u001f",
+ "\u001a\u0011\u0017\uffff\u0001\u0023",
+ "\u0001\u001c\u0001\uffff\u0002\u001c\u0005\uffff\u0010\u001c"+
+ "\u0001\uffff\u0001\u001c\u0001\uffff\u001d\u001c\u0001\uffff"+
+ "\u0001\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u001a\u001c"+
+ "\u0003\uffff\u0001\u001c",
+ "",
+ "",
+ "\u000d\u0011\u0001\u0024\u000c\u0011",
+ "\u0004\u0011\u0001\u0025\u0015\u0011",
+ "\u0001\u0028\u000d\u0011\u0001\u0026\u0005\u0011\u0001\u0027"+
+ "\u0005\u0011",
+ "\u0004\u0011\u0001\u0029\u0015\u0011",
+ "\u0011\u0011\u0001\u002a\u0008\u0011",
+ "\u000f\u0011\u0001\u002b\u000a\u0011",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "\u0001\u002c",
+ "",
+ "",
+ "\u0001\u002d",
+ "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0009"+
+ "\u0001\uffff\u0010\u001c\u0001\uffff\u0001\u001c\u0001\uffff"+
+ "\u001d\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u0001\u001c"+
+ "\u0001\uffff\u000e\u001c\u0001\u002e\u000b\u001c\u0003\uffff"+
+ "\u0001\u001c",
+ "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0009"+
+ "\u0001\uffff\u0010\u001c\u0001\uffff\u0001\u001c\u0001\uffff"+
+ "\u001d\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u0001\u001c"+
+ "\u0001\uffff\u001a\u001c\u0003\uffff\u0001\u001c",
+ "",
+ "\u0001\u0030",
+ "",
+ "\u0001\u0031",
+ "",
+ "\u0001\u0032",
+ "",
+ "\u0001\u0033",
+ "\u0001\u0034",
+ "\u0001\u0035",
+ "\u0001\u0036",
+ "\u0001\u0037",
+ "\u0001\u0038",
+ "\u0001\u0039",
+ "\u0001\u003a",
+ "\u0001\u003b",
+ "\u001a\u0011\u0004\uffff\u0001\u0011",
+ "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0009"+
+ "\u0001\uffff\u0010\u001c\u0001\uffff\u0001\u001c\u0001\uffff"+
+ "\u001d\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u0001\u001c"+
+ "\u0001\uffff\u000c\u001c\u0001\u003d\u000d\u001c\u0003\uffff"+
+ "\u0001\u001c",
+ "",
+ "\u0001\u003e",
+ "\u0001\u003f",
+ "\u001a\u0011\u0004\uffff\u0001\u0011",
+ "\u000b\u0011\u0001\u0042\u000e\u0011\u0004\uffff\u0001\u0011",
+ "\u001a\u0011\u0004\uffff\u0001\u0011",
+ "\u0001\u0044",
+ "\u001a\u0011\u0004\uffff\u0001\u0011",
+ "\u0001\u0045",
+ "\u0001\u0046",
+ "\u0001\u0047",
+ "\u0001\u0048",
+ "\u0001\u0049\u0015\uffff\u001a\u0011\u0004\uffff\u0001\u0011",
+ "",
+ "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0009"+
+ "\u0001\uffff\u0010\u001c\u0001\uffff\u0001\u001c\u0001\uffff"+
+ "\u001d\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u0001\u001c"+
+ "\u0001\uffff\u001a\u001c\u0003\uffff\u0001\u001c",
+ "\u0001\u004b",
+ "\u0001\u004c",
+ "",
+ "",
+ "\u0001\u004d",
+ "",
+ "\u001a\u0011\u0004\uffff\u0001\u0011",
+ "\u0001\u004e",
+ "\u001a\u0011\u0004\uffff\u0001\u0011",
+ "\u0001\u004f",
+ "\u0001\u0050",
+ "\u0001\u0051",
+ "",
+ "\u0001\u0053",
+ "\u001a\u0011\u0004\uffff\u0001\u0011",
+ "\u0001\u0055",
+ "\u001a\u0011\u0004\uffff\u0001\u0011",
+ "\u001a\u0011\u0004\uffff\u0001\u0011",
+ "\u0001\u0056",
+ "",
+ "",
+ "\u001a\u0011\u0004\uffff\u0001\u0011",
+ "",
+ "\u0001\u0057",
+ "\u0001\u0058",
+ "\u0001\u0059",
+ "\u001a\u0011\u0004\uffff\u0001\u0011",
+ "\u0001\u005a",
+ "\u001a\u0011\u0004\uffff\u0001\u0011"
+ ]
+});
+
+org.antlr.lang.augmentObject(ABELexer, {
+ DFA11_eot:
+ org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA11_eotS),
+ DFA11_eof:
+ org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA11_eofS),
+ DFA11_min:
+ org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA11_minS),
+ DFA11_max:
+ org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA11_maxS),
+ DFA11_accept:
+ org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA11_acceptS),
+ DFA11_special:
+ org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA11_specialS),
+ DFA11_transition: (function() {
+ var a = [],
+ i,
+ numStates = ABELexer.DFA11_transitionS.length;
+ for (i=0; i<numStates; i++) {
+ a.push(org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA11_transitionS[i]));
+ }
+ return a;
+ })()
+});
+
+ABELexer.DFA11 = function(recognizer) {
+ this.recognizer = recognizer;
+ this.decisionNumber = 11;
+ this.eot = ABELexer.DFA11_eot;
+ this.eof = ABELexer.DFA11_eof;
+ this.min = ABELexer.DFA11_min;
+ this.max = ABELexer.DFA11_max;
+ this.accept = ABELexer.DFA11_accept;
+ this.special = ABELexer.DFA11_special;
+ this.transition = ABELexer.DFA11_transition;
+};
+
+org.antlr.lang.extend(ABELexer.DFA11, org.antlr.runtime.DFA, {
+ getDescription: function() {
+ return "1:1: Tokens : ( T__28 | T__29 | T__30 | T_SITE | T_FROM | A_DENY | A_LOGOUT | A_SANDBOX | A_ACCEPT | LOCATION | URI | GLOB | REGEXP | ALL | SUB | INC | HTTPVERB | INC_TYPE | COMMA | LPAR | RPAR | WS | COMMENT );";
+ },
+ dummy: null
+});
+
+})(); \ No newline at end of file
diff --git a/extensions/noscript/chrome/content/noscript/ABEParser.js b/extensions/noscript/chrome/content/noscript/ABEParser.js
new file mode 100644
index 0000000..a347bc0
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/ABEParser.js
@@ -0,0 +1,1466 @@
+// $ANTLR 3.1.1 ABE.g 2017-07-26 00:44:40
+
+var ABEParser = function(input, state) {
+ if (!state) {
+ state = new org.antlr.runtime.RecognizerSharedState();
+ }
+
+ (function(){
+ }).call(this);
+
+ ABEParser.superclass.constructor.call(this, input, state);
+
+
+
+
+ /* @todo only create adaptor if output=AST */
+ this.adaptor = new org.antlr.runtime.tree.CommonTreeAdaptor();
+
+};
+
+org.antlr.lang.augmentObject(ABEParser, {
+ INC_TYPE: 11,
+ T_FROM: 14,
+ GLOB: 17,
+ T__29: 29,
+ HTTPVERB: 7,
+ T__28: 28,
+ A_LOGOUT: 21,
+ A_DENY: 20,
+ T_ACTION: 4,
+ SUB: 8,
+ T_METHODS: 5,
+ EOF: -1,
+ URI: 18,
+ T__30: 30,
+ INC: 9,
+ WS: 26,
+ LPAR: 10,
+ URI_PART: 25,
+ COMMA: 12,
+ A_SANDBOX: 22,
+ URI_START: 24,
+ A_ACCEPT: 23,
+ ALL: 6,
+ REGEXP: 16,
+ LOCATION: 19,
+ RPAR: 13,
+ T_SITE: 15,
+ COMMENT: 27
+});
+
+(function(){
+// public class variables
+var INC_TYPE= 11,
+ T_FROM= 14,
+ GLOB= 17,
+ T__29= 29,
+ HTTPVERB= 7,
+ T__28= 28,
+ A_LOGOUT= 21,
+ A_DENY= 20,
+ T_ACTION= 4,
+ SUB= 8,
+ T_METHODS= 5,
+ EOF= -1,
+ URI= 18,
+ T__30= 30,
+ INC= 9,
+ WS= 26,
+ LPAR= 10,
+ URI_PART= 25,
+ COMMA= 12,
+ A_SANDBOX= 22,
+ URI_START= 24,
+ A_ACCEPT= 23,
+ ALL= 6,
+ REGEXP= 16,
+ LOCATION= 19,
+ RPAR= 13,
+ T_SITE= 15,
+ COMMENT= 27;
+
+// public instance methods/vars
+org.antlr.lang.extend(ABEParser, org.antlr.runtime.Parser, {
+
+ setTreeAdaptor: function(adaptor) {
+ this.adaptor = adaptor;
+ },
+ getTreeAdaptor: function() {
+ return this.adaptor;
+ },
+
+ getTokenNames: function() { return ABEParser.tokenNames; },
+ getGrammarFileName: function() { return "ABE.g"; }
+});
+org.antlr.lang.augmentObject(ABEParser.prototype, {
+
+ // inline static return class
+ ruleset_return: (function() {
+ ABEParser.ruleset_return = function(){};
+ org.antlr.lang.extend(ABEParser.ruleset_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:13:1: ruleset : ( rule )* EOF ;
+ // $ANTLR start "ruleset"
+ ruleset: function() {
+ var retval = new ABEParser.ruleset_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var EOF2 = null;
+ var rule1 = null;
+
+ var EOF2_tree=null;
+
+ try {
+ // ABE.g:13:11: ( ( rule )* EOF )
+ // ABE.g:13:13: ( rule )* EOF
+ root_0 = this.adaptor.nil();
+
+ // ABE.g:13:13: ( rule )*
+ loop1:
+ do {
+ var alt1=2;
+ var LA1_0 = this.input.LA(1);
+
+ if ( (LA1_0==T_SITE) ) {
+ alt1=1;
+ }
+
+
+ switch (alt1) {
+ case 1 :
+ // ABE.g:13:13: rule
+ this.pushFollow(ABEParser.FOLLOW_rule_in_ruleset49);
+ rule1=this.rule();
+
+ this.state._fsp--;
+
+ this.adaptor.addChild(root_0, rule1.getTree());
+
+
+ break;
+
+ default :
+ break loop1;
+ }
+ } while (true);
+
+ EOF2=this.match(this.input,EOF,ABEParser.FOLLOW_EOF_in_ruleset52);
+ EOF2_tree = this.adaptor.create(EOF2);
+ this.adaptor.addChild(root_0, EOF2_tree);
+
+
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ rule_return: (function() {
+ ABEParser.rule_return = function(){};
+ org.antlr.lang.extend(ABEParser.rule_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:14:1: rule : subject ( predicate )+ -> subject ( predicate )+ ;
+ // $ANTLR start "rule"
+ rule: function() {
+ var retval = new ABEParser.rule_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var subject3 = null;
+ var predicate4 = null;
+
+ var stream_subject=new org.antlr.runtime.tree.RewriteRuleSubtreeStream(this.adaptor,"rule subject");
+ var stream_predicate=new org.antlr.runtime.tree.RewriteRuleSubtreeStream(this.adaptor,"rule predicate");
+ try {
+ // ABE.g:14:11: ( subject ( predicate )+ -> subject ( predicate )+ )
+ // ABE.g:14:13: subject ( predicate )+
+ this.pushFollow(ABEParser.FOLLOW_subject_in_rule65);
+ subject3=this.subject();
+
+ this.state._fsp--;
+
+ stream_subject.add(subject3.getTree());
+ // ABE.g:14:21: ( predicate )+
+ var cnt2=0;
+ loop2:
+ do {
+ var alt2=2;
+ var LA2_0 = this.input.LA(1);
+
+ if ( ((LA2_0>=A_DENY && LA2_0<=A_ACCEPT)) ) {
+ alt2=1;
+ }
+
+
+ switch (alt2) {
+ case 1 :
+ // ABE.g:14:21: predicate
+ this.pushFollow(ABEParser.FOLLOW_predicate_in_rule67);
+ predicate4=this.predicate();
+
+ this.state._fsp--;
+
+ stream_predicate.add(predicate4.getTree());
+
+
+ break;
+
+ default :
+ if ( cnt2 >= 1 ) {
+ break loop2;
+ }
+ var eee = new org.antlr.runtime.EarlyExitException(2, this.input);
+ throw eee;
+ }
+ cnt2++;
+ } while (true);
+
+
+
+ // AST REWRITE
+ // elements: predicate, subject
+ // token labels:
+ // rule labels: retval
+ // token list labels:
+ // rule list labels:
+ retval.tree = root_0;
+ var stream_retval=new org.antlr.runtime.tree.RewriteRuleSubtreeStream(this.adaptor,"token retval",retval!=null?retval.tree:null);
+
+ root_0 = this.adaptor.nil();
+ // 14:32: -> subject ( predicate )+
+ {
+ this.adaptor.addChild(root_0, stream_subject.nextTree());
+ if ( !(stream_predicate.hasNext()) ) {
+ throw new org.antlr.runtime.tree.RewriteEarlyExitException();
+ }
+ while ( stream_predicate.hasNext() ) {
+ this.adaptor.addChild(root_0, stream_predicate.nextTree());
+
+ }
+ stream_predicate.reset();
+
+ }
+
+ retval.tree = root_0;
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ predicate_return: (function() {
+ ABEParser.predicate_return = function(){};
+ org.antlr.lang.extend(ABEParser.predicate_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:15:1: predicate : action ( methods )? ( origin )? -> T_ACTION action T_METHODS ( methods )? ( origin )? ;
+ // $ANTLR start "predicate"
+ predicate: function() {
+ var retval = new ABEParser.predicate_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var action5 = null;
+ var methods6 = null;
+ var origin7 = null;
+
+ var stream_methods=new org.antlr.runtime.tree.RewriteRuleSubtreeStream(this.adaptor,"rule methods");
+ var stream_action=new org.antlr.runtime.tree.RewriteRuleSubtreeStream(this.adaptor,"rule action");
+ var stream_origin=new org.antlr.runtime.tree.RewriteRuleSubtreeStream(this.adaptor,"rule origin");
+ try {
+ // ABE.g:15:11: ( action ( methods )? ( origin )? -> T_ACTION action T_METHODS ( methods )? ( origin )? )
+ // ABE.g:15:13: action ( methods )? ( origin )?
+ this.pushFollow(ABEParser.FOLLOW_action_in_predicate83);
+ action5=this.action();
+
+ this.state._fsp--;
+
+ stream_action.add(action5.getTree());
+ // ABE.g:15:20: ( methods )?
+ var alt3=2;
+ var LA3_0 = this.input.LA(1);
+
+ if ( ((LA3_0>=ALL && LA3_0<=INC)) ) {
+ alt3=1;
+ }
+ switch (alt3) {
+ case 1 :
+ // ABE.g:15:20: methods
+ this.pushFollow(ABEParser.FOLLOW_methods_in_predicate85);
+ methods6=this.methods();
+
+ this.state._fsp--;
+
+ stream_methods.add(methods6.getTree());
+
+
+ break;
+
+ }
+
+ // ABE.g:15:29: ( origin )?
+ var alt4=2;
+ var LA4_0 = this.input.LA(1);
+
+ if ( (LA4_0==T_FROM) ) {
+ alt4=1;
+ }
+ switch (alt4) {
+ case 1 :
+ // ABE.g:15:29: origin
+ this.pushFollow(ABEParser.FOLLOW_origin_in_predicate88);
+ origin7=this.origin();
+
+ this.state._fsp--;
+
+ stream_origin.add(origin7.getTree());
+
+
+ break;
+
+ }
+
+
+
+ // AST REWRITE
+ // elements: action, methods, origin
+ // token labels:
+ // rule labels: retval
+ // token list labels:
+ // rule list labels:
+ retval.tree = root_0;
+ var stream_retval=new org.antlr.runtime.tree.RewriteRuleSubtreeStream(this.adaptor,"token retval",retval!=null?retval.tree:null);
+
+ root_0 = this.adaptor.nil();
+ // 15:37: -> T_ACTION action T_METHODS ( methods )? ( origin )?
+ {
+ this.adaptor.addChild(root_0, this.adaptor.create(T_ACTION, "T_ACTION"));
+ this.adaptor.addChild(root_0, stream_action.nextTree());
+ this.adaptor.addChild(root_0, this.adaptor.create(T_METHODS, "T_METHODS"));
+ // ABE.g:15:66: ( methods )?
+ if ( stream_methods.hasNext() ) {
+ this.adaptor.addChild(root_0, stream_methods.nextTree());
+
+ }
+ stream_methods.reset();
+ // ABE.g:15:75: ( origin )?
+ if ( stream_origin.hasNext() ) {
+ this.adaptor.addChild(root_0, stream_origin.nextTree());
+
+ }
+ stream_origin.reset();
+
+ }
+
+ retval.tree = root_0;
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ methods_return: (function() {
+ ABEParser.methods_return = function(){};
+ org.antlr.lang.extend(ABEParser.methods_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:16:1: methods : ( ( method )+ | ALL ) ;
+ // $ANTLR start "methods"
+ methods: function() {
+ var retval = new ABEParser.methods_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var ALL9 = null;
+ var method8 = null;
+
+ var ALL9_tree=null;
+
+ try {
+ // ABE.g:16:11: ( ( ( method )+ | ALL ) )
+ // ABE.g:16:13: ( ( method )+ | ALL )
+ root_0 = this.adaptor.nil();
+
+ // ABE.g:16:13: ( ( method )+ | ALL )
+ var alt6=2;
+ var LA6_0 = this.input.LA(1);
+
+ if ( ((LA6_0>=HTTPVERB && LA6_0<=INC)) ) {
+ alt6=1;
+ }
+ else if ( (LA6_0==ALL) ) {
+ alt6=2;
+ }
+ else {
+ var nvae =
+ new org.antlr.runtime.NoViableAltException("", 6, 0, this.input);
+
+ throw nvae;
+ }
+ switch (alt6) {
+ case 1 :
+ // ABE.g:16:14: ( method )+
+ // ABE.g:16:14: ( method )+
+ var cnt5=0;
+ loop5:
+ do {
+ var alt5=2;
+ var LA5_0 = this.input.LA(1);
+
+ if ( ((LA5_0>=HTTPVERB && LA5_0<=INC)) ) {
+ alt5=1;
+ }
+
+
+ switch (alt5) {
+ case 1 :
+ // ABE.g:16:14: method
+ this.pushFollow(ABEParser.FOLLOW_method_in_methods114);
+ method8=this.method();
+
+ this.state._fsp--;
+
+ this.adaptor.addChild(root_0, method8.getTree());
+
+
+ break;
+
+ default :
+ if ( cnt5 >= 1 ) {
+ break loop5;
+ }
+ var eee = new org.antlr.runtime.EarlyExitException(5, this.input);
+ throw eee;
+ }
+ cnt5++;
+ } while (true);
+
+
+
+ break;
+ case 2 :
+ // ABE.g:16:24: ALL
+ ALL9=this.match(this.input,ALL,ABEParser.FOLLOW_ALL_in_methods119);
+ ALL9_tree = this.adaptor.create(ALL9);
+ this.adaptor.addChild(root_0, ALL9_tree);
+
+
+
+ break;
+
+ }
+
+
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ method_return: (function() {
+ ABEParser.method_return = function(){};
+ org.antlr.lang.extend(ABEParser.method_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:17:1: method : ( HTTPVERB | SUB | inclusion ) ;
+ // $ANTLR start "method"
+ method: function() {
+ var retval = new ABEParser.method_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var HTTPVERB10 = null;
+ var SUB11 = null;
+ var inclusion12 = null;
+
+ var HTTPVERB10_tree=null;
+ var SUB11_tree=null;
+
+ try {
+ // ABE.g:17:11: ( ( HTTPVERB | SUB | inclusion ) )
+ // ABE.g:17:13: ( HTTPVERB | SUB | inclusion )
+ root_0 = this.adaptor.nil();
+
+ // ABE.g:17:13: ( HTTPVERB | SUB | inclusion )
+ var alt7=3;
+ switch ( this.input.LA(1) ) {
+ case HTTPVERB:
+ alt7=1;
+ break;
+ case SUB:
+ alt7=2;
+ break;
+ case INC:
+ alt7=3;
+ break;
+ default:
+ var nvae =
+ new org.antlr.runtime.NoViableAltException("", 7, 0, this.input);
+
+ throw nvae;
+ }
+
+ switch (alt7) {
+ case 1 :
+ // ABE.g:17:14: HTTPVERB
+ HTTPVERB10=this.match(this.input,HTTPVERB,ABEParser.FOLLOW_HTTPVERB_in_method132);
+ HTTPVERB10_tree = this.adaptor.create(HTTPVERB10);
+ this.adaptor.addChild(root_0, HTTPVERB10_tree);
+
+
+
+ break;
+ case 2 :
+ // ABE.g:17:25: SUB
+ SUB11=this.match(this.input,SUB,ABEParser.FOLLOW_SUB_in_method136);
+ SUB11_tree = this.adaptor.create(SUB11);
+ this.adaptor.addChild(root_0, SUB11_tree);
+
+
+
+ break;
+ case 3 :
+ // ABE.g:17:31: inclusion
+ this.pushFollow(ABEParser.FOLLOW_inclusion_in_method140);
+ inclusion12=this.inclusion();
+
+ this.state._fsp--;
+
+ this.adaptor.addChild(root_0, inclusion12.getTree());
+
+
+ break;
+
+ }
+
+
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ inclusion_return: (function() {
+ ABEParser.inclusion_return = function(){};
+ org.antlr.lang.extend(ABEParser.inclusion_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:18:1: inclusion : INC ( LPAR ( INC_TYPE COMMA )* ( INC_TYPE )? RPAR )? ;
+ // $ANTLR start "inclusion"
+ inclusion: function() {
+ var retval = new ABEParser.inclusion_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var INC13 = null;
+ var LPAR14 = null;
+ var INC_TYPE15 = null;
+ var COMMA16 = null;
+ var INC_TYPE17 = null;
+ var RPAR18 = null;
+
+ var INC13_tree=null;
+ var LPAR14_tree=null;
+ var INC_TYPE15_tree=null;
+ var COMMA16_tree=null;
+ var INC_TYPE17_tree=null;
+ var RPAR18_tree=null;
+
+ try {
+ // ABE.g:18:11: ( INC ( LPAR ( INC_TYPE COMMA )* ( INC_TYPE )? RPAR )? )
+ // ABE.g:18:13: INC ( LPAR ( INC_TYPE COMMA )* ( INC_TYPE )? RPAR )?
+ root_0 = this.adaptor.nil();
+
+ INC13=this.match(this.input,INC,ABEParser.FOLLOW_INC_in_inclusion149);
+ INC13_tree = this.adaptor.create(INC13);
+ this.adaptor.addChild(root_0, INC13_tree);
+
+ // ABE.g:18:17: ( LPAR ( INC_TYPE COMMA )* ( INC_TYPE )? RPAR )?
+ var alt10=2;
+ var LA10_0 = this.input.LA(1);
+
+ if ( (LA10_0==LPAR) ) {
+ alt10=1;
+ }
+ switch (alt10) {
+ case 1 :
+ // ABE.g:18:18: LPAR ( INC_TYPE COMMA )* ( INC_TYPE )? RPAR
+ LPAR14=this.match(this.input,LPAR,ABEParser.FOLLOW_LPAR_in_inclusion152);
+ LPAR14_tree = this.adaptor.create(LPAR14);
+ this.adaptor.addChild(root_0, LPAR14_tree);
+
+ // ABE.g:18:23: ( INC_TYPE COMMA )*
+ loop8:
+ do {
+ var alt8=2;
+ var LA8_0 = this.input.LA(1);
+
+ if ( (LA8_0==INC_TYPE) ) {
+ var LA8_1 = this.input.LA(2);
+
+ if ( (LA8_1==COMMA) ) {
+ alt8=1;
+ }
+
+
+ }
+
+
+ switch (alt8) {
+ case 1 :
+ // ABE.g:18:24: INC_TYPE COMMA
+ INC_TYPE15=this.match(this.input,INC_TYPE,ABEParser.FOLLOW_INC_TYPE_in_inclusion155);
+ INC_TYPE15_tree = this.adaptor.create(INC_TYPE15);
+ this.adaptor.addChild(root_0, INC_TYPE15_tree);
+
+ COMMA16=this.match(this.input,COMMA,ABEParser.FOLLOW_COMMA_in_inclusion157);
+ COMMA16_tree = this.adaptor.create(COMMA16);
+ this.adaptor.addChild(root_0, COMMA16_tree);
+
+
+
+ break;
+
+ default :
+ break loop8;
+ }
+ } while (true);
+
+ // ABE.g:18:41: ( INC_TYPE )?
+ var alt9=2;
+ var LA9_0 = this.input.LA(1);
+
+ if ( (LA9_0==INC_TYPE) ) {
+ alt9=1;
+ }
+ switch (alt9) {
+ case 1 :
+ // ABE.g:18:41: INC_TYPE
+ INC_TYPE17=this.match(this.input,INC_TYPE,ABEParser.FOLLOW_INC_TYPE_in_inclusion161);
+ INC_TYPE17_tree = this.adaptor.create(INC_TYPE17);
+ this.adaptor.addChild(root_0, INC_TYPE17_tree);
+
+
+
+ break;
+
+ }
+
+ RPAR18=this.match(this.input,RPAR,ABEParser.FOLLOW_RPAR_in_inclusion164);
+ RPAR18_tree = this.adaptor.create(RPAR18);
+ this.adaptor.addChild(root_0, RPAR18_tree);
+
+
+
+ break;
+
+ }
+
+
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ origin_return: (function() {
+ ABEParser.origin_return = function(){};
+ org.antlr.lang.extend(ABEParser.origin_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:19:1: origin : T_FROM oresources ;
+ // $ANTLR start "origin"
+ origin: function() {
+ var retval = new ABEParser.origin_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var T_FROM19 = null;
+ var oresources20 = null;
+
+ var T_FROM19_tree=null;
+
+ try {
+ // ABE.g:19:11: ( T_FROM oresources )
+ // ABE.g:19:13: T_FROM oresources
+ root_0 = this.adaptor.nil();
+
+ T_FROM19=this.match(this.input,T_FROM,ABEParser.FOLLOW_T_FROM_in_origin177);
+ T_FROM19_tree = this.adaptor.create(T_FROM19);
+ this.adaptor.addChild(root_0, T_FROM19_tree);
+
+ this.pushFollow(ABEParser.FOLLOW_oresources_in_origin179);
+ oresources20=this.oresources();
+
+ this.state._fsp--;
+
+ this.adaptor.addChild(root_0, oresources20.getTree());
+
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ subject_return: (function() {
+ ABEParser.subject_return = function(){};
+ org.antlr.lang.extend(ABEParser.subject_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:20:1: subject : T_SITE resources ;
+ // $ANTLR start "subject"
+ subject: function() {
+ var retval = new ABEParser.subject_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var T_SITE21 = null;
+ var resources22 = null;
+
+ var T_SITE21_tree=null;
+
+ try {
+ // ABE.g:20:11: ( T_SITE resources )
+ // ABE.g:20:13: T_SITE resources
+ root_0 = this.adaptor.nil();
+
+ T_SITE21=this.match(this.input,T_SITE,ABEParser.FOLLOW_T_SITE_in_subject189);
+ T_SITE21_tree = this.adaptor.create(T_SITE21);
+ this.adaptor.addChild(root_0, T_SITE21_tree);
+
+ this.pushFollow(ABEParser.FOLLOW_resources_in_subject191);
+ resources22=this.resources();
+
+ this.state._fsp--;
+
+ this.adaptor.addChild(root_0, resources22.getTree());
+
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ oresources_return: (function() {
+ ABEParser.oresources_return = function(){};
+ org.antlr.lang.extend(ABEParser.oresources_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:21:1: oresources : ( ( oresource )+ | ALL ) ;
+ // $ANTLR start "oresources"
+ oresources: function() {
+ var retval = new ABEParser.oresources_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var ALL24 = null;
+ var oresource23 = null;
+
+ var ALL24_tree=null;
+
+ try {
+ // ABE.g:21:11: ( ( ( oresource )+ | ALL ) )
+ // ABE.g:21:13: ( ( oresource )+ | ALL )
+ root_0 = this.adaptor.nil();
+
+ // ABE.g:21:13: ( ( oresource )+ | ALL )
+ var alt12=2;
+ var LA12_0 = this.input.LA(1);
+
+ if ( ((LA12_0>=REGEXP && LA12_0<=LOCATION)||(LA12_0>=28 && LA12_0<=30)) ) {
+ alt12=1;
+ }
+ else if ( (LA12_0==ALL) ) {
+ alt12=2;
+ }
+ else {
+ var nvae =
+ new org.antlr.runtime.NoViableAltException("", 12, 0, this.input);
+
+ throw nvae;
+ }
+ switch (alt12) {
+ case 1 :
+ // ABE.g:21:14: ( oresource )+
+ // ABE.g:21:14: ( oresource )+
+ var cnt11=0;
+ loop11:
+ do {
+ var alt11=2;
+ var LA11_0 = this.input.LA(1);
+
+ if ( ((LA11_0>=REGEXP && LA11_0<=LOCATION)||(LA11_0>=28 && LA11_0<=30)) ) {
+ alt11=1;
+ }
+
+
+ switch (alt11) {
+ case 1 :
+ // ABE.g:21:14: oresource
+ this.pushFollow(ABEParser.FOLLOW_oresource_in_oresources199);
+ oresource23=this.oresource();
+
+ this.state._fsp--;
+
+ this.adaptor.addChild(root_0, oresource23.getTree());
+
+
+ break;
+
+ default :
+ if ( cnt11 >= 1 ) {
+ break loop11;
+ }
+ var eee = new org.antlr.runtime.EarlyExitException(11, this.input);
+ throw eee;
+ }
+ cnt11++;
+ } while (true);
+
+
+
+ break;
+ case 2 :
+ // ABE.g:21:27: ALL
+ ALL24=this.match(this.input,ALL,ABEParser.FOLLOW_ALL_in_oresources204);
+ ALL24_tree = this.adaptor.create(ALL24);
+ this.adaptor.addChild(root_0, ALL24_tree);
+
+
+
+ break;
+
+ }
+
+
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ resources_return: (function() {
+ ABEParser.resources_return = function(){};
+ org.antlr.lang.extend(ABEParser.resources_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:22:1: resources : ( ( resource )+ | ALL ) ;
+ // $ANTLR start "resources"
+ resources: function() {
+ var retval = new ABEParser.resources_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var ALL26 = null;
+ var resource25 = null;
+
+ var ALL26_tree=null;
+
+ try {
+ // ABE.g:22:11: ( ( ( resource )+ | ALL ) )
+ // ABE.g:22:13: ( ( resource )+ | ALL )
+ root_0 = this.adaptor.nil();
+
+ // ABE.g:22:13: ( ( resource )+ | ALL )
+ var alt14=2;
+ var LA14_0 = this.input.LA(1);
+
+ if ( ((LA14_0>=REGEXP && LA14_0<=LOCATION)) ) {
+ alt14=1;
+ }
+ else if ( (LA14_0==ALL) ) {
+ alt14=2;
+ }
+ else {
+ var nvae =
+ new org.antlr.runtime.NoViableAltException("", 14, 0, this.input);
+
+ throw nvae;
+ }
+ switch (alt14) {
+ case 1 :
+ // ABE.g:22:14: ( resource )+
+ // ABE.g:22:14: ( resource )+
+ var cnt13=0;
+ loop13:
+ do {
+ var alt13=2;
+ var LA13_0 = this.input.LA(1);
+
+ if ( ((LA13_0>=REGEXP && LA13_0<=LOCATION)) ) {
+ alt13=1;
+ }
+
+
+ switch (alt13) {
+ case 1 :
+ // ABE.g:22:14: resource
+ this.pushFollow(ABEParser.FOLLOW_resource_in_resources214);
+ resource25=this.resource();
+
+ this.state._fsp--;
+
+ this.adaptor.addChild(root_0, resource25.getTree());
+
+
+ break;
+
+ default :
+ if ( cnt13 >= 1 ) {
+ break loop13;
+ }
+ var eee = new org.antlr.runtime.EarlyExitException(13, this.input);
+ throw eee;
+ }
+ cnt13++;
+ } while (true);
+
+
+
+ break;
+ case 2 :
+ // ABE.g:22:26: ALL
+ ALL26=this.match(this.input,ALL,ABEParser.FOLLOW_ALL_in_resources219);
+ ALL26_tree = this.adaptor.create(ALL26);
+ this.adaptor.addChild(root_0, ALL26_tree);
+
+
+
+ break;
+
+ }
+
+
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ oresource_return: (function() {
+ ABEParser.oresource_return = function(){};
+ org.antlr.lang.extend(ABEParser.oresource_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:23:1: oresource : ( resource | 'SELF' | 'SELF+' | 'SELF++' );
+ // $ANTLR start "oresource"
+ oresource: function() {
+ var retval = new ABEParser.oresource_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var string_literal28 = null;
+ var string_literal29 = null;
+ var string_literal30 = null;
+ var resource27 = null;
+
+ var string_literal28_tree=null;
+ var string_literal29_tree=null;
+ var string_literal30_tree=null;
+
+ try {
+ // ABE.g:23:10: ( resource | 'SELF' | 'SELF+' | 'SELF++' )
+ var alt15=4;
+ switch ( this.input.LA(1) ) {
+ case REGEXP:
+ case GLOB:
+ case URI:
+ case LOCATION:
+ alt15=1;
+ break;
+ case 28:
+ alt15=2;
+ break;
+ case 29:
+ alt15=3;
+ break;
+ case 30:
+ alt15=4;
+ break;
+ default:
+ var nvae =
+ new org.antlr.runtime.NoViableAltException("", 15, 0, this.input);
+
+ throw nvae;
+ }
+
+ switch (alt15) {
+ case 1 :
+ // ABE.g:23:12: resource
+ root_0 = this.adaptor.nil();
+
+ this.pushFollow(ABEParser.FOLLOW_resource_in_oresource227);
+ resource27=this.resource();
+
+ this.state._fsp--;
+
+ this.adaptor.addChild(root_0, resource27.getTree());
+
+
+ break;
+ case 2 :
+ // ABE.g:23:23: 'SELF'
+ root_0 = this.adaptor.nil();
+
+ string_literal28=this.match(this.input,28,ABEParser.FOLLOW_28_in_oresource231);
+ string_literal28_tree = this.adaptor.create(string_literal28);
+ this.adaptor.addChild(root_0, string_literal28_tree);
+
+
+
+ break;
+ case 3 :
+ // ABE.g:23:32: 'SELF+'
+ root_0 = this.adaptor.nil();
+
+ string_literal29=this.match(this.input,29,ABEParser.FOLLOW_29_in_oresource235);
+ string_literal29_tree = this.adaptor.create(string_literal29);
+ this.adaptor.addChild(root_0, string_literal29_tree);
+
+
+
+ break;
+ case 4 :
+ // ABE.g:23:42: 'SELF++'
+ root_0 = this.adaptor.nil();
+
+ string_literal30=this.match(this.input,30,ABEParser.FOLLOW_30_in_oresource239);
+ string_literal30_tree = this.adaptor.create(string_literal30);
+ this.adaptor.addChild(root_0, string_literal30_tree);
+
+
+
+ break;
+
+ }
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ resource_return: (function() {
+ ABEParser.resource_return = function(){};
+ org.antlr.lang.extend(ABEParser.resource_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:24:1: resource : ( REGEXP | GLOB | URI | LOCATION );
+ // $ANTLR start "resource"
+ resource: function() {
+ var retval = new ABEParser.resource_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var set31 = null;
+
+ var set31_tree=null;
+
+ try {
+ // ABE.g:24:11: ( REGEXP | GLOB | URI | LOCATION )
+ // ABE.g:
+ root_0 = this.adaptor.nil();
+
+ set31=this.input.LT(1);
+ if ( (this.input.LA(1)>=REGEXP && this.input.LA(1)<=LOCATION) ) {
+ this.input.consume();
+ this.adaptor.addChild(root_0, this.adaptor.create(set31));
+ this.state.errorRecovery=false;
+ }
+ else {
+ var mse = new org.antlr.runtime.MismatchedSetException(null,this.input);
+ throw mse;
+ }
+
+
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ },
+
+ // inline static return class
+ action_return: (function() {
+ ABEParser.action_return = function(){};
+ org.antlr.lang.extend(ABEParser.action_return,
+ org.antlr.runtime.ParserRuleReturnScope,
+ {
+ getTree: function() { return this.tree; }
+ });
+ return;
+ })(),
+
+ // ABE.g:25:1: action : ( A_DENY | A_LOGOUT | A_SANDBOX | A_ACCEPT );
+ // $ANTLR start "action"
+ action: function() {
+ var retval = new ABEParser.action_return();
+ retval.start = this.input.LT(1);
+
+ var root_0 = null;
+
+ var set32 = null;
+
+ var set32_tree=null;
+
+ try {
+ // ABE.g:25:11: ( A_DENY | A_LOGOUT | A_SANDBOX | A_ACCEPT )
+ // ABE.g:
+ root_0 = this.adaptor.nil();
+
+ set32=this.input.LT(1);
+ if ( (this.input.LA(1)>=A_DENY && this.input.LA(1)<=A_ACCEPT) ) {
+ this.input.consume();
+ this.adaptor.addChild(root_0, this.adaptor.create(set32));
+ this.state.errorRecovery=false;
+ }
+ else {
+ var mse = new org.antlr.runtime.MismatchedSetException(null,this.input);
+ throw mse;
+ }
+
+
+
+
+ retval.stop = this.input.LT(-1);
+
+ retval.tree = this.adaptor.rulePostProcessing(root_0);
+ this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ catch (re) {
+ if (re instanceof org.antlr.runtime.RecognitionException) {
+ this.reportError(re);
+ this.recover(this.input,re);
+ retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re);
+ } else {
+ throw re;
+ }
+ }
+ finally {
+ }
+ return retval;
+ }
+
+ // Delegated rules
+
+
+
+
+}, true); // important to pass true to overwrite default implementations
+
+
+
+// public class variables
+org.antlr.lang.augmentObject(ABEParser, {
+ tokenNames: ["<invalid>", "<EOR>", "<DOWN>", "<UP>", "T_ACTION", "T_METHODS", "ALL", "HTTPVERB", "SUB", "INC", "LPAR", "INC_TYPE", "COMMA", "RPAR", "T_FROM", "T_SITE", "REGEXP", "GLOB", "URI", "LOCATION", "A_DENY", "A_LOGOUT", "A_SANDBOX", "A_ACCEPT", "URI_START", "URI_PART", "WS", "COMMENT", "'SELF'", "'SELF+'", "'SELF++'"],
+ FOLLOW_rule_in_ruleset49: new org.antlr.runtime.BitSet([0x00008000, 0x00000000]),
+ FOLLOW_EOF_in_ruleset52: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_subject_in_rule65: new org.antlr.runtime.BitSet([0x00F00000, 0x00000000]),
+ FOLLOW_predicate_in_rule67: new org.antlr.runtime.BitSet([0x00F00002, 0x00000000]),
+ FOLLOW_action_in_predicate83: new org.antlr.runtime.BitSet([0x000043C2, 0x00000000]),
+ FOLLOW_methods_in_predicate85: new org.antlr.runtime.BitSet([0x00004002, 0x00000000]),
+ FOLLOW_origin_in_predicate88: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_method_in_methods114: new org.antlr.runtime.BitSet([0x00000382, 0x00000000]),
+ FOLLOW_ALL_in_methods119: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_HTTPVERB_in_method132: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_SUB_in_method136: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_inclusion_in_method140: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_INC_in_inclusion149: new org.antlr.runtime.BitSet([0x00000402, 0x00000000]),
+ FOLLOW_LPAR_in_inclusion152: new org.antlr.runtime.BitSet([0x00002800, 0x00000000]),
+ FOLLOW_INC_TYPE_in_inclusion155: new org.antlr.runtime.BitSet([0x00001000, 0x00000000]),
+ FOLLOW_COMMA_in_inclusion157: new org.antlr.runtime.BitSet([0x00002800, 0x00000000]),
+ FOLLOW_INC_TYPE_in_inclusion161: new org.antlr.runtime.BitSet([0x00002000, 0x00000000]),
+ FOLLOW_RPAR_in_inclusion164: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_T_FROM_in_origin177: new org.antlr.runtime.BitSet([0x700F0040, 0x00000000]),
+ FOLLOW_oresources_in_origin179: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_T_SITE_in_subject189: new org.antlr.runtime.BitSet([0x000F0040, 0x00000000]),
+ FOLLOW_resources_in_subject191: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_oresource_in_oresources199: new org.antlr.runtime.BitSet([0x700F0002, 0x00000000]),
+ FOLLOW_ALL_in_oresources204: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_resource_in_resources214: new org.antlr.runtime.BitSet([0x000F0002, 0x00000000]),
+ FOLLOW_ALL_in_resources219: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_resource_in_oresource227: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_28_in_oresource231: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_29_in_oresource235: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_30_in_oresource239: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_set_in_resource0: new org.antlr.runtime.BitSet([0x00000002, 0x00000000]),
+ FOLLOW_set_in_action0: new org.antlr.runtime.BitSet([0x00000002, 0x00000000])
+});
+
+})(); \ No newline at end of file
diff --git a/extensions/noscript/chrome/content/noscript/ASPIdiocy.js b/extensions/noscript/chrome/content/noscript/ASPIdiocy.js
new file mode 100644
index 0000000..1e61f73
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/ASPIdiocy.js
@@ -0,0 +1,566 @@
+ASPIdiocy._replace = function(match, hex) {
+ const k = parseInt(hex, 16);
+ const map = ASPIdiocy.map;
+ if (k in map) return map[k];
+ const range = ASPIdiocy._findRange(k);
+ return range && range.data || String.fromCharCode(k);
+};
+
+ASPIdiocy._findRange = function(k) {
+ const ranges = this.ranges;
+ for (let low = 0, high = ranges.length - 1; low <= high;) {
+ let i = parseInt((low + high) / 2);
+ let r = ranges[i];
+ let comparison = k < r.start ? 1 : k > r.end ? -1 : 0;
+ if (comparison < 0) low = i + 1;
+ else if (comparison > 0) high = i - 1;
+ else return r;
+ }
+ return null;
+};
+
+ASPIdiocy.map = {
+ 0x100: "\x41",
+ 0x101: "\x61",
+ 0x102: "\x41",
+ 0x103: "\x61",
+ 0x104: "\x41",
+ 0x105: "\x61",
+ 0x106: "\x43",
+ 0x107: "\x63",
+ 0x108: "\x43",
+ 0x109: "\x63",
+ 0x10a: "\x43",
+ 0x10b: "\x63",
+ 0x10c: "\x43",
+ 0x10d: "\x63",
+ 0x10e: "\x44",
+ 0x10f: "\x64",
+ 0x110: "\ufffd",
+ 0x111: "\x64",
+ 0x112: "\x45",
+ 0x113: "\x65",
+ 0x114: "\x45",
+ 0x115: "\x65",
+ 0x116: "\x45",
+ 0x117: "\x65",
+ 0x118: "\x45",
+ 0x119: "\x65",
+ 0x11a: "\x45",
+ 0x11b: "\x65",
+ 0x11c: "\x47",
+ 0x11d: "\x67",
+ 0x11e: "\x47",
+ 0x11f: "\x67",
+ 0x120: "\x47",
+ 0x121: "\x67",
+ 0x122: "\x47",
+ 0x123: "\x67",
+ 0x124: "\x48",
+ 0x125: "\x68",
+ 0x126: "\x48",
+ 0x127: "\x68",
+ 0x128: "\x49",
+ 0x129: "\x69",
+ 0x12a: "\x49",
+ 0x12b: "\x69",
+ 0x12c: "\x49",
+ 0x12d: "\x69",
+ 0x12e: "\x49",
+ 0x12f: "\x69",
+ 0x130: "\x49",
+ 0x131: "\x69",
+ 0x134: "\x4a",
+ 0x135: "\x6a",
+ 0x136: "\x4b",
+ 0x137: "\x6b",
+ 0x138: "\x3f",
+ 0x139: "\x4c",
+ 0x13a: "\x6c",
+ 0x13b: "\x4c",
+ 0x13c: "\x6c",
+ 0x13d: "\x4c",
+ 0x13e: "\x6c",
+ 0x141: "\x4c",
+ 0x142: "\x6c",
+ 0x143: "\x4e",
+ 0x144: "\x6e",
+ 0x145: "\x4e",
+ 0x146: "\x6e",
+ 0x147: "\x4e",
+ 0x148: "\x6e",
+ 0x14c: "\x4f",
+ 0x14d: "\x6f",
+ 0x14e: "\x4f",
+ 0x14f: "\x6f",
+ 0x150: "\x4f",
+ 0x151: "\x6f",
+ 0x154: "\x52",
+ 0x155: "\x72",
+ 0x156: "\x52",
+ 0x157: "\x72",
+ 0x158: "\x52",
+ 0x159: "\x72",
+ 0x15a: "\x53",
+ 0x15b: "\x73",
+ 0x15c: "\x53",
+ 0x15d: "\x73",
+ 0x15e: "\x53",
+ 0x15f: "\x73",
+ 0x162: "\x54",
+ 0x163: "\x74",
+ 0x164: "\x54",
+ 0x165: "\x74",
+ 0x166: "\x54",
+ 0x167: "\x74",
+ 0x168: "\x55",
+ 0x169: "\x75",
+ 0x16a: "\x55",
+ 0x16b: "\x75",
+ 0x16c: "\x55",
+ 0x16d: "\x75",
+ 0x16e: "\x55",
+ 0x16f: "\x75",
+ 0x170: "\x55",
+ 0x171: "\x75",
+ 0x172: "\x55",
+ 0x173: "\x75",
+ 0x174: "\x57",
+ 0x175: "\x77",
+ 0x176: "\x59",
+ 0x177: "\x79",
+ 0x178: "\ufffd",
+ 0x179: "\x5a",
+ 0x17a: "\x7a",
+ 0x17b: "\x5a",
+ 0x17c: "\x7a",
+ 0x17f: "\x3f",
+ 0x180: "\x62",
+ 0x189: "\ufffd",
+ 0x197: "\x49",
+ 0x19a: "\x6c",
+ 0x1a1: "\x6f",
+ 0x1ab: "\x74",
+ 0x1ae: "\x54",
+ 0x1af: "\x55",
+ 0x1b0: "\x75",
+ 0x1b6: "\x7a",
+ 0x1c0: "\x7c",
+ 0x1c3: "\x21",
+ 0x1cd: "\x41",
+ 0x1ce: "\x61",
+ 0x1cf: "\x49",
+ 0x1d0: "\x69",
+ 0x1d1: "\x4f",
+ 0x1d2: "\x6f",
+ 0x1d3: "\x55",
+ 0x1d4: "\x75",
+ 0x1d5: "\x55",
+ 0x1d6: "\x75",
+ 0x1d7: "\x55",
+ 0x1d8: "\x75",
+ 0x1d9: "\x55",
+ 0x1da: "\x75",
+ 0x1db: "\x55",
+ 0x1dc: "\x75",
+ 0x1dd: "\x3f",
+ 0x1de: "\x41",
+ 0x1df: "\x61",
+ 0x1e4: "\x47",
+ 0x1e5: "\x67",
+ 0x1e6: "\x47",
+ 0x1e7: "\x67",
+ 0x1e8: "\x4b",
+ 0x1e9: "\x6b",
+ 0x1ea: "\x4f",
+ 0x1eb: "\x6f",
+ 0x1ec: "\x4f",
+ 0x1ed: "\x6f",
+ 0x1f0: "\x6a",
+ 0x261: "\x67",
+ 0x2b9: "\x27",
+ 0x2ba: "\x22",
+ 0x2bb: "\x3f",
+ 0x2bc: "\x27",
+ 0x2c4: "\x5e",
+ 0x2c5: "\x3f",
+ 0x2c6: "\ufffd",
+ 0x2c7: "\x3f",
+ 0x2c8: "\x27",
+ 0x2cb: "\x60",
+ 0x2cc: "\x3f",
+ 0x2cd: "\x5f",
+ 0x2da: "\ufffd",
+ 0x2db: "\x3f",
+ 0x2dc: "\ufffd",
+ 0x300: "\x60",
+ 0x301: "\ufffd",
+ 0x302: "\x5e",
+ 0x303: "\x7e",
+ 0x308: "\ufffd",
+ 0x309: "\x3f",
+ 0x30a: "\ufffd",
+ 0x30e: "\x22",
+ 0x327: "\ufffd",
+ 0x37e: "\x3b",
+ 0x393: "\x47",
+ 0x398: "\x54",
+ 0x3a3: "\x53",
+ 0x3a6: "\x46",
+ 0x3a9: "\x4f",
+ 0x3b1: "\x61",
+ 0x3b2: "\ufffd",
+ 0x3b3: "\x3f",
+ 0x3b4: "\x64",
+ 0x3b5: "\x65",
+ 0x3bc: "\ufffd",
+ 0x3c0: "\x70",
+ 0x3c3: "\x73",
+ 0x3c4: "\x74",
+ 0x3c5: "\x3f",
+ 0x3c6: "\x66",
+ 0x4bb: "\x68",
+ 0x589: "\x3a",
+ 0x66a: "\x25",
+ 0x2012: "\x3f",
+ 0x2017: "\x3d",
+ 0x201b: "\x3f",
+ 0x201f: "\x3f",
+ 0x2023: "\x3f",
+ 0x2024: "\ufffd",
+ 0x2025: "\x3f",
+ 0x2026: "\ufffd",
+ 0x2030: "\ufffd",
+ 0x2031: "\x3f",
+ 0x2032: "\x27",
+ 0x2035: "\x60",
+ 0x2044: "\x2f",
+ 0x2070: "\ufffd",
+ 0x2074: "\x34",
+ 0x2075: "\x35",
+ 0x2076: "\x36",
+ 0x2077: "\x37",
+ 0x2078: "\x38",
+ 0x207f: "\x6e",
+ 0x2080: "\x30",
+ 0x2081: "\x31",
+ 0x2082: "\x32",
+ 0x2083: "\x33",
+ 0x2084: "\x34",
+ 0x2085: "\x35",
+ 0x2086: "\x36",
+ 0x2087: "\x37",
+ 0x2088: "\x38",
+ 0x2089: "\x39",
+ 0x20a1: "\ufffd",
+ 0x20a4: "\ufffd",
+ 0x20a7: "\x50",
+ 0x20ac: "\ufffd",
+ 0x2102: "\x43",
+ 0x2107: "\x45",
+ 0x210a: "\x67",
+ 0x210e: "\x68",
+ 0x210f: "\x3f",
+ 0x2112: "\x4c",
+ 0x2113: "\x6c",
+ 0x2114: "\x3f",
+ 0x2115: "\x4e",
+ 0x211a: "\x51",
+ 0x2122: "\ufffd",
+ 0x2123: "\x3f",
+ 0x2124: "\x5a",
+ 0x2128: "\x5a",
+ 0x2129: "\x3f",
+ 0x212a: "\x4b",
+ 0x212b: "\ufffd",
+ 0x212c: "\x42",
+ 0x212d: "\x43",
+ 0x2130: "\x45",
+ 0x2131: "\x46",
+ 0x2132: "\x3f",
+ 0x2133: "\x4d",
+ 0x2134: "\x6f",
+ 0x2205: "\ufffd",
+ 0x2212: "\x2d",
+ 0x2213: "\ufffd",
+ 0x2214: "\x3f",
+ 0x2215: "\x2f",
+ 0x2216: "\x5c",
+ 0x2217: "\x2a",
+ 0x221a: "\x76",
+ 0x221e: "\x38",
+ 0x2223: "\x7c",
+ 0x2229: "\x6e",
+ 0x2236: "\x3a",
+ 0x223c: "\x7e",
+ 0x2248: "\ufffd",
+ 0x2261: "\x3d",
+ 0x22c5: "\ufffd",
+ 0x2302: "\ufffd",
+ 0x2303: "\x5e",
+ 0x2310: "\ufffd",
+ 0x2320: "\x28",
+ 0x2321: "\x29",
+ 0x2329: "\x3c",
+ 0x232a: "\x3e",
+ 0x2500: "\x2d",
+ 0x2501: "\x3f",
+ 0x2502: "\ufffd",
+ 0x250c: "\x2b",
+ 0x2510: "\x2b",
+ 0x2514: "\x2b",
+ 0x2518: "\x2b",
+ 0x251c: "\x2b",
+ 0x2524: "\ufffd",
+ 0x252c: "\x2d",
+ 0x2534: "\x2d",
+ 0x253c: "\x2b",
+ 0x2550: "\x2d",
+ 0x2551: "\ufffd",
+ 0x2580: "\ufffd",
+ 0x2584: "\x5f",
+ 0x2588: "\ufffd",
+ 0x258c: "\ufffd",
+ 0x25a0: "\ufffd",
+ 0x263c: "\ufffd",
+ 0x2758: "\x7c",
+ 0x3000: "\x20",
+ 0x3008: "\x3c",
+ 0x3009: "\x3e",
+ 0x301a: "\x5b",
+ 0x301b: "\x5d",
+ 0x30fb: "\ufffd",
+ 0xff01: "\x21",
+ 0xff02: "\x22",
+ 0xff03: "\x23",
+ 0xff04: "\x24",
+ 0xff05: "\x25",
+ 0xff06: "\x26",
+ 0xff07: "\x27",
+ 0xff08: "\x28",
+ 0xff09: "\x29",
+ 0xff0a: "\x2a",
+ 0xff0b: "\x2b",
+ 0xff0c: "\x2c",
+ 0xff0d: "\x2d",
+ 0xff0e: "\x2e",
+ 0xff0f: "\x2f",
+ 0xff10: "\x30",
+ 0xff11: "\x31",
+ 0xff12: "\x32",
+ 0xff13: "\x33",
+ 0xff14: "\x34",
+ 0xff15: "\x35",
+ 0xff16: "\x36",
+ 0xff17: "\x37",
+ 0xff18: "\x38",
+ 0xff19: "\x39",
+ 0xff1a: "\x3a",
+ 0xff1b: "\x3b",
+ 0xff1c: "\x3c",
+ 0xff1d: "\x3d",
+ 0xff1e: "\x3e",
+ 0xff1f: "\x3f",
+ 0xff20: "\x40",
+ 0xff21: "\x41",
+ 0xff22: "\x42",
+ 0xff23: "\x43",
+ 0xff24: "\x44",
+ 0xff25: "\x45",
+ 0xff26: "\x46",
+ 0xff27: "\x47",
+ 0xff28: "\x48",
+ 0xff29: "\x49",
+ 0xff2a: "\x4a",
+ 0xff2b: "\x4b",
+ 0xff2c: "\x4c",
+ 0xff2d: "\x4d",
+ 0xff2e: "\x4e",
+ 0xff2f: "\x4f",
+ 0xff30: "\x50",
+ 0xff31: "\x51",
+ 0xff32: "\x52",
+ 0xff33: "\x53",
+ 0xff34: "\x54",
+ 0xff35: "\x55",
+ 0xff36: "\x56",
+ 0xff37: "\x57",
+ 0xff38: "\x58",
+ 0xff39: "\x59",
+ 0xff3a: "\x5a",
+ 0xff3b: "\x5b",
+ 0xff3c: "\x5c",
+ 0xff3d: "\x5d",
+ 0xff3e: "\x5e",
+ 0xff3f: "\x5f",
+ 0xff40: "\x60",
+ 0xff41: "\x61",
+ 0xff42: "\x62",
+ 0xff43: "\x63",
+ 0xff44: "\x64",
+ 0xff45: "\x65",
+ 0xff46: "\x66",
+ 0xff47: "\x67",
+ 0xff48: "\x68",
+ 0xff49: "\x69",
+ 0xff4a: "\x6a",
+ 0xff4b: "\x6b",
+ 0xff4c: "\x6c",
+ 0xff4d: "\x6d",
+ 0xff4e: "\x6e",
+ 0xff4f: "\x6f",
+ 0xff50: "\x70",
+ 0xff51: "\x71",
+ 0xff52: "\x72",
+ 0xff53: "\x73",
+ 0xff54: "\x74",
+ 0xff55: "\x75",
+ 0xff56: "\x76",
+ 0xff57: "\x77",
+ 0xff58: "\x78",
+ 0xff59: "\x79",
+ 0xff5a: "\x7a",
+ 0xff5b: "\x7b",
+ 0xff5c: "\x7c",
+ 0xff5d: "\x7d",
+ 0xff5e: "\x7e"
+};
+
+(function() {
+ function Range(start, end, data) {
+ this.start = start;
+ this.end = end;
+ this.data = data;
+ }
+
+ ASPIdiocy.ranges = [
+ new Range(0x80, 0xff, "\ufffd"),
+ new Range(0x132, 0x133, "\x3f"),
+ new Range(0x13f, 0x140, "\x3f"),
+ new Range(0x149, 0x14b, "\x3f"),
+ new Range(0x152, 0x153, "\ufffd"),
+ new Range(0x160, 0x161, "\ufffd"),
+ new Range(0x17d, 0x17e, "\ufffd"),
+ new Range(0x181, 0x188, "\x3f"),
+ new Range(0x18a, 0x190, "\x3f"),
+ new Range(0x191, 0x192, "\ufffd"),
+ new Range(0x193, 0x196, "\x3f"),
+ new Range(0x198, 0x199, "\x3f"),
+ new Range(0x19b, 0x19e, "\x3f"),
+ new Range(0x19f, 0x1a0, "\x4f"),
+ new Range(0x1a2, 0x1aa, "\x3f"),
+ new Range(0x1ac, 0x1ad, "\x3f"),
+ new Range(0x1b1, 0x1b5, "\x3f"),
+ new Range(0x1b7, 0x1bf, "\x3f"),
+ new Range(0x1c1, 0x1c2, "\x3f"),
+ new Range(0x1c4, 0x1cc, "\x3f"),
+ new Range(0x1e0, 0x1e3, "\x3f"),
+ new Range(0x1ee, 0x1ef, "\x3f"),
+ new Range(0x1f1, 0x260, "\x3f"),
+ new Range(0x262, 0x2b8, "\x3f"),
+ new Range(0x2bd, 0x2c3, "\x3f"),
+ new Range(0x2c9, 0x2ca, "\ufffd"),
+ new Range(0x2ce, 0x2d9, "\x3f"),
+ new Range(0x2dd, 0x2ff, "\x3f"),
+ new Range(0x304, 0x305, "\ufffd"),
+ new Range(0x306, 0x307, "\x3f"),
+ new Range(0x30b, 0x30d, "\x3f"),
+ new Range(0x30f, 0x326, "\x3f"),
+ new Range(0x328, 0x330, "\x3f"),
+ new Range(0x331, 0x332, "\x5f"),
+ new Range(0x333, 0x37d, "\x3f"),
+ new Range(0x37f, 0x392, "\x3f"),
+ new Range(0x394, 0x397, "\x3f"),
+ new Range(0x399, 0x3a2, "\x3f"),
+ new Range(0x3a4, 0x3a5, "\x3f"),
+ new Range(0x3a7, 0x3a8, "\x3f"),
+ new Range(0x3aa, 0x3b0, "\x3f"),
+ new Range(0x3b6, 0x3bb, "\x3f"),
+ new Range(0x3bd, 0x3bf, "\x3f"),
+ new Range(0x3c1, 0x3c2, "\x3f"),
+ new Range(0x3c7, 0x4ba, "\x3f"),
+ new Range(0x4bc, 0x588, "\x3f"),
+ new Range(0x58a, 0x669, "\x3f"),
+ new Range(0x66b, 0x1fff, "\x3f"),
+ new Range(0x2000, 0x2006, "\x20"),
+ new Range(0x2007, 0x200f, "\x3f"),
+ new Range(0x2010, 0x2011, "\x2d"),
+ new Range(0x2013, 0x2014, "\ufffd"),
+ new Range(0x2015, 0x2016, "\x3f"),
+ new Range(0x2018, 0x201a, "\ufffd"),
+ new Range(0x201c, 0x201e, "\ufffd"),
+ new Range(0x2020, 0x2022, "\ufffd"),
+ new Range(0x2027, 0x202f, "\x3f"),
+ new Range(0x2033, 0x2034, "\x3f"),
+ new Range(0x2036, 0x2038, "\x3f"),
+ new Range(0x2039, 0x203a, "\ufffd"),
+ new Range(0x203b, 0x2043, "\x3f"),
+ new Range(0x2045, 0x206f, "\x3f"),
+ new Range(0x2071, 0x2073, "\x3f"),
+ new Range(0x2079, 0x207e, "\x3f"),
+ new Range(0x208a, 0x20a0, "\x3f"),
+ new Range(0x20a2, 0x20a3, "\x3f"),
+ new Range(0x20a5, 0x20a6, "\x3f"),
+ new Range(0x20a8, 0x20ab, "\x3f"),
+ new Range(0x20ad, 0x2101, "\x3f"),
+ new Range(0x2103, 0x2106, "\x3f"),
+ new Range(0x2108, 0x2109, "\x3f"),
+ new Range(0x210b, 0x210d, "\x48"),
+ new Range(0x2110, 0x2111, "\x49"),
+ new Range(0x2116, 0x2117, "\x3f"),
+ new Range(0x2118, 0x2119, "\x50"),
+ new Range(0x211b, 0x211d, "\x52"),
+ new Range(0x211e, 0x2121, "\x3f"),
+ new Range(0x2125, 0x2127, "\x3f"),
+ new Range(0x212e, 0x212f, "\x65"),
+ new Range(0x2135, 0x2204, "\x3f"),
+ new Range(0x2206, 0x2211, "\x3f"),
+ new Range(0x2218, 0x2219, "\ufffd"),
+ new Range(0x221b, 0x221d, "\x3f"),
+ new Range(0x221f, 0x2222, "\x3f"),
+ new Range(0x2224, 0x2228, "\x3f"),
+ new Range(0x222a, 0x2235, "\x3f"),
+ new Range(0x2237, 0x223b, "\x3f"),
+ new Range(0x223d, 0x2247, "\x3f"),
+ new Range(0x2249, 0x2260, "\x3f"),
+ new Range(0x2262, 0x2263, "\x3f"),
+ new Range(0x2264, 0x2265, "\x3d"),
+ new Range(0x2266, 0x2269, "\x3f"),
+ new Range(0x226a, 0x226b, "\ufffd"),
+ new Range(0x226c, 0x22c4, "\x3f"),
+ new Range(0x22c6, 0x2301, "\x3f"),
+ new Range(0x2304, 0x230f, "\x3f"),
+ new Range(0x2311, 0x231f, "\x3f"),
+ new Range(0x2322, 0x2328, "\x3f"),
+ new Range(0x232b, 0x24ff, "\x3f"),
+ new Range(0x2503, 0x250b, "\x3f"),
+ new Range(0x250d, 0x250f, "\x3f"),
+ new Range(0x2511, 0x2513, "\x3f"),
+ new Range(0x2515, 0x2517, "\x3f"),
+ new Range(0x2519, 0x251b, "\x3f"),
+ new Range(0x251d, 0x2523, "\x3f"),
+ new Range(0x2525, 0x252b, "\x3f"),
+ new Range(0x252d, 0x2533, "\x3f"),
+ new Range(0x2535, 0x253b, "\x3f"),
+ new Range(0x253d, 0x254f, "\x3f"),
+ new Range(0x2552, 0x255d, "\x2b"),
+ new Range(0x255e, 0x2563, "\ufffd"),
+ new Range(0x2564, 0x2569, "\x2d"),
+ new Range(0x256a, 0x256c, "\x2b"),
+ new Range(0x256d, 0x257f, "\x3f"),
+ new Range(0x2581, 0x2583, "\x3f"),
+ new Range(0x2585, 0x2587, "\x3f"),
+ new Range(0x2589, 0x258b, "\x3f"),
+ new Range(0x258d, 0x258f, "\x3f"),
+ new Range(0x2590, 0x2593, "\ufffd"),
+ new Range(0x2594, 0x259f, "\x3f"),
+ new Range(0x25a1, 0x263b, "\x3f"),
+ new Range(0x263d, 0x2757, "\x3f"),
+ new Range(0x2759, 0x2fff, "\x3f"),
+ new Range(0x3001, 0x3007, "\x3f"),
+ new Range(0x300a, 0x300b, "\ufffd"),
+ new Range(0x300c, 0x3019, "\x3f"),
+ new Range(0x301c, 0x30fa, "\x3f"),
+ new Range(0x30fc, 0xff00, "\x3f")
+ ];
+})(); \ No newline at end of file
diff --git a/extensions/noscript/chrome/content/noscript/AddressMatcher.js b/extensions/noscript/chrome/content/noscript/AddressMatcher.js
new file mode 100644
index 0000000..8607057
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/AddressMatcher.js
@@ -0,0 +1,279 @@
+function AddressMatcher(s) {
+ this.source = s;
+ this.rx = this.parse(s);
+}
+AddressMatcher.create = function(s) {
+ return s && new AddressMatcher(s);
+}
+
+AddressMatcher.prototype = {
+ rx: null,
+ networks: null,
+ netMatching: false,
+
+ _universal: { test: function(s) { return true; } },
+
+ _specRx: /^((?:ht|f)tps?:\/*)([^\/]*)/i,
+ test: function(u) {
+ if (!this.rx) return false;
+
+ let spec = this._specRx.exec(u);
+
+ if (spec) {
+ let host = spec[2];
+ let atPos = host.indexOf("@");
+ if (atPos > -1) {
+ host = host.substring(atPos + 1);
+ u = spec[1] + host + u.substring(spec[0].length);
+ }
+ // handle IDN
+ if (host.substring(0, 4) === "xn--") {
+ try {
+ if (this.rx.test(spec[1] + DNS.idn.convertACEtoUTF8(host) + spec.input.substring(spec[0].length)))
+ return true;
+ } catch (e) {}
+ }
+ }
+
+ return this.rx.test(u);
+ },
+
+ testURI: function(uri) { return this.test(uri.spec); },
+
+ _networkTest: function(uri, canDoDNS, allIPs) {
+ var res = this.rx && this.rx.test(uri.spec || uri);
+ if (res || !canDoDNS) return res;
+
+ if (!uri.spec) {
+ uri = IOS.newURI(uri, null, null);
+ }
+ try {
+ var host = uri.host
+ if (!host) return false;
+ if (Network.isNet(host))
+ return this.testIP(host);
+
+ var dnsRecord = DNS.resolve(host);
+ if (dnsRecord && dnsRecord.valid)
+ return allIPs ? dnsRecord.entries.every(this.testIP, this)
+ : dnsRecord.entries.some(this.testIP, this);
+ } catch(e) {
+ dump(e + "\n");
+ }
+ return false;
+ },
+
+ testIP: function(ip) {
+ return this.networks.some((n) => n.test(ip));
+ },
+
+ parse: function(s) {
+ try {
+ var universal = false;
+ var rxs = s && s.split(/\s+/).map(function(p) {
+ if (p === '*') {
+ universal = true;
+ }
+
+ if (universal || !/\S+/.test(p)) return null;
+
+ if (Network.isNet(p)) {
+ var net;
+ if (!this.netMatching) {
+ this.netMatching = true;
+ this.test = this.testURI = this._networkTest;
+ this.networks = [net = new Network(p)];
+ } else {
+ this.networks.push(net = new Network(p));
+ }
+
+ if (p.indexOf("/") > -1 || (net.ipv4 ? net.mask < 32 : net.mask < 128))
+ return null; // is a whole network, using IP for URL doesn't make sense
+
+ if (p.indexOf(":") > -1)
+ p = "[" + p + "]"; // prepare IPv6 URL host
+ }
+
+ if(!/[^\w\-\[\]/:%@;&#\?\.\*]/.test(p)) {
+
+ // either simple or glob
+ const hasPath = /^(?:\w+:\/\/|)[^\/]+\//.test(p);
+ const hasScheme = /^[a-z][\w\-]+:(?:\/+|[^/]*\D|$)/.test(p);
+
+ p = p.replace(/[\.\?\-]/g, "\\$&"); // escape special regexp chars
+
+ if (!hasScheme) { // adjust for no protocol
+ if (p.substring(0, 2) === '\\.') {
+ // al_9x's proposed syntactic sugar to match both *.x.y and x.y
+ p = "(?:[^/]+\\.)?" + p.substring(2);
+ }
+ p = "[a-z]\\w+://" + p;
+ }
+
+ if (!hasPath &&
+ p.substring(p.length - 1) != ':' // unless scheme-only
+ ) {
+ // adjust for no path
+ p += "(?::\\d+)?(?:[/\\?#]|$)";
+ }
+
+ if (!/\*/.test(p)) {
+ // simple "starts with..." site matching
+ return '^' + p;
+ }
+
+ // glob matching
+ if (p.slice(-1) == '*') p = p.slice(0, -1); // optimize trailing *
+ else if (hasPath) p += '$';
+
+ return '^' + p.replace(/\*/g, '.*?').replace(/^([^\/:]+:\/*)\.\*/, "$1[^/]*");
+ }
+
+ return p;
+ }, this).filter(function(p) { return p !== null });
+
+ if (universal) {
+ this.test = this._universal.test;
+ return this._universal;
+ }
+
+ if (rxs.length !== 0) {
+ try {
+ return new RegExp(rxs.join("|"));
+ } catch(e) {
+ rxs = rxs.filter(function(p) {
+ try {
+ new RegExp(p);
+ return true;
+ } catch(e) {
+ dump("Illegal regexp in AddressMatcher: " + p + " -- " + e + "\n");
+ }
+ return false;
+ });
+ if (rxs.length !== 0) {
+ return new RegExp(rxs.join("|"));
+ }
+ }
+ }
+ } catch(e) {
+ dump("Illegal AddressMatcher: " + s + " -- " + e + "\n");
+ }
+ return null;
+ }
+};
+
+function Network(s) {
+ this.src = s;
+ var parts = s.split("/");
+ var addr = parts[0];
+ var smask;
+
+ if (!this._isIPV4(addr))
+ this.ipv4 = false;
+
+ if (parts.length > 1) {
+ this.mask = parseInt(parts[1]);
+
+ var defMask = this.ipv4 ? 32 : 128;
+
+ if (this.mask != defMask) {
+ if (this.mask > defMask) this.mask = defMask;
+ else {
+ if (this.ipv4) this.ipv4Mask = this._maskToBits(this.mask, 32)
+ else this.ipv6Mask = this._maskToBits(this.mask, 128);
+ }
+ }
+ } else if (!this.ipv4) {
+ this.mask = 128;
+ }
+ this.addr = this.ipv4 ? this._parseIPV4(addr) : this._parseIPV6(addr) ;
+}
+
+Network._netRx = /^(?:(?:\d+\.){1,3}\d*|[0-9a-f:]*:[0-9a-f:]*:[0-9a-f:]*)(:?\/\d{1,3})?$/i;
+Network.isNet = function(s) {
+ return this._netRx.test(s);
+}
+
+Network.prototype = {
+ ipv4: true,
+ mask: 32,
+ ipv4Mask: 0xffffffff,
+ ipv6Mask: [0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff],
+
+ _isIPV4: function(addr) {
+ return addr.indexOf(":") < 0;
+ },
+ _maskToBits: function(mask, length) {
+ var smask = "", j = 0;
+ for(; j < mask; j++) smask += "1";
+ for(; j < length; j++) smask += "0";
+ if (length <= 32)
+ return parseInt(smask, 2);
+ var ret = [];
+
+ for(j = 0; j < length; j += 32) {
+ ret.push(parseInt(smask.substring(j, j + 32), 2));
+ }
+ return ret;
+ },
+
+ test: function(addr) {
+ addr = this.parse(addr);
+ if (typeof(addr) === "number")
+ return this.addr === addr;
+
+ if (typeof(this.addr) === "number") return false;
+ for (var j = this.addr.length; j-- > 0;) {
+ if (addr[j] !== this.addr[j]) return false;
+ }
+ return true;
+ },
+
+ parse: function(addr) {
+ return this._isIPV4(addr) ? this._parseIPV4(addr) : this._parseIPV6(addr);
+ },
+ _parseIPV6: function(addr) {
+ var parts = addr.split(":");
+ var s = '', c, k, dz = false;
+ for (var j = 0, len = parts.length; j < len; j++) {
+ c = parts[j];
+ if (c.length === 0 && !dz) {
+ dz = true;
+ for (k = 9 - len; k-- >0;) s += "0000";
+ } else {
+ s += "0000".substring(c.length) + c;
+ }
+ }
+
+ var ret = [0, 0, 0, 0];
+ var pos;
+ for (j = 4; j-- > 0; ) {
+ pos = j * 8;
+ ret[j] = parseInt(s.substring(pos, pos + 8), 16) & this.ipv6Mask[j];
+ }
+ return ret;
+ },
+ _pows: [0x1000000, 0x10000, 0x100, 1],
+ _parseIPV4: function(addr) {
+ var parts = addr.split(".");
+ var ret = 0, byt3;
+ for (var j = parts.length; j-- > 0;) {
+ byt3 = parseInt(parts[j], 10);
+ if (byt3) {
+ if (byt3 > 255) byt3 = 255;
+ ret += byt3 * this._pows[j];
+ } else if (j == parts.length - 1 && parts[j] == '') {
+ parts.pop();
+ }
+ }
+ if (parts.length < 4 && this.mask == 32 && typeof (this.addr) == "undefined") {
+ this.mask = parts.length * 8;
+ this.ipv4Mask = this._maskToBits(this.mask, 32);
+ }
+ return ret & this.ipv4Mask;
+ },
+
+ toString: function() {
+ return this.src;
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/Bug.js b/extensions/noscript/chrome/content/noscript/Bug.js
new file mode 100644
index 0000000..5531a30
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Bug.js
@@ -0,0 +1,21 @@
+var Bug = {
+
+};
+
+{
+ let lazy = {
+ $677643: "8.0",
+ $677050: ["6.0", "18.0"],
+ $771655: "20",
+ $789773: "19",
+ }
+ for (let b in lazy) {
+ let v = lazy[b];
+ Bug.__defineGetter__(b, function() {
+ delete this[b];
+ return this[b] = (typeof v[0] === "object")
+ ? ns.geckoVersionCheck(v[0]) >= 0 && ns.geckoVersionCheck(v[1]) < 0
+ : ns.geckoVersionCheck(v) < 0;
+ });
+ }
+} \ No newline at end of file
diff --git a/extensions/noscript/chrome/content/noscript/ChannelReplacement.js b/extensions/noscript/chrome/content/noscript/ChannelReplacement.js
new file mode 100644
index 0000000..dae16ff
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/ChannelReplacement.js
@@ -0,0 +1,61 @@
+function ChannelReplacement(chan, newURI, newMethod) {
+ return this._init(chan, newURI, newMethod);
+}
+
+ChannelReplacement.runWhenPending = function(channel, callback) {
+ callback();
+};
+
+ChannelReplacement.prototype = {
+ _init: function(chan, newURI, newMethod) {
+ this.oldChannel = this.channel = chan;
+ this.newURI = newURI || chan.URI;
+ this.newMethod = newMethod;
+ return this;
+ },
+ replace: function(realRedirect, callback) {
+ let chan = this.channel;
+ if (!this.newURI.equals(chan.URI)) {
+ realRedirect = true;
+ }
+ if (this.newMethod && this.newMethod !== chan.requestMethod) {
+ chan.requestMethod = this.newMethod;
+ realRedirect = true;
+ }
+
+ let forceRedirect = !realRedirect;
+ if (forceRedirect) {
+ chan.redirectionLimit += 1;
+ } else {
+ let loadInfo = chan.loadInfo;
+ if (loadInfo) {
+ let type = loadInfo.externalContentPolicyType || loadInfo.contentPolicyType;
+ forceRedirect = type === 11 || type === 12;
+ }
+ }
+
+ if (forceRedirect) {
+ let ncb = chan.notificationCallbacks;
+ if (ncb) {
+ try {
+ let ces = ncb.getInterface(Ci.nsIChannelEventSink);
+ if (ces) {
+ INCLUDE("ForcedRedirectionCallback");
+ chan.notificationCallbacks = new NCBWrapper(ncb, new CESDelegate(ces));
+ }
+ } catch (e) {
+ // notificationCallbacks might not implement nsIChannelEventSink, e.g. in live bookmarks
+ }
+ }
+ }
+
+
+ chan.redirectTo(this.newURI);
+ chan.suspend();
+ if (typeof callback === "function") callback(this);
+ else this.open();
+ },
+ open: function() {
+ this.channel.resume();
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/ClearClickHandler.js b/extensions/noscript/chrome/content/noscript/ClearClickHandler.js
new file mode 100644
index 0000000..211c330
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/ClearClickHandler.js
@@ -0,0 +1,1414 @@
+function ClearClickHandler(ns) {
+ this.ns = ns;
+}
+
+ClearClickHandler.prototype = {
+
+ uiEvents: ["mousedown", "mouseup", "click", "dblclick", "drop", "keydown", "keypress", "keyup", "blur"],
+
+ rapidFire: {
+ events: ["keydown", "mousedown", "mouseover"],
+ quarantine: 800,
+ site: null,
+ ts: 0,
+ mouse: false,
+ lastOver: { x: 0, y: 0, site: '', ts: 0 },
+
+ check: function(ev, site, ts) {
+ const type = ev.type;
+
+ let mouse = false, over = false;
+ switch(type[0]) {
+ case 'c': case 'm':
+ mouse = true;
+ over = type === "mouseover";
+ case 'k':
+ break;
+
+ default:
+ return false;
+ }
+
+ // ns.log(ev.type + " " + ev.target + "@" + site + " <- " + this.site + " -- " + ev.timeStamp)
+
+ let lo = this.lastOver;
+
+ if (this.mouse === mouse) {
+ if (site !== this.site) {
+ let contentRx = /^(?:(?:ht|f)tps?|data|javascript|feed):/i;
+ if (contentRx.test(this.site) &&
+ (contentRx.test(site) || !contentRx.test(ev.target.ownerDocument.defaultView.top.location.href))
+ ) {
+
+ if (lo.site && lo.site !== site && (ts - lo.ts) < this.quarantine) {
+ let d = ev.target.ownerDocument;
+ let w = d.defaultView;
+ let de = d.documentElement;
+ let width = de.clientWidth;
+ let height = de.clientHeight;
+ let top = w.mozInnerScreenY + w.scrollY + de.offsetTop;
+ let left = w.mozInnerScreenX + w.scrollX + de.offsetLeft;
+ // ns.log("HOVER " + ev.target + "@" + lo.site + ", " + top + ", " + left + ", " + (top + height) + ", " + (left + width) + " - " + lo.y + ", " + lo.x );
+ if (lo.x > left && lo.x - left < width && lo.y > top && lo.y - top < height) {
+ this.ts = ts;
+ // ns.log("HOVER TS " + ts);
+ }
+ lo.site = '';
+ }
+
+ if (over) {
+ if (ts - lo.ts < this.quarantine) return false;
+ } else {
+ if (ts - this.ts < this.quarantine) {
+ if (!lo.site) this.ts = ts - this.quarantine / 2;
+ return ns.getPref("clearClick.rapidFireCheck");
+ }
+ }
+
+ }
+ }
+ } else this.mouse = mouse;
+
+ this.site = site;
+
+ if (over) {
+ if (!ev.target.contentWindow) {
+ lo.site = site;
+ lo.ts = ts;
+ let w = ev.target.ownerDocument.defaultView;
+ lo.x = ev.pageX + w.mozInnerScreenX;
+ lo.y = ev.pageY + w.mozInnerScreenY;
+ }
+ } else {
+ if (mouse) {
+ lo.site = '';
+ }
+ this.ts = ts;
+ }
+ return false;
+ }
+ },
+
+ chromeInstall(window) {
+ this._install(window.document, this.rapidFire.events);
+ },
+ chromeUninstall(window) {
+ this.uninstall(window.document);
+ },
+
+ install(target) {
+ this._install(target, this.uiEvents);
+ },
+
+ _install(target, events) {
+ for (let et of events) {
+ target.addEventListener(et, this, true);
+ }
+ (target._clearClickEvents || (target._clearClickEvents = [])).push(...events);
+ },
+
+ uninstall(target) {
+ let events = target._clearClickEvents;
+ try {
+ for (let et of events) {
+ target.removeEventListener(et, this, true);
+ }
+ ns.dump(`Removed [${events.join(", ")}] listener.`);
+ } catch (e) {
+ if (Components) Components.utils.reportError(e);
+ }
+ },
+
+ exceptions: null,
+
+ sameSiteParents: function(w) {
+ const ns = this.ns;
+ var site = ns.getSite(w.location.href);
+ if (site == "about:blank") site = "";
+ var parentSite;
+ for(var p = w.parent; p != w; w = p, p = w.parent) {
+ parentSite = ns.getSite(p.location.href);
+ if (!site || /^(?:chrome|resource|about):/.test(parentSite)) {
+ site = parentSite;
+ continue;
+ }
+ if (site != parentSite) return false;
+ }
+ if (ns.consoleDump & LOG_CLEARCLICK) ns.dump("ClearClick skipping, same site parents for " + site);
+ return true;
+ },
+
+ appliesHere: function(url) {
+ const ns = this.ns;
+ return ns.appliesHere(ns.clearClick, url) &&
+ !(this.exceptions && this.exceptions.test(url));
+ },
+
+ checkSubexception: function(url) {
+ return this.subexceptions && this.subexceptions.test(url);
+ },
+
+ _whitelist: {},
+ whitelistLen: 0,
+ isWhitelisted: function(w) {
+
+ var l = this._whitelist[w.location.href];
+ if (!l) return false;
+
+ var pp = [];
+ for(var p = w.parent; p != w; w = p, p = w.parent) {
+ pp.push(p.location.href);
+ }
+ return l.indexOf(pp.join(" ")) > -1;
+ },
+
+ whitelist: function(w) {
+ if (this.isWhitelisted(w)) return;
+ var u = w.location.href;
+
+ var pp = [];
+ for(var p = w.parent; p != w; w = p, p = w.parent) {
+ pp.push(p.location.href);
+ }
+
+ var l;
+ if (u in this._whitelist) l = this._whitelist[u];
+ else {
+ l = this._whitelist[u] = [];
+ this.whitelistLen++;
+ }
+
+ l.push(pp.join(" "));
+ },
+ resetWhitelist: function() {
+ this._whitelist = {};
+ this.whitelistLen = 0;
+ },
+ _embedRx: /^(?:object|embed)$/i,
+ isEmbed(o) {
+ return this._embedRx.test(o.tagName) &&
+ !o.contentDocument && ns.getExpando(o, "site") != ns.getSite(o.ownerDocument.documentURI)
+ },
+
+ swallowEvent: function(ev) {
+ ev.cancelBubble = true;
+ ev.stopPropagation();
+ ev.preventDefault();
+ },
+
+ _zoom: 1,
+
+
+ getBox: function(o, d, w) {
+ if (!d) d = o.ownerDocument;
+ if (!w) w = d.defaultView;
+ var c = o.getBoundingClientRect();
+ var x = c.left, y = c.top; // this is relative to the view port, just like mozInnerScreen*
+
+ return {
+ x: x + w.scrollX, y: y + w.scrollY, // add scroll* to make it absolute
+ width: c.width, height: c.height,
+ screenX: w.mozInnerScreenX + x, screenY: w.mozInnerScreenY + y
+ };
+ },
+
+
+ getBG: function(w) {
+ var bg = w.document.body && w.getComputedStyle(w.document.body, '').backgroundColor || "#fff";
+ return bg == "transparent" ? w != w.parent && this.getBG(w.parent) || "#fff" : bg;
+ },
+
+ _constrain: function(box, axys, dim, max, vp, center) {
+ var d;
+ var scr = "screen" + axys.toUpperCase();
+ // trim bounds to take in account fancy overlay borders
+ var l = box[dim];
+ var n = box[axys];
+
+ if (vp.frame && center && l < vp[dim]) { // expand to viewport if possible
+ l = vp[dim];
+ }
+
+ if (l > 6) {
+ var bStart = Math.floor(l * 0.1) // 20% border
+ var bEnd = bStart;
+ if (bStart + n > center) {
+ bStart = center - n;
+ } else if (l + n - center < bEnd) {
+ bEnd = l + n - center;
+ }
+ box[dim] = (l -= (bStart + bEnd));
+ box[axys] = (n += bStart);
+ box[scr] += bStart;
+
+ }
+
+ if (l > max) {
+ // resize
+ if (center) {
+ var halfMax = Math.round(max / 2);
+ var nn = center - halfMax;
+ if (nn > n && center + halfMax > n + l) nn = (n + l) - max;
+ box[axys] = nn;
+ box[scr] += (nn - n);
+ n = nn;
+ }
+ l = box[dim] = max;
+ }
+ // slide into viewport
+ var vpn = vp[axys];
+ d = (n < vpn)
+ ? vpn - n
+ : (n + l) > (vpn + vp[dim])
+ ? (vpn + vp[dim]) - (n + l)
+ : 0;
+
+ if (d) {
+ n = (box[axys] += d);
+ box[scr] += d;
+ }
+
+ },
+
+ get canvas() {
+ delete this.__proto__.canvas;
+ const impl = Cc["@mozilla.org/xul/xul-document;1"].createInstance(Ci.nsIDOMDocument).implementation;
+ return this.__proto__.canvas = (("createHTMLDocument" in impl)
+ ? impl.createHTMLDocument("")
+ : impl.createDocument(
+ HTML_NS, "html", impl.createDocumentType(
+ "html", "-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd"
+ ))
+ ).createElementNS(HTML_NS, "canvas");
+ },
+
+ _semanticContainersRx: /^(?:p|quote|ul|ol|dir|pre|table)$/i,
+ isSemanticContainer: function(o) { return this._semanticContainersRx.test(o.tagName) && o.ownerDocument.URL.indexOf("view-source") !== 0; },
+
+ forLog: function(o) {
+ return o.tagName + "/" + (o.tabIndex || 0);
+ },
+
+ handleEvent: function(ev) {
+ if (typeof ClearClickHandler === "undefined") { // uninstalled
+ ev.currentTarget.removeEventListener(ev.type, arguments.callee, true);
+ return;
+ }
+ const o = ev.target;
+ const d = o.ownerDocument;
+ if (!d) return;
+
+ if (d === ev.currentTarget || // chrome source, see rapidFire installation
+ ev.button || // right or middle click
+ ev.keyCode && // special keys, e.g. for UI navigation
+ (ev.ctrlKey || ev.metaKey || ev.altKey || ev.keyCode < 48 && ev.keyCode !== 13 && ev.keyCode !== 32)
+ ) {
+ this.rapidFire.ts = 0;
+ // this.ns.log("Reset global event tracking");
+ if (d === ev.currentTarget || ev.keyCode) return;
+ }
+
+
+ const w = d.defaultView;
+ if (!w) return;
+
+ const ns = this.ns;
+
+ const top = w.top;
+ const topURL = top.document.documentURI;
+
+ var isEmbed;
+ var ts = Date.now();
+
+ if (this.rapidFire.check(ev, d.documentURIObject.prePath, ts)) {
+ this.swallowEvent(ev);
+ ns.log("[NoScript ClearClick] Swallowed event " + ev.type + " on " +
+ d.documentURI + " (rapid fire from " + this.rapidFire.site +
+ " in " + (ts - this.rapidFire.ts) + "ms)", true);
+ return;
+ }
+
+ if (ev.type === "mouseover") return;
+
+ if (!("__clearClickUnlocked" in top))
+ top.__clearClickUnlocked = !this.appliesHere(topURL);
+
+ if (top.__clearClickUnlocked) return;
+
+ if (!("__clearClickUnlocked" in o)) {
+
+ o.__clearClickUnlocked =
+ o === d.documentElement || o === d.body || // key event on empty region
+ this.isSemanticContainer(o) ||
+ !(isEmbed = this.isEmbed(o)) && // plugin embedding?
+ (w == top ||
+ ("__clearClickUnlocked" in w
+ ? w.__clearClickUnlocked
+ : (w.__clearClickUnlocked = this.isWhitelisted(w))
+ ) ||
+ this.sameSiteParents(w) // cross-site document?
+ ) ||
+ isEmbed && ns.isClickToPlay(o) ||
+ ns.getPluginExtras(o) && ns.getPref("confirmUnblock") || // Just enabled from NS placeholder after prompt?
+ this.checkSubexception(isEmbed && (o.src || o.data) || w.location.href);
+ }
+
+ if (o.__clearClickUnlocked || w.__clearClickUnlocked) return;
+
+ var p = ns.getExpando(o, "clearClickProps", {});
+ var verbose = ns.consoleDump & LOG_CLEARCLICK;
+ var etype = ev.type;
+ if (verbose) ns.dump(o.tagName + ", " + etype + ", " + p.toSource());
+
+ var obstructed, ctx, primaryEvent;
+ try {
+ if (etype == "blur") {
+ if(/click|key/.test(p.lastEtype)) {
+ if (verbose) ns.dump("ClearClick: resetting status on " + this.forLog(o) + " for " + etype);
+ if (p.unlocked) p.unlocked = false;
+ }
+ return;
+ }
+ if (p.unlocked) return;
+
+ ctx = /mouse|drop/.test(etype)
+ && { x: ev.pageX, y: ev.pageY, debug: ev.ctrlKey && ev.button == 1 && ns.getPref("clearClick.debug") }
+ || {};
+ isEmbed = (typeof(isEmbed) === "boolean" ? isEmbed : this.isEmbed(o)) // && ns.isWindowlessObject(o);
+ if (!(isEmbed || w.frameElement)) return;
+ ctx.isEmbed = isEmbed;
+ primaryEvent = /^(?:(?:mouse|key)down|drop)$/.test(etype) ||
+ // submit button generates a syntethic click if any text-control receives [Enter]: we must consider this "primary"
+ etype == "click" && ev.screenX == 0 && ev.screenY == 0 && ev.pageX == 0 && ev.pageY == 0 && ev.clientX == 0 && ev.clientY == 0 && ev.target.form &&
+ ((ctx.box = this.getBox(ev.target, d, w)).screenX * ctx.box.screenY != 0) ||
+ // allow infra-document drag operations and tabulations
+ etype != "blur" && top.__clearClickDoc == d && (top.__clearClickProps.unlocked || top.__clearClickProps.lastEtype == "blur");
+
+ obstructed = (primaryEvent || !("obstructed" in p))
+ ? p.obstructed = this.checkObstruction(o, ctx)
+ : p.obstructed; // cache for non-primary events
+ } catch(e) {
+ ns.dump(e);
+ obstructed = true;
+ } finally {
+ p.lastEtype = etype;
+ top.__clearClickProps = p;
+ top.__clearClickDoc = d;
+ }
+
+ var quarantine = ts - (p.ts || 0);
+
+ if (verbose) ns.dump("ClearClick: " + ev.target.tagName + " " + etype +
+ "(s:{" + ev.screenX + "," + ev.screenY + "}, p:{" + ev.pageX + "," + ev.pageY + "}, c:{" + ev.clientX + "," + ev.clientY +
+ ", w:" + ev.which + "}) - obstructed: " + obstructed + ", check time: " + (Date.now() - ts) + ", quarantine: " + quarantine +
+ ", primary: " + primaryEvent + ", ccp:" + (top.__clearClickProps && top.__clearClickProps.toSource()));
+
+ var unlocked = !obstructed && primaryEvent && quarantine > 3000;
+
+ if (unlocked) {
+ if (verbose) ns.dump("ClearClick: unlocking " + ev.target.tagName + " " + etype);
+ p.unlocked = true;
+ } else {
+
+ this.swallowEvent(ev);
+ ns.log("[NoScript ClearClick] Swallowed event " + etype + " on " + this.forLog(o) + " at " + w.location.href, true);
+ var docShell = DOM.getDocShellForWindow(w);
+ var loading = docShell && (docShell instanceof Ci.nsIWebProgress) && docShell.isLoadingDocument;
+ if (!loading) {
+ p.ts = ts;
+ if (primaryEvent && ctx.img && ns.getPref("clearClick.prompt") && !this.prompting) {
+ try {
+ this.prompting = true;
+ let params = {
+ url: ctx.isEmbed && (o.src || o.data) || o.ownerDocument.URL,
+ pageURL: w.location.href,
+ topURL: topURL,
+ img: ctx.img,
+ locked: false,
+ pageX: ev.pageX,
+ pageY: ev.pageY,
+ zoom: this._zoom
+ };
+ if (!this.showWarning(w, params)) {
+ w.__clearClickUnlocked = o.__clearClickUnlocked = true
+ this.whitelist(w);
+ }
+ } finally {
+ this.prompting = false;
+ }
+ }
+ }
+ }
+ },
+
+ showWarningParent(window, params) {
+ window.openDialog(
+ "chrome://noscript/content/clearClick.xul",
+ "noscriptClearClick",
+ "chrome, dialog, dependent, centerscreen, modal",
+ params);
+ return params;
+ },
+ showWarning(window, params) {
+ return DOM.getFrameMM(window).sendSyncMessage(IPC_MSG.CLEARCLICK_WARNING, params)[0];
+ },
+
+ findParentForm: function(o) {
+ var ftype = Cu.getGlobalForObject(o).HTMLFormElement;
+ if (!ftype) return null;
+ while((o = o.parentNode)) {
+ if (o instanceof ftype) return o;
+ }
+ return null;
+ },
+
+
+ rndColor: function() {
+ var c = Math.round(Math.random() * 0xffffff).toString(16);
+ return "#" + ("000000".substring(c.length)) + c;
+ },
+
+
+ maxWidth: 350,
+ maxHeight: 200,
+ minWidth: 160,
+ minHeight: 100,
+ _NO_SCROLLBARS: {w: 0, h: 0},
+ computeScrollbarSizes: function(window, dElem, body) {
+ var fw = window.innerWidth, fh = window.innerHeight;
+
+ if (body && body.ownerDocument.compatMode == "BackCompat") {
+ dElem = body;
+ }
+
+ var dw = dElem.clientWidth, dh = dElem.clientHeight;
+ var w = Math.min(fw, dw), h = Math.min(fh, dh);
+
+ var zoom = window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils).screenPixelsPerCSSPixel;
+
+ return { w: (fw - w) * zoom, h: (fh - h) * zoom };
+ },
+
+ checkObstruction: function(o, ctx) {
+ var d = o.ownerDocument;
+ var w = d.defaultView;
+ if (!(ctx.isEmbed || d instanceof w.HTMLDocument)) {
+ o = w.frameElement;
+ d = o.ownerDocument;
+ w = d.defaultView;
+ ctx.isEmbed = true;
+ }
+
+ var dElem = d.documentElement;
+
+ var top = w.top;
+
+ if (!DOM.getFrameMM(top)) return false; // some extensions, e.g. FoxTab, cause this
+
+ var c = this.canvas;
+ var gfx = c.getContext("2d");
+
+ var bg = this.getBG(w);
+
+ var bgStyle;
+ var box, rootBox, curtain, woi;
+
+ var frame, frameClass, objClass;
+
+ var docPatcher = new DocPatcher(this.ns, o, w);
+
+ var sheet = null;
+
+ var img1 = null, img2 = null, tmpImg = null;
+
+ function Snapshot(w, x, y) {
+ gfx.drawWindow(w, Math.round(x), Math.round(y), c.width, c.height, bg);
+ if (woi && w == top && rootBox) {
+ gfx.fillStyle = bg;
+ for (let b of woi)
+ gfx.fillRect(b.screenX - rootBox.screenX - x, b.screenY - rootBox.screenY - y, b.width, b.height);
+ }
+ this.imageData = gfx.getImageData(0, 0, c.width, c.height);
+ }
+
+ Snapshot.prototype = {
+ THRESHOLD: ns.getPref("clearClick.threshold") / 100,
+ resembles: function(other) {
+ if (other === null) return false;
+
+ let buf1 = this.imageData.data;
+ let buf2 = other.imageData.data;
+ let diff = 0, eq = 0;
+ const w = this.imageData.width;
+ const h = this.imageData.height;
+ const tot = w * h;
+ const maxDiff = Math.round(tot * this.THRESHOLD);
+ const minEq = tot - maxDiff;
+ let resembles = true;
+ resembles_loop:
+ for (let x = 0; x < w; x++) {
+ for (let y = 0; y < h; y++) {
+ let p = (y * w + x) * 4;
+ let r1 = buf1[p], r2 = buf2[p],
+ g1 = buf1[++p], g2 = buf2[p],
+ b1 = buf1[++p], b2 = buf2[p];
+ if (r1 !== r2 || g1 !== g2 || b1 !== b2) {
+ if (++diff > maxDiff) {
+ resembles = false;
+ break resembles_loop;
+ }
+ } else if (++eq > minEq) {
+ break resembles_loop;
+ }
+ }
+ }
+ if (ns.consoleDump & LOG_CLEARCLICK) {
+ ns.dump("Diff: " + diff + " / Tot: " + tot + "(maxDiff = " + maxDiff + ")");
+ }
+ return resembles;
+ },
+ toURL: function(imageData) {
+ gfx.putImageData(imageData || this.imageData, 0, 0);
+ return c.toDataURL();
+ }
+ }
+
+ function compareSnapshots(x1, y1, x2, y2) {
+ img1 = null;
+ try {
+ if (objClass) {
+ docPatcher.clean(true);
+ }
+ if (curtain && !curtain.parentNode) {
+ if (o.nextSibling) {
+ o.parentNode.insertBefore(curtain, o.nextSibling);
+ } else {
+ o.parentNode.appendChild(curtain);
+ }
+ }
+ img1 = new Snapshot(w, x1, y1);
+ } catch(ex) {
+ throw ex;
+ } finally {
+ docPatcher.clean(false);
+ }
+ img2 = tmpImg = new Snapshot(top, x2, y2);
+ return ret && !img1.resembles(img2);
+ }
+
+ var sd = this._NO_SCROLLBARS;
+
+ try {
+
+ docPatcher.linkAlertHack(true);
+ docPatcher.fbPresenceHack(true);
+ docPatcher.abpTabsHack(true);
+ docPatcher.trafficLightHack(true);
+ try {
+ docPatcher.opaque(true);
+
+ var fbPresence; // hack for Facebooks's fixed positioned widget
+
+ if (ctx.isEmbed) { // objects and embeds
+ if (this.ns.getPref("clearClick.plugins", true)) {
+ objClass = new ClassyObj(o);
+ objClass.append(" __noscriptBlank__");
+ docPatcher.blankPositioned(true);
+ docPatcher.clean(true);
+ } else {
+ DOM.addClass(o, "__noscriptOpaqued__");
+ }
+ }
+
+ if ((frame = w.frameElement)) {
+ frameClass = new ClassyObj(frame);
+ DOM.removeClass(frame, "__noscriptScrolling__");
+ sd = this.computeScrollbarSizes(w, dElem, d.body);
+
+ }
+
+ let clientHeight = w.innerHeight - sd.h;
+ let clientWidth = w.innerWidth - sd.w;
+ // print(dElem.clientWidth + "," + dElem.clientHeight + " - " + w.innerWidth + "," + w.innerHeight);
+
+ if (!ctx.isEmbed) {
+ curtain = d.createElementNS(HTML_NS, "div");
+ with (curtain.style) {
+ top = left = "0px";
+
+ width = (clientWidth + w.scrollX) + "px";
+ height = (clientHeight + w.scrollY) + "px";
+
+ padding = margin = borderWidth = MozOutlineWidth = "0px";
+ position = "absolute";
+ zIndex = DOM.maxZIndex;
+
+ background = this.rndColor();
+ }
+ }
+
+ let maxWidth = Math.max(Math.min(this.maxWidth, clientWidth), sd.w ? 0 : Math.min(this.minWidth, dElem.offsetWidth), 8);
+ let maxHeight = Math.max(Math.min(this.maxHeight, clientHeight), sd.h ? 0 : Math.min(this.minHeight, dElem.offsetHeight, 8));
+
+ for (;;) {
+ box = this.getBox(o, d, w);
+ if (box.width > 0 && box.height > 0) break;
+ o = o.parentNode;
+ if (!o) return false;
+ }
+
+ // expand to parent form if needed
+ var form = o.form;
+ if (frame && !ctx.isEmbed && (form || (form = this.findParentForm(o)))) {
+
+ let formBox = this.getBox(form, d, w);
+ if (!(formBox.width && formBox.height)) { // some idiots put <form> as first child of <table> :(
+ formBox = this.getBox(form.offsetParent || form.parentNode, d, w);
+ if (!(formBox.width && formBox.height)) {
+ formBox = this.getBox(form.parentNode.offsetParent || o.offsetParent, d, w);
+ }
+ }
+
+ if (formBox.width && formBox.height) {
+ // form has layout, recenter to show as much as possible
+ ctx.x = ctx.x || box.x + box.width; // use mouse coordinates or
+ ctx.y = ctx.y || box.y + box.height; // rightmost widget position
+
+ box = formBox; // the form is our new reference
+
+ var delta;
+
+ // move inside the viewport if needed
+ if (box.x < 0) {
+ box.screenX -= box.x;
+ box.x = 0;
+ }
+ if (box.y < 0) {
+ box.screenY -= box.y;
+ box.y = 0;
+ }
+
+ // is our center out of the form?
+ if (box.x + Math.min(box.width, maxWidth) < ctx.x) {
+ box.width = Math.min(box.width, maxWidth);
+ delta = ctx.x + 4 - box.width - box.x;
+ box.x += delta;
+ box.screenX += delta;
+
+ }
+ if (box.y + Math.min(box.height, maxHeight) < ctx.y) {
+ box.height = Math.min(box.height, maxHeight);
+ delta = ctx.y + 4 - box.height - box.y;
+ box.y += delta;
+ box.screenY += delta;
+ }
+
+ // recenter to the form
+ ctx.x = box.x + box.width / 2;
+ ctx.y = box.y + box.height / 2;
+
+ o = form;
+ }
+ }
+
+ bgStyle = dElem.style.background;
+ dElem.style.background = bg;
+
+ // clip, slide in viewport and trim
+
+ var vp = {
+ x: w.scrollX,
+ y: w.scrollY + 3, // 3 pixels grace for box shadows cast from above a frame, like in the FB header
+ width: Math.max(w.innerWidth - sd.w, 32),
+ height: Math.max(w.innerHeight - sd.h - 3, 16), // Facebook like buttons are 20 pixel high
+ frame: frame
+ };
+
+ var rtlOffset = 0;
+
+ if (ctx.isEmbed) { // check in-page vieport
+ vp.frame = null;
+ vp.x = Math.max(vp.x, box.x);
+ vp.y = Math.max(vp.y, box.y);
+ vp.width = Math.min(vp.width, box.width);
+ vp.height = Math.min(vp.height, box.height);
+
+ for(let ancestor = o; ancestor = ancestor.parentNode;) {
+
+ if ((ancestor.offsetWidth < box.width || ancestor.offsetHeight < box.height) &&
+ w.getComputedStyle(ancestor, '').overflow != "visible") {
+
+ // check if we're being fooled by some super-zoomed applet
+ if (box.width / 4 <= ancestor.offsetWidth && box.height / 4 <= ancestor.offsetHeight) {
+ let ancestorBox = this.getBox(ancestor, d, w);
+
+ if (box.x < ancestorBox.x) {
+ box.x = ancestorBox.x;
+ box.screenX = ancestorBox.screenX;
+ }
+ if (box.y < ancestorBox.y) {
+ box.y = ancestorBox.y;
+ box.screenY = ancestorBox.screenY;
+ }
+ if (box.width + box.x > ancestorBox.width + ancestorBox.x) box.width = Math.max(this.minWidth, ancestor.clientWidth - (box.x - ancestorBox.x));
+ if (box.height + box.y > ancestorBox.height + ancestorBox.y) box.height = Math.max(this.minHeight, ancestor.offsetHeight - (box.y - ancestorBox.y));
+ }
+ break;
+ }
+ }
+ } else {
+
+ // correct x offsets according to left scrollbars if needed
+ try {
+ var adaptiveScrollerSide = false;
+ switch(this.ns.prefService.getIntPref("layout.scrollbar.side")) {
+ case 1:
+ adaptiveScrollerSide = true;
+ case 0:
+ if (!adaptiveScrollerSide && this.ns.prefService.getIntPref("bidi.direction") != 2)
+ break;
+ case 3:
+ vp.x += this._scrollerCorrect(w, adaptiveScrollerSide);
+ rtlOffset = this._scrollerCorrect(top, adaptiveScrollerSide);
+ }
+ } catch(e) {
+ if (ns.consoleDump & LOG_CLEARCLICK) ns.dump(e);
+ }
+
+ }
+
+ // clip viewport intersecting with scrolling parents
+
+ const CLIP_MIN = 64;
+ var clip = this._clip(o.parentNode, frame ? this.getBox(frame) : box);
+ if (clip.h != 0) {
+ if (vp.height + clip.h >= CLIP_MIN) vp.height += clip.h;
+ else vp.height = CLIP_MIN;
+ if (maxHeight + clip.h >= CLIP_MIN) maxHeight += clip.h;
+ else maxHeight = CLIP_MIN;
+ }
+ if (clip.w != 0) {
+ if (vp.width + clip.w >= CLIP_MIN) vp.width += clip.w;
+ else vp.width = CLIP_MIN;
+ if (maxWidth + clip.w >= CLIP_MIN) maxWidth += clip.w;
+ else maxWidth = CLIP_MIN;
+ }
+ vp.x += clip.x;
+ vp.y += clip.y;
+
+ // Fit in viewport
+
+ box.oX = box.x;
+ box.oY = box.y;
+ box.oW = box.width;
+ box.oH = box.height;
+
+ // print("Fitting " + box.toSource() + " in " + vp.toSource() + " - ctx " + ctx.x + ", " + ctx.y + " - max " + maxWidth + ", " + maxHeight);
+
+ this._constrain(box, "x", "width", maxWidth, vp, ctx.x);
+ this._constrain(box, "y", "height", maxHeight, vp, ctx.y);
+ // print(box.toSource());
+
+
+
+ c.width = box.width;
+ c.height = box.height;
+
+ woi = this.findWindowedRects(ctx.isEmbed ? o : w.frameElement);
+
+ if (this.ns.consoleDump & LOG_CLEARCLICK) this.ns.dump("Snapshot at " + box.toSource() + " + " + w.pageXOffset + ", " + w.pageYOffset);
+
+ if (curtain && frame) {
+ dElem.appendChild(curtain);
+ }
+
+ img1 = new Snapshot(w, box.x, box.y);
+
+ } finally {
+ docPatcher.clean(false);
+ }
+
+
+ var rootElement = top.document.documentElement;
+ rootBox = this.getBox(rootElement, top.document, top);
+
+
+ var offsetY = (box.screenY - rootBox.screenY);
+ var offsetX = (box.screenX - rootBox.screenX) + rtlOffset;
+
+ var ret = true;
+ var tmpImg;
+
+ const offs = ctx.isEmbed ? [0] : [0, -1, 1, -2, 2, -3, -3];
+
+ checkImage:
+ for (let x of offs) {
+ for (let y of offs) {
+ tmpImg = new Snapshot(top, offsetX + x, offsetY + y);
+ if (img1.resembles(tmpImg)) {
+ ret = false;
+ break checkImage;
+ }
+ if (!img2) img2 = tmpImg;
+ }
+ }
+
+ if (ret && !curtain && ctx.isEmbed) {
+ curtain = d.createElementNS(HTML_NS, "div");
+ if (docPatcher) curtain.className = docPatcher.shownCS;
+ with (curtain.style) {
+ // we expand by 1 pixel in order to avoid antialias effects on the edge at zoom != 1 (GMail Flash attachment)
+ top = (o.offsetTop - 1) + "px";
+ left = (o.offsetLeft -1) + "px";
+ width = (o.offsetWidth +2) + "px";
+ height = (o.offsetHeight +2) + "px";
+ position = "absolute";
+ zIndex = w.getComputedStyle(o, '').zIndex;
+ background = this.rndColor();
+ }
+
+ ret = compareSnapshots(box.x, box.y, offsetX, offsetY);
+ }
+
+ if (ret && ctx.isEmbed && ("x" in ctx) && c.width > this.minWidth && c.height > this.minHeight) {
+ c.width = this.minWidth;
+ c.height = this.minHeight;
+ for (x of [Math.max(ctx.x - this.minWidth, box.oX), Math.min(ctx.x, box.oX + box.oW - this.minWidth)]) {
+ for (y of [Math.max(ctx.y - this.minHeight, box.oY), Math.min(ctx.y, box.oY + box.oH - this.minHeight)]) {
+ ret = compareSnapshots(x, y, offsetX + (x - box.x), offsetY + (y - box.y));
+ if (!ret) {
+ offsetX += (x - box.x);
+ offsetY += (y - box.y);
+ box.x = x;
+ box.y = y;
+ break;
+ }
+ }
+ if (!ret) break;
+ }
+ }
+
+ if (ctx.debug || this.checkCursor(ctx.isEmbed ? o : frame)) {
+ ret = true;
+ img2 = tmpImg;
+ }
+
+ if (ret) {
+
+ if (curtain) {
+
+ if (ctx.debug) {
+
+ if (docPatcher.cleanSheet) {
+ curtain.id = "curtain_" + DOM.rndId();
+ docPatcher.cleanSheet += " #" + curtain.id + " { opacity: .4 !important }";
+ }
+
+ curtain.style.opacity = ".4"
+
+ } else {
+ curtain.parentNode.removeChild(curtain);
+ curtain = null;
+ }
+ compareSnapshots(box.x, box.y, offsetX, offsetY);
+ }
+
+ ctx.img =
+ {
+ src: img1.toURL(),
+ altSrc: img2.toURL(),
+ width: c.width,
+ height: c.height
+ }
+ }
+
+ } finally {
+ if (ctx.isEmbed) docPatcher.blankPositioned(false);
+
+
+ if (curtain && curtain.parentNode) curtain.parentNode.removeChild(curtain);
+ if (typeof(bgStyle) == "string") dElem.style.background = bgStyle;
+
+ docPatcher.opaque(false);
+ docPatcher.trafficLightHack(false);
+ docPatcher.abpTabsHack(false);
+ docPatcher.fbPresenceHack(false);
+ docPatcher.linkAlertHack(false);
+
+ if (objClass) objClass.reset();
+ if (frameClass) frameClass.reset();
+ }
+
+ return ret;
+
+ },
+
+ checkCursor: function(o) {
+ let w = o.ownerDocument.defaultView;
+ let HTMLElement = w.HTMLElement;
+ for(; o && o instanceof HTMLElement; o = o.parentNode) {
+ try {
+ let cursor = w.getComputedStyle(o, ':hover').cursor;
+ if (cursor === "none" || cursor.indexOf("url(") !== -1) return true;
+ } catch (e) {}
+ }
+ return w.frameElement && this.checkCursor(w.frameElement);
+ },
+
+ _clip: function(parent, box) {
+ const MIN = 64;
+
+ // backtrack all the overflow~="auto|scroll" parent elements and clip
+
+ var pw = parent.ownerDocument.defaultView;
+
+ var current, cbox;
+ var dw = 0, dh = 0, dx = 0, dy = 0;
+
+ var bx = box.screenX;
+ var by = box.screenY;
+ var bw = box.width;
+ var bh = box.height;
+
+ const ELEMENT = Ci.nsIDOMElement;
+
+ while(parent) {
+
+ current = parent;
+ switch (pw.getComputedStyle(current, '').overflow) {
+ case "auto" : case "scroll":
+ cbox = this.getBox(current);
+
+ d = cbox.screenY - by;
+ if (d > 0) {
+ dy += d;
+ dh -= d;
+ by += d;
+ bh -= d;
+ }
+ d = cbox.screenX - bx;
+ if (d > 0) {
+ dx += d;
+ dw -= d;
+ bx += d;
+ bw -= d;
+
+ }
+ d = by + bh - (cbox.screenY + current.clientHeight);
+ if (d > 0) {
+ if (cbox.height - current.clientHeight < 10) // compensate for miscalculated scrollbars bug
+ d += 20;
+ dh -= d;
+ bh -= d;
+ }
+ d = bx + bw - (cbox.screenX + current.clientWidth);
+ if (d > 0) {
+ if (cbox.width - current.clientWidth < 10) // compensate for miscalculated scrollbars bug
+ d += 20;
+ dw -= d;
+ bw -= d;
+ }
+ }
+ parent = current.parentNode;
+ if (parent instanceof ELEMENT) continue;
+ parent = pw.frameElement;
+ if (parent) pw = parent.ownerDocument.defaultView;
+ }
+
+ return { x: dx, y: dy, w: dw, h: dh };
+ },
+
+ _scrollerCorrect: function(w, adaptive) {
+ return (adaptive && w.getComputedStyle(w.document.body || w.document.documentElement, '').direction != 'rtl')
+ ? 0
+ : w.innerWidth - w.document.documentElement.clientWidth;
+ },
+
+ _offsetParents: function(p) {
+ let pp = [];
+ for (; p; p = p.offsetParent) pp.push(p);
+ return pp;
+ },
+
+ get _ignoreWindowedZ() {
+ delete this.__proto__._ignoreWindowedZ;
+ return this.__proto__._ignoreWindowedZ = ns.geckoVersionCheck("10.0") < 0;
+ },
+ findWindowedRects: function(el) {
+ const tags = ["object", "embed"];
+ var woi = null;
+
+ while(el) {
+ let d = el.ownerDocument;
+ let w = d.defaultView;
+ let elPP = this._offsetParents(el);
+ try {
+ for (let t of tags) {
+ let oo = d.getElementsByTagName(t);
+ for (let i = oo.length; i-- > 0;) {
+ let o = oo[i];
+ if (o != el && !ns.isWindowlessObject(o)) {
+ let oPP = this._offsetParents(o);
+ for (let j = elPP.length, k = oPP.length; j-- > 0 && k-- > 0;) {
+ let p1 = elPP[j], p2 = oPP[k];
+ if (p1 != p2) {
+ let s1 = w.getComputedStyle(p1, '');
+ let s2 = w.getComputedStyle(p2, '');
+
+ if (s2.display != 'none' && s2.visibility != 'hidden' &&
+ (this._ignoreWindowedZ ||
+ (s2.position != 'static' &&
+ (s1.position == 'static' ||
+ (parseInt(s1.zIndex, 10) || 0) <= (parseInt(s2.zIndex, 10) || 0)))
+ )
+ ) {
+ (woi || (woi = [])).push(this.getBox(o, d, w));
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch (e) {
+ ns.log(e);
+ }
+ el = w.frameElement;
+ }
+ return woi;
+ }
+}
+
+function ClassyObj(o) {
+ this.o = o;
+ if (o.hasAttribute("class")) this.c = o.className;
+}
+ClassyObj.prototype = {
+ o: null,
+ c: null,
+ append: function(newC) {
+ try {
+ this.o.className = this.c ? this.c + newC : newC;
+ } catch(e) {}
+ },
+ reset: function() {
+ try {
+ if (this.c == null) this.o.removeAttribute("class");
+ else this.o.className = this.c;
+ } catch(e) {}
+ }
+}
+
+function DocPatcher(ns, o, w) {
+ this.ns = ns;
+ this.o = o;
+ this.win = w;
+ this.top = w.top;
+ this.shownCS = " __noscriptShown__" + DOM.rndId();
+}
+
+DocPatcher.prototype = {
+
+ collectAncestors: function(o) {
+ var res = [];
+ for(; o && o.hasAttribute; o = o.parentNode) res.push(new ClassyObj(o));
+ return res;
+ },
+
+ getRect: function(o, d) {
+ return (this.getRect = ("getBoundingClientRect" in o)
+ ? function(o) { return o.getBoundingClientRect() }
+ : function(o, d) {
+ var b = d.getBoxObjectFor(o);
+ var x = o.x, y = o.y;
+ return {
+ left: x,
+ top: y,
+ right: x + o.width,
+ bottom: y + o.height
+ };
+ })(o, d)
+ },
+
+ collectPositioned: function(d) {
+ var t = Date.now();
+ const w = d.defaultView;
+ const res = [];
+ var s = null, p = '', n = null;
+
+ const r = this.o.getBoundingClientRect();
+ const top = r.top;
+ const bottom = r.bottom;
+ const left = r.left;
+ const right = r.right;
+
+ var c = '', b = null;
+ var hasPos = false;
+ const posn = [];
+
+ const tw = d.createTreeWalker(d, Ci.nsIDOMNodeFilter.SHOW_ELEMENT, null, false);
+ for (var n = null; (n = tw.nextNode());) {
+ b = n.getBoundingClientRect();
+ if (b.bottom < top || b.top > bottom ||
+ b.right < left || b.left > right)
+ continue;
+
+ s = w.getComputedStyle(n, '');
+ p = s.position;
+ if (p == "absolute" || p == "fixed") {
+ c = " __noscriptPositioned__";
+ n.__noscriptPos = hasPos = true;
+ posn.push(n);
+ } else {
+ hasPos = hasPos && n.parentNode.__noscriptPos;
+ if (!hasPos) continue;
+ c = '';
+ n.__noscriptPos = true;
+ posn.push(n);
+ }
+
+ if (s.backgroundImage != "none" || s.backgroundColor != "transparent") {
+ c += " __noscriptBlank__";
+ };
+
+
+ if (c) {
+ res.push(n = new ClassyObj(n));
+ n.append(c);
+ }
+ }
+
+ for (n of posn) n.__noscriptPos = false;
+
+ if(ns.consoleDump & LOG_CLEARCLICK) ns.dump("DocPatcher.collectPositioned(): " + (Date.now() - t));
+ return res;
+ },
+
+ collectOpaqued: function(o, oo) {
+ if (!oo) oo = { opacity: 1, res: [] };
+
+ var w = o.ownerDocument.defaultView;
+
+ var opacity;
+ var co = null;
+ for(; o && o.hasAttribute; o = o.parentNode) {
+ opacity = parseFloat(w.getComputedStyle(o, '').opacity);
+ if (opacity < 1) {
+ if ((oo.opacity *= opacity) < .3) return []; // too much combined transparency!
+ oo.res.push(new ClassyObj(o));
+ }
+ }
+
+ o = w.frameElement;
+ return o ? this.collectOpaqued(o, oo) : oo.res;
+ },
+
+ forceVisible: function(co) { // TODO: I cause too much reflow, please CHECK ME!
+ co.append(this.shownCS);
+ },
+
+ forceOpaque: function(co) {
+ co.append(" __noscriptJustOpaqued__");
+ },
+
+ resetClass: function(co) {
+ co.reset();
+ },
+
+ _ancestors: null,
+ _cleanSheetHandle: null,
+ clean: function(toggle) {
+ if (toggle) {
+ if (!this._ancestors) {
+ this.cleanSheet = "body * { visibility: hidden !important } body ." + this.shownCS.substring(1) + " { visibility: visible !important; opacity: 1 !important }";
+ this._ancestors = this.collectAncestors(this.o);
+ }
+ this._ancestors.forEach(this.forceVisible, this);
+ this._cleanSheetHandle = this.applySheet(this.cleanSheet);
+ } else if (this._ancestors) {
+ this._ancestors.forEach(this.resetClass);
+ this.removeSheet(this._cleanSheetHandle);
+ }
+ },
+
+ _positioned: null,
+ _blankSheetHandle: null,
+ blankSheet: ".__noscriptPositioned__ * { color: white !important; border-color: white !important; }",
+ blankPositioned: function(toggle) {
+ if (toggle) {
+ this._positioned = this.collectPositioned(this.o.ownerDocument);
+ this._blankSheetHandle = this.applySheet(this.blankSheet);
+ } else if (this._positioned) {
+ this._positioned.forEach(this.resetClass);
+ this.removeSheet(this._blankSheetHandle);
+ }
+ },
+
+ _opaqued: null,
+ opaque: function(toggle) {
+ if (toggle) {
+ this._opaqued = this._opaqued || this.collectOpaqued(this.o);
+ this._opaqued.forEach(this.forceOpaque);
+ } else if (this._opaqued) {
+ this._opaqued.forEach(this.resetClass);
+ }
+ },
+
+
+ applySheet: function(sheetHandle) {
+ this.ns.updateStyleSheet(sheetHandle, true);
+ return sheetHandle;
+ },
+ removeSheet: function(sheetHandle) {
+ this.ns.updateStyleSheet(sheetHandle, false);
+ },
+
+ trafficLightHack: function(toggle) {
+ const ID = "tll_hui_container";
+ if (!(toggle && this.top.document.getElementById(ID))) return;
+
+ delete this.__proto__.trafficLightHack;
+ try {
+ Cc["@mozilla.org/chrome/chrome-registry;1"]
+ .getService(Ci.nsIChromeRegistry)
+ .convertChromeURL(IOS.newURI("chrome://trafficlight/content", null, null));
+ } catch(e) {
+ this.__proto__.trafficLightHack = DUMMY_FUNC;
+ return;
+ }
+ this.__proto__._trafficLightHackToogle = false;
+ this.__proto__.trafficLightHack = function(toggle) {
+ var w = this.top;
+ var d = w.document;
+ var c = d.getElementById(ID);
+ if (!toggle) {
+ if (this._trafficLightHackToggle) {
+ c.style.visibility = "visible";
+ this._trafficLightHackToggle = false;
+ }
+ return;
+ }
+ if (w.getComputedStyle(c, '').visibility !== "visible") return;
+
+ for (let n of Array.push(c, c.getElementsByTagName("*"))) {
+ if (n.getBoundingClientRect().bottom > 50) return;
+ }
+ c.style.visibility = "hidden";
+ this._trafficLightHackToggle = true;
+ }
+ this.trafficLightHack(toggle);
+ },
+
+ _linkAlertBox: null,
+ linkAlertHack: function(toggle) {
+ try {
+ var w = this.top;
+ var d = w.document;
+ if (toggle) {
+ let box = d.getElementById("linkalert-box");
+ if (!box || box.style.display) return;
+ let imgs = box.getElementsByTagName("img");
+ if (imgs.length > 5) return;
+ for (let j = imgs.length; j-- > 0;) {
+ let img = imgs[j];
+ if (!/^(?:chrome:\/\/linkalert\/skin\/|(?:moz\-icon|file):\/\/)/.test(img.src) || img.naturalWidth == 0 ||
+ img.offsetWidth > 32 || img.offsetHeight > 32) return;
+ }
+ box.style.display = "none";
+ this._linkAlertBox = box;
+ } else {
+ if (this._linkAlertBox) {
+ this._linkAlertBox.style.display = "";
+ this._linkAlertBox = null;
+ }
+ }
+ } catch (e) {}
+ },
+
+ _fbPresence: null,
+ fbPresenceHack: function(toggle) {
+ if (toggle) {
+ try {
+ if (this.top.location.host == "apps.facebook.com") {
+ var fbPresence = this.top.document.getElementById("presence");
+ if (fbPresence) {
+ fbPresence._ccVisibility = fbPresence.style.visibility;
+ fbPresence.style.visibility = "hidden";
+ this._fbPresence = fbPresence;
+ }
+ }
+ } catch(e) {}
+ } else if (this._fbPresence) {
+ this._fbPresence.style.visibility = this._fbPresence._ccVisibility;
+ }
+ },
+
+ _abpTabs: null,
+ get _abpTabsObj() {
+ delete this.__proto__._abpTabsObj;
+ var tobj;
+ try {
+ tobj = Cc["@mozilla.org/adblockplus;1"].getService().wrappedJSObject.objTabs;
+ } catch(e) {
+ try {
+ let baseURL = Cc["@adblockplus.org/abp/private;1"].getService(Ci.nsIURI);
+ let x = {};
+ Cu.import(baseURL.spec + "ObjectTabs.jsm", x);
+ tobj = (x.objectMouseEventHander.__parent__ || Cu.getGlobalForObject(x.objectMouseEventHander)).objTabs;
+ } catch (e) {
+ tobj = null;
+ }
+ }
+ return this.__proto__._abpTabsObj = tobj;
+ },
+
+ abpTabsHack: function(toggle) {
+ let visibleClass, hiddenClass;
+ try {
+ let tobj = this._abpTabsObj;
+ if (tobj) {
+ hiddenClass = tobj.objTabClassHidden;
+ if (!hiddenClass) return;
+ visibleClasses = [tobj.objTabClassVisibleTop, tobj.objTabClassVisibleBottom];
+ }
+ } catch(e) {
+ }
+ delete this.__proto__.abpTabsHack;
+ this.__proto__.abpTabsHack =
+ hiddenClass
+ ? function(toggle) {
+ try {
+ let document = this.top.document;
+ if (toggle) {
+ let tabs = [];
+ for (let c of visibleClasses) {
+
+ Array.forEach(document.getElementsByClassName(c), function(t) {
+ let co = new ClassyObj(t);
+ t.className = hiddenClass;
+ tabs.push(co);
+ });
+ }
+ this._abpTabs = tabs;
+ } else {
+ for (let co of this._abpTabs) {
+ co.reset();
+ }
+ }
+ } catch(e) {
+ Cu.reportError(e);
+ }
+ }
+ : DUMMY_FUNC;
+ this.abpTabsHack(toggle);
+ }
+};
+
+
+["clearClick", "clearClick.exceptions", "clearClick.subexceptions"].forEach(function(p) {
+ try {
+ ns.syncPrefs(ns.prefs, p);
+ } catch(e) {
+ ns.dump(e.message + ":" + e.stack + " setting " + p + "\n");
+ }
+});
diff --git a/extensions/noscript/chrome/content/noscript/Cookie.js b/extensions/noscript/chrome/content/noscript/Cookie.js
new file mode 100644
index 0000000..db23ab5
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Cookie.js
@@ -0,0 +1,148 @@
+function Cookie(s, host) {
+ this.parse(s, host);
+}
+Cookie.computeId = function(c) {
+ return c.name + ";" + c.host + "/" + c.path;
+};
+Cookie.find = function(f) {
+ var cc = Cookie.prototype.cookieManager.enumerator;
+ var c;
+ while (cc.hasMoreElements()) {
+ if (f(c = cc.getNext())) return c;
+ }
+ return null;
+};
+
+Cookie.attributes = { host: 'domain', path: 'path', expires: 'expires', isHttpOnly: 'HttpOnly', isSecure: 'Secure' };
+Cookie.prototype = {
+
+ name: '',
+ value: '',
+ source: '',
+ domain: '',
+ host: '',
+ rawHost: '',
+ path: '',
+ secure: false,
+ httponly: false,
+ session: true,
+ expires: 0,
+
+ id: '',
+
+
+ toString: function() {
+ var c = [this['name'] + "=" + this.value];
+ var v;
+ const aa = Cookie.attributes;
+ for (var k in aa) {
+ var p = aa[k];
+ v = this[k];
+ switch(typeof(v)) {
+ case "string":
+ if (v) c.push(p + "=" + v);
+ break;
+ case "boolean":
+ if (v) c.push(p);
+ break;
+ case "number":
+ if (!this.isSession) c.push(p + "=" + new Date(v * 1000).toUTCString());
+ break;
+ }
+ }
+ return c.join("; ");
+ },
+ parse: function(s, host) {
+ var p;
+ if (this.source) {
+ // cleanup for recycle
+ for (p in this) {
+ if (typeof (p) != "function") delete this[p];
+ }
+ }
+ this.source = s;
+ this.host = host;
+
+ var parts = s.split(/;\s*/);
+ var nv = parts.shift().split("=");
+
+ this.name = nv.shift() || '';
+ this.value = nv.join('=') || '';
+
+ var n, v;
+ for (p of parts) {
+ nv = p.split("=");
+ switch (n = nv[0].toLowerCase()) {
+ case 'expires':
+ v = Math.round(Date.parse((nv[1] || '').replace(/\-/g, ' ')) / 1000);
+ break;
+ case 'domain':
+ case 'path':
+ v = nv[1] || '';
+ break;
+ case 'secure':
+ case 'httponly':
+ v = true;
+ break;
+ default:
+ n = 'unknown'
+ }
+ this[n] = v;
+ }
+ if (!this.expires) {
+ this.session = true;
+ this.expires = Math.round(new Date() / 1000) + 31536000;
+ }
+ if (this.domain) {
+ if (!this.isDomain) this.domain = "." + this.domain;
+ this.host = this.domain;
+ }
+ this.rawHost = this.host.replace(/^\./, '');
+
+ this.id = Cookie.computeId(this);
+ },
+
+
+ get cookieManager() {
+ delete Cookie.prototype.cookieManager;
+ var cman = Cc["@mozilla.org/cookiemanager;1"]
+ .getService(Ci.nsICookieManager2).QueryInterface(Ci.nsICookieManager);
+ return Cookie.prototype.cookieManager = cman;
+ },
+ belongsTo: function(host, path) {
+ if (path && this.path && path.indexOf(this.path) != 0) return false;
+ if (host == this.rawHost) return true;
+ var d = this.domain;
+ return d && (host == d || this.isDomain && host.slice(-d.length) == d);
+ },
+ save: function() {
+ this.save = ("cookieExists" in this.cookieManager)
+ ? function() { this.cookieManager.add(this.host, this.path, this.name, this.value, this.secure, this.httponly, this.session, this.expires); }
+ : function() { this.cookieManager.add(this.host, this.path, this.name, this.value, this.secure, this.session, this.expires);}
+ ;
+ return this.save();
+ },
+ exists: function() {
+ var cc = this.cookieManager.enumerator;
+ while(cc.hasMoreElements()) {
+ if (this.sameAs(cc.getNext())) return true;
+ }
+ return false;
+ },
+
+ sameAs: function(c) {
+ (c instanceof Ci.nsICookie) && (c instanceof Ci.nsICookie2);
+ return Cookie.computeId(c) == this.id;
+ },
+
+ // nsICookie2 interface extras
+ get isSecure() { return this.secure; },
+ get expiry() { return this.expires; },
+ get isSession() { return this.session; },
+ get isHttpOnly() { return this.httponly; },
+ get isDomain() { return this.domain && this.domain[0] == '.'; },
+ policy: 0,
+ status: 0,
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsICookie, Ci.nsICookie2])
+
+} \ No newline at end of file
diff --git a/extensions/noscript/chrome/content/noscript/DNS.js b/extensions/noscript/chrome/content/noscript/DNS.js
new file mode 100644
index 0000000..80e9920
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/DNS.js
@@ -0,0 +1,374 @@
+function DNSRecord(record) {
+ this.ts = Date.now();
+ var ttl;
+ if (record) {
+ try {
+ this.canonicalName = record.canonicalName;
+ } catch(e) {}
+ this.entries = [];
+
+ try {
+ for (;;) this.entries.push(record.getNextAddrAsString());
+ } catch(e) {
+ // NS_ERROR_NOT_AVAILABLE, no more records
+ // notice that hasMore() internall just calls getNextAttr(), checks for errors and resets the iterator
+ }
+ ttl = this.TTL;
+ if (!this.entries.length) this.valid = false;
+ } else {
+ this.valid = false;
+ }
+ if (!this.valid) ttl = this.INVALID_TTL_ASYNC;
+ this.expireTime = this.ts + ttl;
+}
+
+DNSRecord.prototype = {
+ INVALID_TTL_ASYNC: 3000,
+ INVALID_TTL_SYNC: 8000,
+ TTL: 60000,
+ valid: true,
+ ts: 0,
+ entries: [],
+ canonicalName: '',
+ expireTime: 0,
+ refreshing: false,
+ localExtras: null, // AddressMatcher object which can be added to the LOCAL resolution
+
+
+ isLocal: function(all) {
+ return all
+ ? "everyLocal" in this
+ ? this.everyLocal
+ : this.everyLocal = this.entries.every(DNS.isLocalIP, DNS)
+ : "someLocal" in this
+ ? this.someLocal
+ : this.someLocal = this.entries.some(DNS.isLocalIP, DNS)
+ ;
+ },
+ get expired() {
+ return Date.now() > this.expireTime;
+ }
+
+}
+
+
+var DNS = {
+
+ get logFile() {
+ delete this.logFile;
+ var logFile = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
+ logFile.append("noscript_dns.log");
+ return this.logFile = logFile;
+ },
+ logEnabled: false,
+ log: function(msg) {
+ try {
+ if (!this.logStream) {
+ const logFile = this.logFile;
+ const logStream = Cc["@mozilla.org/network/file-output-stream;1"]
+ .createInstance(Ci.nsIFileOutputStream);
+ logStream.init(logFile, 0x02 | 0x08 | 0x10, 384 /*0600*/, 0 );
+ this.logStream = logStream;
+ const header="*** Log start at "+new Date().toGMTString()+"\n";
+ this.logStream.write(header,header.length);
+ }
+
+ if (msg!=null) {
+ msg += "\n";
+ this.logStream.write(msg,msg.length);
+ }
+ this.logStream.flush();
+ } catch(ex) {
+ dump(ex.message+"\noccurred logging this message:\n"+msg);
+ }
+ },
+
+ get _dns() {
+ delete this._dns;
+ return this._dns = Cc["@mozilla.org/network/dns-service;1"]
+ .getService(Ci.nsIDNSService);
+ },
+
+ _cache: {
+ CAPACITY: 400, // when we purge, we cut this to half
+ _map: {__proto__: null},
+ _ext: {__proto__: null},
+ count: 0,
+
+
+ get: function(key) {
+ return key in this._map && this._map[key];
+ },
+ put: function(key, entry) {
+ if (!(key in this._map)) {
+ if (this.count >= this.CAPACITY) {
+ this.purge();
+ }
+ }
+ this._map[key] = entry;
+ this.count++;
+ },
+ evict: function(host) {
+ return (host in this._map) && (delete this._map[host]);
+ },
+
+ purge: function() {
+ var max = this.CAPACITY / 2;
+ if (this.count < max) return;
+ var l = [];
+ var map = this._map;
+ for (var key in map) {
+ l.push({ k: key, t: map[key].ts});
+ }
+ this._doPurge(map, l, max);
+ },
+
+ reset: function() {
+ this._map = {__proto__: null};
+ this._ext = {__proto__: null},
+ this.count = 0;
+ },
+
+ _oldLast: function(a, b) {
+ return a.t > b.t ? -1 : a.t < b.t ? 1 : 0;
+ },
+
+ putExt: function(host) {
+ this._ext[host] = true;
+ },
+ isExt: function(host) {
+ return host in this._ext;
+ },
+
+
+ _doPurge: function(map, l, max) {
+ l.sort(this._oldLast);
+ for (var j = l.length; j-- > max;) {
+ delete map[l[j].k];
+ }
+ this.count -= (l.length - max);
+ }
+ },
+
+ get idn() {
+ delete this.idn;
+ return this.idn = Cc["@mozilla.org/network/idn-service;1"]
+ .getService(Ci.nsIIDNService);
+ },
+
+ _invalidRx: /[^\w\-\.]/,
+ checkHostName: function(host) {
+ if (this._invalidRx.test(host) && !this.isIP(host)) {
+ try {
+ host = this.idn.convertUTF8toACE(host);
+ } catch(e) {
+ return false;
+ }
+ return !this._invalidRx.test(host);
+ }
+ return true;
+ },
+
+ _resolving: {},
+ resolve: function(host, flags, callback) {
+ flags = flags || 0;
+
+ var elapsed = 0, t;
+ var cache = this._cache;
+ var async = IOUtil.asyncNetworking || !!callback;
+
+ var dnsRecord = cache.get(host);
+ if (dnsRecord) {
+ // cache invalidation, if needed
+ if (dnsRecord.expired && !dnsRecord.refreshing) {
+ if (dnsRecord.valid && !(flags & 1)) {
+ // refresh async
+ dnsRecord.refreshing = true;
+ DNS._dns.asyncResolve(host, flags, new DNSListener(function() {
+ if (DNS.logEnabled) DNS.log("Async " + host);
+ cache.put(host, dnsRecord = new DNSRecord(this.record));
+ }), Thread.currentQueue);
+ } else {
+ flags |= 1;
+ }
+ if (flags & 1) {
+ dnsRecord = null;
+ cache.evict(host);
+ }
+ }
+ }
+ if (dnsRecord) {
+ if (ABE.consoleDump) ABE.log("Using cached DNS record for " + host);
+ } else if (this.checkHostName(host)) {
+
+ if (async) {
+ var resolving = this._resolving;
+
+ if (host in resolving) {
+ ABE.log("Already resolving " + host);
+
+ if (callback) {
+ resolving[host].push(callback);
+ return null;
+ }
+ } else resolving[host] = callback ? [callback] : [];
+
+ var ctrl = {
+ running: true,
+ startTime: Date.now()
+ };
+
+ var status = Cr.NS_OK;
+
+
+ var resolve = function() {
+ DNS._dns.asyncResolve(host, flags, new DNSListener(function() {
+ if (DNS.logEnabled) DNS.log("Async " + host);
+ cache.put(host, dnsRecord = new DNSRecord(this.record));
+ ctrl.running = false;
+ var callbacks = resolving[host];
+ delete resolving[host];
+ if (ABE.consoleDump && t) {
+ elapsed = Date.now() - t;
+ ABE.log("Async DNS query on " + host + " done, " + elapsed + "ms, callbacks: " + (callbacks && callbacks.length));
+ }
+
+ if (callbacks && callbacks.length)
+ for (var cb of callbacks)
+ cb(dnsRecord);
+
+ }), Thread.currentQueue);
+ if (ABE.consoleDump) ABE.log("Waiting for DNS query on " + host);
+ if (!callback) Thread.spin(ctrl);
+ }
+
+ if (callback) {
+ t = Date.now();
+ resolve();
+ return null;
+ }
+
+ resolve();
+
+ if (!Components.isSuccessCode(status)) throw status;
+
+ elapsed = ctrl.elapsed || 0;
+ } else {
+ t = Date.now();
+ if (ABE.consoleDump) ABE.log("Performing DNS query on " + host);
+ if (DNS.logEnabled) DNS.log("Sync " + host);
+ cache.put(host, dnsRecord = new DNSRecord(this._dns.resolve(host, flags)));
+ elapsed = Date.now() - t;
+ }
+ } else {
+ this._cache.put(host, dnsRecord = new DNSRecord(null)); // invalid host name
+ }
+
+ if (ABE.consoleDump) ABE.log("DNS query on " + host + " done, " + elapsed + "ms");
+
+ if (callback) {
+ callback(dnsRecord);
+ } else {
+ if (!(dnsRecord && dnsRecord.valid)) throw Cr.NS_ERROR_UNKNOWN_HOST;
+ }
+ return dnsRecord;
+ },
+
+
+
+ evict: function(host) {
+ ABE.log("Removing DNS cache record for " + host);
+ return this._cache.evict(host);
+ },
+
+ invalidate: function(host) {
+ var dnsRecord = this._cache.get(host);
+ if (!dnsRecord.valid) return false;
+ dnsRecord.valid = false;
+ dnsRecord.expireTime = 0;
+ return true;
+ },
+
+ getCached: function(host) {
+ return this._cache.get(host);
+ },
+
+ isCached: function(host) {
+ var res = this._cache.get(host);
+ return res && (res.valid || !res.expired);
+ },
+
+ isLocalURI: function(uri, all) {
+ var host;
+ try {
+ host = uri.host;
+ } catch(e) {
+ return false;
+ }
+ if (!host) return true; // local file:///
+ return this.isLocalHost(host, all);
+ },
+
+ _localDomainRx: /\.local$/i,
+ isLocalHost: function(host, all, dontResolve) {
+ if (host === "localhost" || this._localDomainRx.test(host)) return true;
+ if (this.isIP(host)) {
+ return this.isLocalIP(host);
+ }
+
+ if (all && this._cache.isExt(host) || dontResolve) return false;
+
+ var res = this.resolve(host, 0).isLocal(all);
+
+ if (!res) {
+ this._cache.putExt(host);
+ }
+
+ return res;
+ },
+
+ _localIP6Rx: /^(?:::1?$|f(?:[cd]|e[c-f])[0-9a-f]*:)/i,
+ get _localIPMatcher() {
+ delete this._localIPMatcher;
+ return this._localIPMatcher = new AddressMatcher('0. 127. 10. 169.254.0.0/16 172.16.0.0/12 192.168.0.0/16 255.255.255.255');
+ },
+ isLocalIP: function(addr) {
+ // see https://bug354493.bugzilla.mozilla.org/attachment.cgi?id=329492 for a more verbose but incomplete (missing IPv6 ULA) implementation
+ // Relevant RFCs linked at http://en.wikipedia.org/wiki/Private_network
+ // Note: we omit link-local IPv6 addresses (fe80:/10) on purpose, because they're currently found in the wild as misconfigured
+ // AAAA DNS records. The safest work-around is considering them external to the LAN always.
+
+ return this._localIP6Rx.test(addr) ||
+ this._localIPMatcher.testIP(addr = this.ip6to4(addr)) ||
+ this.localExtras && this.localExtras.testIP(addr) ||
+ WAN.ipMatcher && WAN.ipMatcher.testIP(addr);
+ },
+ _ip6to4Rx: /^2002:([A-F0-9]{2})([A-F0-9]{2}):([A-F0-9]{2})([A-F0-9]{2})|:(?:\d+\.){3}\d+$/i,
+ ip6to4: function(addr) {
+ let m = addr.match(this._ip6to4Rx);
+ return m ? (m[1]
+ ? m.slice(1).map((h) => parseInt(h, 16)).join(".")
+ : m[0].substring(1)
+ )
+ : addr;
+ },
+ _ipRx: /^(?:0\.|[1-9]\d{0,2}\.){3}(?:0|[1-9]\d{0,2})$|:.*:/i, // very restrictive, rejects IPv4 hex, octal and int32
+ _ipRx_permissive: /^(?:(?:\d+|0x[a-f0-9]+)\.){0,3}(?:\d+|0x[a-f0-9]+)$|:.*:/i,
+ isIP: function(host) { return this._ipRx.test(host); }
+};
+
+function DNSListener(callback) {
+ if (callback) this.callback = callback;
+};
+DNSListener.prototype = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSListener]),
+ record: null,
+ status: 0,
+ callback: null,
+ onLookupComplete: function(req, rec, status) {
+ this.record = rec;
+ this.status = status;
+ if (this.callback) this.callback();
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/DOM.js b/extensions/noscript/chrome/content/noscript/DOM.js
new file mode 100644
index 0000000..3c90aad
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/DOM.js
@@ -0,0 +1,245 @@
+var DOM = {
+
+ maxZIndex: "99999999",
+
+ confirm: function(s) { // for interactive debugging purposes
+ return this.mostRecentBrowserWindow.confirm(s);
+ },
+
+ findWindow: function(ctx) {
+ if (!(ctx instanceof Ci.nsIDOMWindow)) {
+ if (ctx instanceof Ci.nsIDOMDocument) {
+ ctx = ctx.defaultView;
+ } else if(ctx instanceof Ci.nsIDOMNode) {
+ ctx = ctx.ownerDocument.defaultView;
+ } else return null;
+ }
+ return ctx;
+ },
+
+ findBrowserForNode: function(ctx) {
+ try {
+ } catch (e) {
+ }
+ if (!ctx) return null;
+ var bi = null;
+ try {
+ ctx = this.findWindow(ctx);
+ if (!ctx) return null;
+ try {
+ ctx = Cu.lookupMethod(ctx, "top")();
+ } catch(e) {
+ ctx = ctx.top;
+ }
+ var bi = this.createBrowserIterator(this.getChromeWindow(ctx));
+
+ for (var b; b = bi.next();) {
+ try {
+ if (b.contentWindow == ctx) return b;
+ } catch(e) {}
+ }
+ } catch(e) {
+ } finally {
+ if (bi) bi.dispose();
+ ctx = null;
+ }
+
+ return null;
+ },
+
+ getDocShellForWindow: function(window) {
+ try {
+ return window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ } catch(e) {
+ return null;
+ }
+ },
+
+ getFrameMM(windowOrNode) {
+ if (windowOrNode.ownerDocument) windowOrNode = windowOrNode.ownerDocument;
+ if (windowOrNode.defaultView) windowOrNode = windowOrNode.defaultView;
+ return windowOrNode.top.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDocShell)
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIContentFrameMessageManager);
+ },
+
+ getChromeWindow: function(window) {
+ try {
+ return this.getDocShellForWindow(window.top)
+ .QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindow).window;
+ } catch(e) {
+ return null;
+ }
+ },
+
+ get windowMediator() {
+ delete this.windowMediator;
+ return this.windowMediator = Cc['@mozilla.org/appshell/window-mediator;1']
+ .getService(Ci.nsIWindowMediator);
+ },
+
+ get browserWinURI() {
+ let uri = this.browserWinChromeURI;
+ if (!uri) return null;
+ delete this.browserWinURI;
+ return this.browserWinURI = uri.schemeIs("chrome")
+ ? Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry).convertChromeURL(uri)
+ : uri;
+ },
+ get browserWinChromeURI() {
+ let w = this.mostRecentBrowserWindow;
+ if (!w) return null;
+ delete this.browserWinChromeURI;
+ return this.browserWinChromeURI = w.document.documentURIObject;
+ },
+
+ browserWinType: 'navigator:browser',
+ perWinType: function(delegate) {
+ var wm = this.windowMediator;
+ var w = null;
+ var aa = Array.slice(arguments, 0);
+ for (var type of ['navigator:browser', 'emusic:window', 'Songbird:Main']) {
+ aa[0] = type;
+ w = delegate.apply(wm, aa);
+ if (w) {
+ this.browserWinType = type;
+ break;
+ }
+ }
+ return w;
+ },
+
+ get mostRecentBrowserWindow() {
+ return this.windowMediator.getMostRecentWindow(this.browserWinType, true) ||
+ this.perWinType(this.windowMediator.getMostRecentWindow, true);
+ },
+ get windowEnumerator() {
+ return this.windowMediator.getZOrderDOMWindowEnumerator(this.browserWinType, true) ||
+ this.perWinType(this.windowMediator.getZOrderDOMWindowEnumerator, true);
+ },
+ createBrowserIterator: (initialWin) => new BrowserIterator(initialWin),
+
+ addClass: function(e, c) {
+ var cur = e.className;
+ if (cur) {
+ var cc = cur.split(/\s+/);
+ if (cc.indexOf(c) > -1) return;
+ cc.push(c);
+ e.className = cc.join(" ");
+ } else e.className += " " + c;
+ },
+ removeClass: function(e, c) {
+ var cur = e.className;
+ if (cur) {
+ var cc = cur.split(/\s+/);
+ for (var pos; (pos = cc.indexOf(c)) > -1;)
+ cc.splice(pos, 1);
+
+ e.className = cc.join(" ");
+ }
+ },
+ toggleClass: function(e, c, add) {
+ if (typeof add == "undefined")
+ add = !this.hasClass(e, c);
+ if (add) this.addClass(e, c);
+ else this.removeClass(e, c);
+ return add;
+ },
+ hasClass: function(e, c) {
+ var cur = e.className;
+ return cur && cur.split(/\s+/).indexOf(c) > -1;
+ },
+
+ _idCounter: Math.round(Math.random() * 9999),
+ rndId: function() {
+ return Date.now().toString(32) + "_" + (this._idCounter++).toString(32) + "_" + Math.round(Math.random() * 9999999).toString(32);
+ },
+
+ elementContainsPoint: function(el, p) {
+ var rect = el.getBoundingClientRect();
+ return p.x >= rect.left && p.x <= rect.right && p.y >= rect.top && p.y <= rect.bottom;
+ }
+};
+
+function BrowserIterator(initialWin) {
+ if (!initialWin) {
+ initialWin = DOM.mostRecentBrowserWindow;
+ }
+ this.currentWin = this.initialWin = initialWin;
+ this.initPerWin();
+}
+BrowserIterator.prototype = {
+
+ initPerWin: function() {
+ var w = this.currentWin;
+ var overlay;
+ if (w) {
+ if (w.wrappedJSObject) w = w.wrappedJSObject;
+ overlay = ("noscriptOverlay" in w) ? w.noscriptOverlay : null;
+ } else overlay = null;
+
+ if (overlay) {
+ this.browsers = overlay.browsers;
+ this.currentTab = overlay.currentBrowser;
+ } else {
+ this.currentTab = this.currentWin = null;
+ this.browsers = [];
+ }
+ this.mostRecentTab = this.currentTab;
+ this.curTabIdx = 0;
+ },
+
+ next: function() {
+ var ret = this.currentTab;
+ this.currentTab = null;
+ if (ret != null) return ret.wrappedJSObject || ret;
+ if(!this.initialWin) return null;
+ if (this.curTabIdx >= this.browsers.length) {
+ if (!this.winEnum) {
+ this.winEnum = DOM.windowEnumerator;
+ }
+ if (this.winEnum.hasMoreElements()) {
+ this.currentWin = this.winEnum.getNext();
+ if (this.currentWin != this.initialWin){
+ this.initPerWin();
+ }
+ return this.next();
+ } else {
+ this.dispose();
+ return null;
+ }
+ }
+ this.currentTab = this.browsers[this.curTabIdx++];
+ if (this.currentTab == this.mostRecentTab) this.next();
+ return this.next();
+ },
+ dispose: function() {
+ if (!this.initialWin) return; // already disposed;
+ this.initialWin =
+ this.currentWin =
+ this.browsers =
+ this.currentTab =
+ this.mostRecentTab =
+ this.winEnum =
+ null;
+ },
+
+ find: function(filter) {
+ try {
+ for (var b; b = this.next();) {
+ if (filter(b)) {
+ return b;
+ }
+ }
+ } finally {
+ this.dispose();
+ filter = null;
+ }
+ return null;
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/DoNotTrack.js b/extensions/noscript/chrome/content/noscript/DoNotTrack.js
new file mode 100644
index 0000000..e22f492
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/DoNotTrack.js
@@ -0,0 +1,59 @@
+var DoNotTrack = {
+ enabled: true,
+ exceptions: null,
+ forced: null,
+
+ init: function(prefs) {
+ this.prefs = prefs;
+ for (let k of prefs.getChildList("", {})) {
+ this.observe(prefs, null, k);
+ }
+ prefs.addObserver("", this, true);
+ },
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
+ observe: function(prefs, topic, name) {
+ switch(name) {
+ case "enabled":
+ this.enabled = prefs.getBoolPref(name);
+ break;
+ case "exceptions":
+ case "forced":
+ this[name] = AddressMatcher.create(COMPAT.getStringPref(prefs, name));
+ break;
+ }
+ },
+
+ apply: function(/* ABEReq */ req) {
+ let url = req.destination;
+
+ try {
+ if (
+ (this.exceptions && this.exceptions.test(url) ||
+ req.localDestination ||
+ req.isDoc && req.method === "POST" && req.originURI.host === req.destinationURI.host
+ ) &&
+ !(this.forced && this.forced.test(url))
+ // TODO: find a way to check whether this request is gonna be WWW-authenticated
+ )
+ return;
+
+ let channel = req.channel;
+ channel.setRequestHeader("DNT", "1", false);
+
+ // reorder headers to mirror Firefox 4's behavior
+ let conn = channel.getRequestHeader("Connection");
+ channel.setRequestHeader("Connection", "", false);
+ channel.setRequestHeader("Connection", conn, false);
+ } catch(e) {}
+ },
+
+ getDOMPatch: function(docShell) {
+ try {
+ if (docShell.document.defaultView.navigator.doNotTrack !== "1" &&
+ docShell.currentDocumentChannel.getRequestHeader("DNT") === "1") {
+ return 'Object.defineProperty(window.navigator, "doNotTrack", { configurable: true, enumerable: true, value: "1" });';
+ }
+ } catch (e) {}
+ return "";
+ },
+}
diff --git a/extensions/noscript/chrome/content/noscript/Entities.js b/extensions/noscript/chrome/content/noscript/Entities.js
new file mode 100644
index 0000000..ed00186
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Entities.js
@@ -0,0 +1,37 @@
+var Entities = {
+
+ get htmlNode() {
+ delete this.htmlNode;
+ var impl = Cc["@mozilla.org/xul/xul-document;1"].createInstance(Ci.nsIDOMDocument).implementation;
+ return this.htmlNode = (("createHTMLDocument" in impl)
+ ? impl.createHTMLDocument("")
+ : impl.createDocument(
+ HTML_NS, "html", impl.createDocumentType(
+ "html", "-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd"
+ ))
+ ).createElementNS(HTML_NS, "body");
+ },
+ convert: function(e) {
+ try {
+ this.htmlNode.innerHTML = e;
+ var child = this.htmlNode.firstChild || null;
+ return child && child.nodeValue || e;
+ } catch(ex) {
+ return e;
+ }
+ },
+ convertAll: function(s) {
+ return s.replace(/[\\&][^<>]+/g, function(e) { return Entities.convert(e) });
+ },
+ convertDeep: function(s) {
+ for (var prev = null; (s = this.convertAll(s)) !== prev || (s = unescape(s)) !== prev; prev = s);
+ return s;
+ },
+ neutralize: function(e, whitelist) {
+ var c = this.convert(e);
+ return (c == e) ? c : (whitelist && whitelist.test(c) ? e : e.replace(";", ","));
+ },
+ neutralizeAll: function(s, whitelist) {
+ return s.replace(/&[\w#-]*?;/g, function(e) { return Entities.neutralize(e, whitelist || null); });
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/ExternalFilters.js b/extensions/noscript/chrome/content/noscript/ExternalFilters.js
new file mode 100644
index 0000000..a20c317
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/ExternalFilters.js
@@ -0,0 +1,728 @@
+var ExternalFilters = {
+ prefs: null,
+ _filters: [],
+ enabled: false,
+ supported: true,
+ lastFilterName: null,
+
+ get _builtIns() {
+ delete this._builtIns;
+ return this._builtIns = [
+ new ExternalFilter("Blitzableiter", null, "shockwave|futuresplash", ".hulu.com .youtube.com")
+ ];
+ },
+
+ isBuiltIn: function (f) {
+ return this._builtIns.some(f.same, f);
+ },
+
+ cloneFilters: function() {
+ return this._filters.concat(
+ this._builtIns.filter((bif) => !this._filters.some(bif.same, bif), this )
+ ).map((f) => new ExternalFilter(f.name, f.exe, f.contentType, f.whitelist)
+ );
+ },
+
+ save: function(filters) {
+ if (filters) this._filters = filters;
+
+ const prefs = this.prefs;
+ for (let key of prefs.getChildList("", {})) {
+ try {
+ prefs.clearUserPref(key);
+ } catch(e) {}
+ }
+ prefs.setBoolPref("enabled", this.enabled);
+
+ const props = ["name", "exe", "contentType", "whitelist"];
+
+ this._filters.forEach(function(f) {
+ for (let p of props) {
+ prefs.setCharPref(f.name + "." + p,
+ p == "exe" ? f[p] && f[p].path || '' :
+ p == "whitelist" ? f[p] && f[p].source || '' :
+ f[p]
+ );
+ }
+ });
+ },
+
+ get whitelists() {
+ if (!("_whitelists" in this)) {
+ let wl = {}, some = false;
+ if (this._filters.length) {
+ for (let f of this._filters) {
+ if (f.whitelist) wl[f.name] = f.whitelist;
+ some = true;
+ }
+ }
+ this._whitelists = some ? wl : null;
+ }
+ return this._whitelists;
+ },
+
+ register: function(f) {
+ if (f.valid) {
+ const ff = this._filters;
+ for (let j = ff.length; j-- > 0;) {
+ if (f.same(ff[j])) ff.splice(j, 1);
+ }
+ this._filters.push(f);
+ delete this._whitelists;
+ return true;
+ }
+ return false;
+ },
+
+ get ioUtil() {
+ delete this.ioUtil;
+ return this.ioUtil = Cc["@mozilla.org/io-util;1"].getService(Ci.nsIIOUtil);
+ },
+
+ get tmpDir() {
+ delete this.tmpDir;
+ return this.tmpDir = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIProperties)
+ .get("TmpD", Ci.nsILocalFile);
+ },
+
+
+ createProcess: function() {
+ const clazz = Cc["@mozilla.org/process/util;1"];
+ const iface = "nsIProcess2" in Ci ? Ci.nsIProcess2 : Ci.nsIProcess;
+ delete this.createProcess;
+ this.createProcess = () => clazz.createInstance(iface);
+ return this.createProcess();
+ },
+
+ createTempFile: function() {
+ let tf = this.tmpDir.clone();
+ tf.append(Math.round(Math.random() * 99999999).toString(16));
+ tf.createUnique(tf.FILE_TYPE, 384);
+ return tf;
+ },
+
+ handle: function(channel, extraType, ctx, cached) {
+ if (channel instanceof Ci.nsITraceableChannel) {
+
+ let contentType;
+ try {
+ contentType = channel.contentType;
+ } catch(e) {
+ contentType = extraType || '';
+ }
+
+ if (contentType || extraType) {
+ contentType = extraType || contentType;
+ for (let f of this._filters) {
+ if (f.handle(channel, contentType, ctx, cached)) {
+ this.storeFilterInfo(ctx, f, channel.name);
+ return f;
+ }
+ }
+ }
+ }
+
+ return null;
+ },
+
+ getFiltersInfo: function(top) {
+ return top.__externalContentFilters__ || (top.__externalContentFilters__ = {});
+ },
+
+ getObjFilterInfo: function(obj) {
+ return obj.__externalContentFilter__ || null;
+ },
+
+ storeFilterInfo: function(ctx, filter, url) {
+ ctx.__externalContentFilter__ = { url: url, filter: filter };
+
+ var info = this.getFiltersInfo(ctx.ownerDocument.defaultView.top);
+ info[url] = filter;
+ return info;
+ },
+
+ byName: function(name) {
+ for (var j = this._filters.length; j-- > 0;) {
+ if (this._filters[j].name == name) return this._filters[j];
+ }
+ return null;
+ },
+
+
+ log: function(msg) {
+ dump("[External Filters] " + msg + "\n");
+ },
+
+ initFromPrefs: function(prefRoot) {
+ this.prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService)
+ .getBranch(prefRoot).QueryInterface(Ci.nsIPrefBranch);
+ this._syncPrefs();
+
+ },
+
+ _observingPrefs: false,
+ _syncPrefs: function() {
+ const prefs = this.prefs;
+ if ((this.enabled = prefs.getBoolPref("enabled"))) {
+ this._filters = [];
+ var args,
+ name, member
+ map = {};
+ for (let key of prefs.getChildList("", {})) {
+ [name, member] = key.split(".");
+ if (!(name && member)) continue;
+
+ if (!(name in map)) map[name] = { name: name };
+ try {
+ map[name][member] = prefs.getCharPref(key);
+ } catch(e) {}
+ }
+ for (name in map) {
+ this._createAndRegister(map[name]);
+ }
+ }
+ if (!this._observingPrefs) {
+ prefs.addObserver("", this, true);
+ this._observingPrefs = true;
+ }
+ EFCacheSessions.purge();
+ },
+
+ _createAndRegister: function(args) {
+ var f = args
+ ? new ExternalFilter(args.name, args.exe, args.contentType || '', "whitelist" in args && args.whitelist)
+ : null;
+ if (f && f.name) this.register(f);
+ return f;
+ },
+
+ create: function(name, exe, contentType, whitelist) {
+ return new ExternalFilter(name, exe, contentType, whitelist);
+ },
+
+ observe: function(prefs, topic, key) {
+ this.prefs.removeObserver("", this, true);
+ this._observingPrefs = false;
+ Thread.asap(this._syncPrefs, this);
+ },
+
+ testSetup: function() {
+ if (!this._filters.length)
+ new ExternalFilter("Blitzableiter",
+ "G:\\Install\\Blitzableiter.rev125.binary\\Blitzableiter.exe",
+ "shockwave|futuresplash"
+ );
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference])
+}
+
+
+function ExternalFilter(name, exe, contentType, whitelist) {
+ name = name.replace(/^\W+/, '').replace(/\s+$/, '');
+ if (!name) return this;
+ this.name = name[0].toUpperCase() + name.substring(1);
+ try {
+
+
+ this.contentType = contentType;
+
+ if (whitelist)
+ this.whitelist = new AddressMatcher(
+ (whitelist instanceof AddressMatcher)
+ ? whitelist.source
+ : whitelist
+ );
+
+ if (exe instanceof Ci.nsIFile) {
+ this.exe = exe;
+ } else if (exe) {
+ this.exe = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+ this.exe.initWithPath(exe);
+ }
+
+ if (this.exe && !this.exe.exists())
+ this.exe = null;
+
+ } catch(e) {
+ ExternalFilters.log(name + ": " + e);
+ }
+ return this;
+}
+
+ExternalFilter.prototype = {
+ name: '',
+ whitelist: null,
+ exe: null,
+ get valid() {
+ return !!this.exe;
+ },
+ get enabled() {
+ return this.valid && !!this.contentType;
+ },
+
+ get builtIn() {
+ return ExternalFilters.isBuiltIn(this);
+ },
+
+ same: function(f) {
+ return f.name == this.name;
+ },
+
+ _ct: '',
+ _ctRx: /^$/,
+ set contentType(s) {
+ s = s || '';
+ this._ct = s;
+ delete this._ctRx;
+ if (s) {
+ var rx = this.parseContentType(s);
+ if (rx) this._ctRx = rx;
+ }
+ return s;
+ },
+
+ get contentType() {
+ return this._ct;
+ },
+
+ parseContentType: function(s) {
+ try {
+ return new RegExp(
+ /[\^\$\*\(\[\]\)\|\?]/.test(s)
+ ? s
+ : '^' + s.replace(/[^\w\/;]/g, "\\$1") + '$',
+ "i"
+ );
+ } catch(e) {
+ return null;
+ }
+ },
+
+ isDomainException: function(d) {
+ return this.whitelist && this.whitelist.source.split(/\s+/).indexOf("." + d) !== -1
+ },
+
+ addDomainException: function(d) {
+ if (this.isDomainException(d)) return false;
+ var wl = this.whitelist && this.whitelist.source || '';
+ ExternalFilters.prefs.setCharPref(this.name + ".whitelist", wl.split(/\s+/).concat("." + d).join(" "));
+ return true;
+ },
+
+ removeDomainException: function(d) {
+ var wl = this.whitelist;
+ if (!wl) return false;
+ var list = wl.source.split(/\s+/);
+ var fqd = "." + d;
+ var pos = list.indexOf(fqd);
+ if (pos < 0) return false;
+ do {
+ list.splice(pos, 1);
+ } while((pos = list.indexOf(fqd)) !== -1);
+ ExternalFilters.prefs.setCharPref(this.name + ".whitelist", list.join(" "));
+ return true;
+ },
+
+ handle: function(traceableChannel, contentType, ctx, cached) {
+ if (!(this.enabled && this._ctRx.test(contentType)))
+ return false;
+
+ if (!(this.whitelist && this.whitelist.test(traceableChannel.name))) {
+ try {
+ if (cached && traceableChannel instanceof Ci.nsICachingChannel &&
+ traceableChannel.cacheToken instanceof Ci.nsICacheEntryDescriptor &&
+ EFCacheSessions.isFiltered(traceableChannel.cacheToken, this.name)) {
+ return true;
+ }
+ } catch(e) {
+ // cache miss
+ }
+
+ new EFHandler(this, traceableChannel, ctx);
+ }
+ return true;
+ }
+}
+
+
+
+function EFHandler(filter, traceableChannel, object) {
+ this.filter = filter;
+ this.channel = traceableChannel;
+ this.object = object;
+ this.originalListener = traceableChannel.setNewListener(this);
+}
+
+EFHandler.prototype = {
+ _observers: [],
+
+ outFile: null,
+ cleanFile: null,
+ outStream: null,
+ bufSize: 0x8000,
+ ctx: null,
+ statusCode: 0,
+
+ processed: false,
+
+ caching: false,
+ cacheEntry: null,
+ offlineCacheEntry: null,
+
+
+
+ process: function() {
+ this.originalListener.onStartRequest(this.channel, this.ctx);
+ try {
+ this.outStream.flush();
+ this.outStream.close();
+
+ this.overwriteCache(this.loadAndCache);
+
+ ExternalFilters.log("Running " + this.filter.exe.path + " on " + this.channel.name);
+
+ this.cleanFile = ExternalFilters.createTempFile();
+ var p = ExternalFilters.createProcess();
+ p.init(this.filter.exe);
+ var origin = '';
+ try {
+ origin = this.object.ownerDocument.defaultView.location.href;
+ } catch(e) {
+ }
+ var args = [this.outFile.path, this.cleanFile.path, origin, this.channel.name];
+ p.runAsync(args, args.length, this, true);
+ this._observers.push(this); // anti-gc kung-fu death grip
+
+ } catch(e) {
+ this.abort(e);
+ }
+ },
+
+ abort: function(e) {
+ ExternalFilters.log("Aborting " + this.channel.name + ": " + e);
+ this.channel.cancel(Cr.NS_ERROR_ABORT);
+ this.overwriteCache(null);
+ this.cleanup();
+ },
+
+ onCacheWrite: null,
+
+ nukeCache: function(ce) {
+ ce.openOutputStream(0).close();
+ ce.markValid();
+ },
+
+ loadAndCache: function() {
+ if (this.processed &&
+ (!this.caching ||
+ this.cacheEntry &&
+ (this.offlineCacheEntry ||
+ !this.channel.cacheForOfflineUse))
+ ) {
+ new EFFilePassthru(this);
+ }
+ },
+
+ overwriteCache: function(writerCallback) {
+ var ch = this.channel;
+ if (!(ch instanceof Ci.nsICachingChannel)) return false;
+
+ this.onCacheWrite = writerCallback || this.nukeCache;
+
+ try {
+
+ let ce = ch.cacheToken;
+ if (!(ce instanceof Ci.nsICacheEntryDescriptor && ce.isStreamBased()))
+ return false;
+
+ try {
+ if (ch.isFromCache()) return false;
+ } catch(e) {
+ ExternalFilters.log("[" + ch.name + "].isFromCache() " + e);
+ }
+
+ this.caching = true;
+
+ new EFCacheHandler(this, ce, ce.clientID, ce.storagePolicy);
+
+ if (ch.cacheForOfflineUse) {
+ new EFCacheHandler(this, ce, ch.offlineCacheClientID);
+ }
+
+ return true;
+ } catch(e) {
+ ExternalFilters.log(e);
+ }
+ return false;
+ },
+
+ forCache: function(callback) {
+ if (this.cacheEntry) callback(this.cacheEntry);
+ if (this.offlineCacheEntry) callback(this.offlineCacheEntry);
+ },
+
+ _finalizeCacheEntry: function(ce) {
+ try {
+ var h = ce.getMetaDataElement("response-head");
+ ce.setMetaDataElement("response-head",
+ h.replace(/^(Content-Length:\s*)\d+/mi, "$1" + ce.dataSize));
+ } catch(e) {
+ ExternalFilters.log(e);
+ }
+ ce.markValid();
+ ce.close();
+ },
+
+ cleanup: function() {
+ if (this.outFile) {
+ this.outFile.remove(false);
+ delete this.outFile;
+ }
+ if (this.cleanFile) {
+ this.cleanFile.remove(false);
+ delete this.cleanFile;
+ }
+
+ this.forCache(this._finalizeCacheEntry);
+
+ delete this.cacheEntry;
+ delete this.offlineCacheEntry;
+ },
+
+ onStartRequest: function(request, ctx) {
+ var outFile = ExternalFilters.createTempFile();
+ var os = Cc["@mozilla.org/network/file-output-stream;1"]
+ .createInstance(Ci.nsIFileOutputStream);
+ os.init(outFile, 0x02 | 0x08 | 0x22 /* write, create, truncate */, 384 /*0600*/, 0);
+ var bos = Cc["@mozilla.org/network/buffered-output-stream;1"]
+ .createInstance(Ci.nsIBufferedOutputStream);
+ bos.init(os, this.bufSize);
+ this.outStream = bos;
+ this.outFile = outFile;
+ },
+
+ onDataAvailable: function(request, ctx, inStream, offset, count) {
+ var outStream = this.outStream;
+ while(count > 0)
+ count -= outStream.writeFrom(inStream, count);
+ },
+
+ onStopRequest: function(request, ctx, statusCode) {
+ this.ctx = ctx;
+ this.statusCode = statusCode;
+ this.process();
+ },
+
+ observe: function(subject, topic, data) {
+
+ this._observers.splice(this._observers.lastIndexOf(this), 1);
+ var p = subject;
+ if (p instanceof Ci.nsIProcess) {
+ this.processed = true;
+ switch(topic) {
+ case "process-finished":
+ if (!p.exitValue) {
+ this.loadAndCache();
+ break;
+ }
+ case "process-failed":
+ // TODO: better error management and nuke cache entry
+ this.abort("error #" + p.exitValue);
+ break;
+ }
+ }
+ },
+
+ QueryInterface: XPCOMUtils.generateQI(
+ [Ci.nsITraceableChannel, Ci.nsICacheListener,
+ Ci.nsIObserver, Ci.nsISupportsWeakReference])
+}
+
+function EFFilePassthru(handler) {
+ this.handler = handler;
+ this.request = handler.channel;
+ this.originalListener = handler.originalListener;
+
+ for (let ce of [handler.cacheEntry, handler.offlineCacheEntry]) {
+ if (ce) {
+ let tee = Cc["@mozilla.org/network/stream-listener-tee;1"].
+ createInstance(Ci.nsIStreamListenerTee);
+ tee.init(this.originalListener, ce.openOutputStream(0));
+ this.originalListener = tee;
+ }
+ }
+
+ // TODO: rewrite http://mxr.mozilla.org/mozilla-central/source/netwerk/cache/public/nsICacheEntryDescriptor.idl#86
+ this.bytes = 0;
+ var ch = IOUtil.newChannelFromURI(IOS.newFileURI(handler.cleanFile));
+ ch.asyncOpen(this, handler.ctx);
+}
+
+EFFilePassthru.prototype = {
+ onStartRequest: function(ch, ctx) {},
+
+ onDataAvailable: function(ch, ctx, inStream, offset, count) {
+ this.originalListener.onDataAvailable(this.request, ctx, inStream, offset, count);
+ },
+
+
+ onStopRequest: function(ch, ctx, statusCode) {
+ ExternalFilters.log(this.request.name + " succesfully filtered");
+
+ var handler = this.handler;
+ this.originalListener.onStopRequest(this.request, ctx, handler.statusCode);
+ handler.cleanup();
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener])
+}
+
+
+function EFCacheHandler(handler, ce, clientID, storagePolicy) {
+ this.handler = handler;
+ this.expirationTime = ce.expirationTime;
+ this.securityInfo = ce.securityInfo;
+ this.metaData = {};
+ ce.visitMetaData(this);
+
+ if (typeof(storagePolicy) == "undefined")
+ storagePolicy = EFCacheSessions.OFFLINE_POLICY;
+
+ EFCacheSessions.getSession(clientID, storagePolicy)
+ .asyncOpenCacheEntry(ce.key, EFCacheSessions.WRITE_ACCESS, this);
+}
+
+EFCacheHandler.prototype = {
+
+
+ visitMetaDataElement: function(key, value) {
+ this.metaData[key] = value;
+ return true;
+ },
+
+ onCacheEntryAvailable: function(ce, accessGranted, status) {
+ var handler = this.handler;
+
+ if (Components.isSuccessCode(status) && handler.onCacheWrite) {
+
+ ce.setExpirationTime(this.expirationTime);
+
+ if (this.securityInfo) ce.securityInfo = this.securityInfo;
+
+ let md = this.metaData;
+ for (let key in md) {
+ ce.setMetaDataElement(key, md[key]);
+ }
+
+ if (ce.storagePolicy == EFCacheSessions.OFFLINE_POLICY) {
+ handler.offlineCacheEntry = ce;
+ } else {
+ handler.cacheEntry = ce;
+ }
+
+ EFCacheSessions.setFiltered(ce, handler.filter.name);
+
+ handler.onCacheWrite(ce);
+ }
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsICacheListener, Ci.nsICacheMetaDataVisitor])
+}
+
+
+var EFCacheSessions = {
+ FILTER_MD_KEY: "noscript-external-filter",
+ WRITE_ACCESS: Ci.nsICache.ACCESS_WRITE,
+ READ_ACCESS: Ci.nsICache.ACCESS_READ,
+ OFFLINE_POLICY: Ci.nsICache.STORE_OFFLINE,
+
+ nsICacheEntryDescriptor: Ci.nsICacheEntryDescriptor,
+
+ get cacheService() {
+ delete this.cacheService;
+ return this.cacheService = Cc["@mozilla.org/network/cache-service;1"]
+ .getService(Ci.nsICacheService)
+ },
+
+ _sessions: {},
+ getSession: function(clientID, storagePolicy) {
+ const sk = clientID + "#" + storagePolicy;
+ if (!(sk in this._sessions)) {
+ this._sessions[sk] = this.cacheService.createSession(clientID, storagePolicy, true);
+ }
+ return this._sessions[sk];
+ },
+
+ setFiltered: function(ce, filterName) {
+ ce.setMetaDataElement(this.FILTER_MD_KEY, filterName);
+ },
+ isFiltered: function(ce, filterName) {
+ return ce.getMetaDataElement(this.FILTER_MD_KEY) == filterName;
+ },
+
+ purge: function() {
+ const whitelists = ExternalFilters.whitelists;
+ if (whitelists) {
+ this.whitelists = whitelists;
+ const t = Date.now();
+
+ this._entries = [];
+ this.cacheService.visitEntries(this);
+ this._entries.forEach(this._open, this);
+ delete this._entries;
+
+ ExternalFilters.log("Cache purged in " + (Date.now() - t) + "ms");
+ }
+ },
+
+ _open: function(ce) {
+ try {
+ this.getSession(ce.clientID, ce.storagePolicy)
+ .asyncOpenCacheEntry(ce.key, this.READ_ACCESS, this);
+ } catch(e) {
+ // already purged?
+ }
+ },
+
+ visitDevice: function(deviceID, deviceInfo) {
+ return true;
+ },
+ visitEntry: function(deviceID, ce) {
+ this._entries.push({ // we must clone ce, since it appears to be a reused stub
+ key: ce.key,
+ clientID: ce.clientID,
+ storagePolicy: ce.storagePolicy
+ });
+ return true;
+ },
+
+ onCacheEntryAvailable: function(ce, accessGranted, status) {
+ if (!status) return;
+ try {
+ if (accessGranted == this.READ_ACCESS && ce instanceof this.nsICacheEntryDescriptor) {
+ try {
+ const filterName = ce.getMetaDataElement(this.FILTER_MD_KEY);
+ if (filterName) {
+ const wl = this.whitelists[filterName];
+ if (wl && wl.test(ce.key)) {
+ ExternalFilters.log("Dooming cache entry " + ce.key);
+ ce.doom();
+ return;
+ }
+ }
+ } catch(e) {
+ // meta data not found
+ }
+ } else {
+ ExternalFilters.log(ce.key + ": MAYDAY!!!");
+ }
+ ce.markValid();
+ } catch(e) {
+ if (ce) ce.close();
+ }
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsICacheListener, Ci.nsICacheVisitor])
+}
diff --git a/extensions/noscript/chrome/content/noscript/FlashIdiocy.js b/extensions/noscript/chrome/content/noscript/FlashIdiocy.js
new file mode 100644
index 0000000..f1096c6
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/FlashIdiocy.js
@@ -0,0 +1,133 @@
+FlashIdiocy.purgeBadEncodings = s => s.replace(/%(?:[0-9a-f]?(?:[^0-9a-f]|$))/ig, "");
+FlashIdiocy.platformDecode = s => s.replace(/%[8-9a-f][0-9a-f]/ig, s => FlashIdiocy.map[s.substring(1).toLowerCase()]);
+
+FlashIdiocy.map = {
+ "80": "?",
+ "81": "Â",
+ "82": "?",
+ "83": "?",
+ "84": "?",
+ "85": "?",
+ "86": "?",
+ "87": "?",
+ "88": "?",
+ "89": "?",
+ "8a": "?",
+ "8b": "?",
+ "8c": "?",
+ "8d": "Â",
+ "8e": "?",
+ "8f": "Â",
+ "90": "Â",
+ "91": "?",
+ "92": "?",
+ "93": "?",
+ "94": "?",
+ "95": "?",
+ "96": "?",
+ "97": "?",
+ "98": "?",
+ "99": "?",
+ "9a": "?",
+ "9b": "?",
+ "9c": "?",
+ "9d": "Â",
+ "9e": "?",
+ "9f": "?",
+ "a0": " ",
+ "a1": "¡",
+ "a2": "¢",
+ "a3": "£",
+ "a4": "¤",
+ "a5": "Â¥",
+ "a6": "¦",
+ "a7": "§",
+ "a8": "¨",
+ "a9": "©",
+ "aa": "ª",
+ "ab": "«",
+ "ac": "¬",
+ "ad": "­",
+ "ae": "®",
+ "af": "¯",
+ "b0": "°",
+ "b1": "±",
+ "b2": "²",
+ "b3": "³",
+ "b4": "´",
+ "b5": "µ",
+ "b6": "¶",
+ "b7": "·",
+ "b8": "¸",
+ "b9": "¹",
+ "ba": "º",
+ "bb": "»",
+ "bc": "¼",
+ "bd": "½",
+ "be": "¾",
+ "bf": "¿",
+ "c0": "À",
+ "c1": "Ã",
+ "c2": "Â",
+ "c3": "Ã",
+ "c4": "Ä",
+ "c5": "Ã…",
+ "c6": "Æ",
+ "c7": "Ç",
+ "c8": "È",
+ "c9": "É",
+ "ca": "Ê",
+ "cb": "Ë",
+ "cc": "Ì",
+ "cd": "Ã",
+ "ce": "ÃŽ",
+ "cf": "Ã",
+ "d0": "Ã",
+ "d1": "Ñ",
+ "d2": "Ã’",
+ "d3": "Ó",
+ "d4": "Ô",
+ "d5": "Õ",
+ "d6": "Ö",
+ "d7": "×",
+ "d8": "Ø",
+ "d9": "Ù",
+ "da": "Ú",
+ "db": "Û",
+ "dc": "Ü",
+ "dd": "Ã",
+ "de": "Þ",
+ "df": "ß",
+ "e0": "à",
+ "e1": "á",
+ "e2": "â",
+ "e3": "ã",
+ "e4": "ä",
+ "e5": "Ã¥",
+ "e6": "æ",
+ "e7": "ç",
+ "e8": "è",
+ "e9": "é",
+ "ea": "ê",
+ "eb": "ë",
+ "ec": "ì",
+ "ed": "í",
+ "ee": "î",
+ "ef": "ï",
+ "f0": "ð",
+ "f1": "ñ",
+ "f2": "ò",
+ "f3": "ó",
+ "f4": "ô",
+ "f5": "õ",
+ "f6": "ö",
+ "f7": "÷",
+ "f8": "ø",
+ "f9": "ù",
+ "fa": "ú",
+ "fb": "û",
+ "fc": "ü",
+ "fd": "ý",
+ "fe": "þ",
+ "ff": "ÿ",
+}
diff --git a/extensions/noscript/chrome/content/noscript/ForcedRedirectionCallback.js b/extensions/noscript/chrome/content/noscript/ForcedRedirectionCallback.js
new file mode 100644
index 0000000..25b05b0
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/ForcedRedirectionCallback.js
@@ -0,0 +1,59 @@
+
+function NCBWrapper(delegator, delegate) {
+ this.delegator = delegator;
+ this.delegate = delegate;
+}
+NCBWrapper.prototype = {
+ QueryInterface: function(iid) {
+ if (Ci.nsIInterfaceRequestor.equals(iid)) {
+ return this;
+ }
+ return this.delegator.QueryInterface(iid);
+ },
+ getInterface: function(iid) {
+ try {
+ return this.delegate.QueryInterface(iid);
+ } catch (e) {}
+ return this.delegator.getInterface(iid);
+ }
+}
+
+function RCBDelegate(redirectCallback, label) {
+ this.delegator = redirectCallback;
+ this.label = label;
+}
+RCBDelegate.prototype = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.sIAsyncVerifyRedirectCallback]),
+ onRedirectVerifyCallback: function(result) {
+ try {
+ if (result !== 0) ns.log("Overriding failed (" + result + ") redirect callback for " + this.label); // plugin failure is 2147500037
+ this.delegator.onRedirectVerifyCallback(0);
+ } catch (e) {
+ ns.log(e);
+ }
+ }
+}
+
+function CESDelegate(ces) {
+ this.delegator = ces;
+}
+CESDelegate.prototype = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannelEventSink]),
+ asyncOnChannelRedirect: function(oldChan, newChan, flags, callback) {
+ let label = "plugin forced redirection";
+ try {
+ label = (oldChan.loadInfo.externalContentPolicyType || oldChan.loadInfo.contentPolicyType)+ ": " + oldChan.name + " -> " + newChan.name + " - " + flags;
+ } catch (e) {
+ ns.log(e);
+ }
+ let cb = new RCBDelegate(callback, label);
+ try {
+ this.delegator.asyncOnChannelRedirect(oldChan, newChan, Ci.nsIChannelEventSink.REDIRECT_INTERNAL, cb);
+ } catch (e) {
+ ns.log(e);
+ throw e;
+ } finally {
+ oldChan.notificationCallbacks = newChan.notificationCallbacks = this.delegator;
+ }
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/FrameScript.jsm b/extensions/noscript/chrome/content/noscript/FrameScript.jsm
new file mode 100644
index 0000000..4a896e7
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/FrameScript.jsm
@@ -0,0 +1,87 @@
+'use strict';
+
+var EXPORTED_SYMBOLS = ["FrameScript"];
+
+const { utils: Cu, interfaces: Ci, classes: Cc } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const SERVICE_READY = "NoScript.ServiceReady";
+const SERVICE_DISPOSE = "NoScript.Dispose";
+
+Cu.import("chrome://noscript/content/importer.jsm");
+let IMPORT = IMPORT_FOR(this);
+IMPORT("PasteHandler");
+IMPORT("UISync");
+
+function FrameScript(ctx) {
+ Object.defineProperty(ctx, "ns", {
+ get: function() {
+ try {
+ const CTRID = "@maone.net/noscript-service;1";
+ if (CTRID in Cc) {
+ let ns = Cc[CTRID].getService().wrappedJSObject;
+ delete this.ns;
+ return (this.ns = ns);
+ }
+ } catch(e) {
+ Cu.reportError(e);
+ }
+ return null;
+ },
+ configurable: true,
+ enumerable: true
+ });
+
+ this.ctx = ctx;
+
+ if (ctx.ns) {
+ this.init();
+ } else {
+ Services.obs.addObserver(this, SERVICE_READY, true);
+ }
+
+}
+
+FrameScript.prototype = {
+ QueryInterface: XPCOMUtils.generateQI(
+ [Ci.nsIObserver, Ci.nsISupportsWeakReference]),
+ init() {
+ if (this.uiSync) return;
+
+ let ctx = this.ctx;
+ this.pasteHandler = new PasteHandler(ctx);
+ this.uiSync = new UISync(ctx);
+ ctx.addMessageListener("NoScript:unload", this);
+ Services.obs.addObserver(this, SERVICE_DISPOSE, true);
+ let ns = ctx.ns;
+ if (ns.consoleDump && ctx.content && ctx.content.location)
+ ns.dump(`Framescript initialized in ${ctx.content.location.href}`);
+ },
+ observe(subj, topic, data) {
+ switch(topic) {
+ case SERVICE_READY:
+ this.init();
+ break;
+ case SERVICE_DISPOSE:
+ this.dispose();
+ break;
+ }
+ },
+ receiveMessage(m) {
+ if (m.name === "NoScript:unload") {
+ this.dispose();
+ }
+ },
+ dispose() {
+ if (!this.uiSync) return;
+ this.pasteHandler.dispose();
+ this.uiSync.unwire();
+ this.uiSync = this.pasteHandler = null;
+ let ctx = this.ctx;
+ let ns = ctx.ns;
+ if (ns.consoleDump && ctx.content && ctx.content.location)
+ this.ctx.ns.dump(`Framescript disposed in ${this.ctx.content.location.href}`);
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/HTTPS.js b/extensions/noscript/chrome/content/noscript/HTTPS.js
new file mode 100644
index 0000000..1538036
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/HTTPS.js
@@ -0,0 +1,405 @@
+LAZY_INCLUDE('Cookie');
+
+var HTTPS = {
+ ready: false,
+
+ secureCookies: false,
+ secureCookiesExceptions: null,
+ secureCookiesForced: null,
+ httpsForced: null,
+ httpsForcedExceptions: null,
+ httpsDefWhitelist: true,
+
+ replacements: [
+ [/^http:\/\/yui\.yahooapis\.com\//i, "https://yui-s.yahooapis.com/"]
+ ],
+ modifyURI: function(uri) {
+ let spec = uri.spec;
+ for (let replacement of this.replacements) {
+ if (replacement[0].test(spec)) uri.spec = spec.replace(replacement[0], replacement[1]);
+ }
+ uri.scheme = "https";
+ uri.port = -1;
+ return uri;
+ },
+
+ forceChannel: function(channel) {
+ return this.mustForce(channel.URI, channel) && this.replaceChannel(channel)
+ },
+ replaceChannel: function(channel) {
+ var uri = this.modifyURI(channel.URI.clone());
+
+ if (channel.redirectTo) {
+ channel.redirectTo(uri);
+ HTTPS.log("Redirected Channel " + uri.spec);
+ } else {
+ ChannelReplacement.runWhenPending(channel, function() {
+
+ new ChannelReplacement(channel, uri).replace(true);
+ HTTPS.log("Forced Channel " + uri.spec);
+ });
+ }
+ return true;
+
+ },
+
+ forceURI: function(uri, fallback, ctx) {
+ if (!uri.schemeIs("http")) return false;
+ if (IOUtil.newChannel(uri.spec).nsIHttpChannel.redirectTo) {
+ this.forceURI = DUMMY_FUNC;
+ return false;
+ }
+ return (this.forceURI = this._forceURI).apply(this, arguments);
+ },
+ _forceURI: function(uri, fallback, ctx) {
+ if (this.mustForce(uri)) {
+ try {
+
+ this.modifyURI(uri);
+
+ this.log("Forced URI " + uri.spec);
+ return true;
+
+ } catch(e) {
+ if (ctx) {
+ let g = Cu.getGlobalForObject(ctx);
+ if (ctx instanceof g.HTMLImageElement || ctx instanceof g.HTMLInputElement ||
+ ctx instanceof Ci.nsIObjectLoadingContent) {
+ uri = uri.clone();
+ uri.scheme = "https";
+
+ var type, attr;
+ if (ctx instanceof Ci.nsIObjectLoadingContent) {
+ type = "Object";
+ attr = "data";
+ } else {
+ type = "Image";
+ attr = "src";
+ }
+ Thread.asap(function() { ctx.setAttribute(attr, uri.spec); });
+
+ var msg = type + " HTTP->HTTPS redirection to " + uri.spec;
+ this.log(msg);
+ throw msg;
+ }
+ }
+ if (fallback && fallback()) {
+ this.log("Channel redirection fallback on " + uri.spec);
+ return true;
+ }
+
+ this.log("Error trying to force https on " + uri.spec + ": " + e);
+ }
+ }
+ return false;
+ },
+
+ get defWhitelist() {
+ delete this.defWhitelist;
+ return this.defWhitelist = new RegExp("\\b(?:" + ns.getPref("default").replace(/\./g, "\\.").split(/\s+/).join("|") + ")$");
+ },
+
+ mustForce: function(uri, channel) {
+ if (!uri.schemeIs("http")) return false;
+
+ let url = uri.spec;
+ if (this.httpsForcedExceptions && this.httpsForcedExceptions.test(url)) return false;
+
+ if (channel && this.httpsDefWhitelist &&
+ (channel.loadFlags & (Ci.nsIChannel.LOAD_DOCUMENT_URI | Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS)) &&
+ !(channel instanceof Ci.nsIHttpChannelInternal && !channel.allowSTS)) {
+ let site = ns.getSite(url);
+ if (this.defWhitelist.test(site) && ns.isJSEnabled(site)) {
+ return true;
+ }
+ }
+
+ return this.httpsForced && this.httpsForced.test(url) ||
+ this.httpsForcedBuiltIn && this.httpsForcedBuiltIn.test(url);
+ },
+
+ log: function(msg) {
+ this.log = ns.getPref("https.showInConsole", true)
+ ? function(msg) { ns.log("[NoScript HTTPS] " + msg); }
+ : function(msg) {}
+
+ return this.log(msg);
+ },
+
+ onCrossSiteRequest: function(channel, origin, browser, rw) {
+ try {
+ this.handleCrossSiteCookies(channel, origin, browser);
+ } catch(e) {
+ this.log(e + " --- " + e.stack);
+ }
+ },
+
+ registered: false,
+ handleSecureCookies: function(req) {
+ /*
+ we check HTTPS responses setting cookies and
+ 1) if host is in the noscript.secureCookiesExceptions list we let
+ it pass through
+ 2) if host is in the noscript.secureCookiesForced list we append a
+ ";Secure" flag to every non-secure cookie set by this response
+ 3) otherwise, we just log unsafe cookies BUT if no secure cookie
+ is set, we patch all these cookies with ";Secure" like in #2.
+ However, if current request redirects (directly or indirectly)
+ to an unencrypted final URI, we remove our ";Secure" patch to
+ ensure compatibility (ref: mail.yahoo.com and hotmail.com unsafe
+ behavior on 11 Sep 2008)
+ */
+
+ if (!this.secureCookies) return;
+
+ var uri = req.URI;
+
+ if (uri.schemeIs("https") &&
+ !(this.secureCookiesExceptions && this.secureCookiesExceptions.test(uri.spec)) &&
+ (req instanceof Ci.nsIHttpChannel)) {
+ try {
+ var host = uri.host;
+ try {
+ var cookies = req.getResponseHeader("Set-Cookie");
+ } catch(mayHappen) {
+ return;
+ }
+ if (cookies) {
+ var forced = this.secureCookiesForced && this.secureCookiesForced.test(uri.spec);
+ var secureFound = false;
+ var unsafe = null;
+
+ const rw = ns.requestWatchdog;
+ var browser = rw.findBrowser(req);
+
+ if (!browser) {
+ if (ns.consoleDump) ns.dump("Browser not found for " + uri.spec);
+ }
+
+ var unsafeMap = this.getUnsafeCookies(browser) || {};
+ var c;
+ for (var cs of cookies.split("\n")) {
+ c = new Cookie(cs, host);
+ if (c.secure && c.belongsTo(host)) {
+ this.log("Secure cookie set by " + host + ": " + c);
+ secureFound = c;
+ delete unsafeMap[c.id];
+ } else {
+ if (!unsafe) unsafe = [];
+ unsafe.push(c);
+ }
+ }
+
+
+ if (unsafe && !(forced || secureFound)) {
+ // this page did not set any secure cookie, let's check if we already have one
+ secureFound = Cookie.find(function(c) {
+ return (c instanceof Ci.nsICookie) && (c instanceof Ci.nsICookie2)
+ && c.isSecure && !unsafe.find(function(x) { return x.sameAs(c); })
+ });
+ if (secureFound) {
+ this.log("Secure cookie found for this host: " + Cookie.prototype.toString.apply(secureFound));
+ }
+ }
+
+ if (secureFound && !forced) {
+ this.cookiesCleanup(secureFound);
+ return;
+ }
+
+ if (!unsafe) return;
+
+ var msg;
+ if (forced || !secureFound) {
+ req.setResponseHeader("Set-Cookie", "", false);
+ msg = forced ? "FORCED SECURE" : "AUTOMATIC SECURE";
+ forced = true;
+ } else {
+ msg = "DETECTED INSECURE";
+ }
+
+ if (!this.registered) {
+ this.registered = true;
+ rw.addCrossSiteListener(this);
+ }
+
+ this.setUnsafeCookies(browser, unsafeMap);
+ msg += " on https://" + host + ": ";
+ for (c of unsafe) {
+ if (forced) {
+ c.secure = true;
+ req.setResponseHeader("Set-Cookie", c.source + ";Secure", true);
+ unsafeMap[c.id] = c;
+ }
+ this.log(msg + c);
+ }
+
+ }
+ } catch(e) {
+ if (ns.consoleDump) ns.dump(e);
+ }
+ }
+ },
+
+ handleCrossSiteCookies: function(req, origin, browser) {
+
+ var unsafeCookies = this.getUnsafeCookies(browser);
+ if (!unsafeCookies) return;
+
+ var uri = req.URI;
+ var dscheme = uri.scheme;
+
+ var oparts = origin && origin.match(/^(https?):\/\/([^\/:]+).*?(\/.*)/);
+ if (!(oparts && /https?/.test(dscheme))) return;
+
+ var oscheme = oparts[1];
+ if (oscheme == dscheme) return; // we want to check only cross-scheme requests
+
+ var dsecure = dscheme == "https";
+
+ if (dsecure && !ns.getPref("secureCookies.recycle", false)) return;
+
+ var dhost = uri.host;
+ var dpath = uri.filePath;
+
+ var ohost = oparts[2];
+ var opath = oparts[3];
+
+ var ocookieCount = 0, totCount = 0;
+ var dcookies = [];
+ var c;
+
+ for (var k in unsafeCookies) {
+ c = unsafeCookies[k];
+ if (!c.exists()) {
+ delete unsafeCookies[k];
+ } else {
+ totCount++;
+ if (c.belongsTo(dhost, dpath) && c.isSecure != dsecure) { // either secure on http or not secure on https
+ dcookies.push(c);
+ }
+ if (c.belongsTo(ohost, opath)) {
+ ocookieCount++;
+ }
+ }
+ }
+
+ if (!totCount) {
+ this.setUnsafeCookies(browser, null);
+ return;
+ }
+
+ // We want to "desecurify" cookies only if cross-navigation to unsafe
+ // destination originates from a site sharing some secured cookies
+
+ if (ocookieCount == 0 && !dsecure || !dcookies.length) return;
+
+ if (dsecure) {
+ this.log("Detected cross-site navigation with secured cookies: " + origin + " -> " + uri.spec);
+
+ } else {
+ this.log("Detected unsafe navigation with NoScript-secured cookies: " + origin + " -> " + uri.spec);
+ this.log(uri.prePath + " cannot support secure cookies because it does not use HTTPS. Consider forcing HTTPS for " + uri.host + " in NoScript's Advanced HTTPS options panel.")
+ }
+
+ var cs = Cc['@mozilla.org/cookieService;1'].getService(Ci.nsICookieService).getCookieString(uri, req);
+
+ for (c of dcookies) {
+ c.secure = dsecure;
+ c.save();
+ this.log("Toggled secure flag on " + c);
+ }
+
+ if (cs) {
+ dcookies.push.apply(
+ dcookies, cs.split(/\s*;\s*/).map(function(cs) { var nv = cs.split("="); return { name: nv.shift(), value: nv.join("=") } })
+ .filter(function(c) { return dcookies.every(function(x) { return x.name != c.name }) })
+ );
+ }
+
+ cs = dcookies.map(function(c) { return c.name + "=" + c.value }).join("; ");
+
+ this.log("Sending Cookie for " + dhost + ": " + cs);
+ req.setRequestHeader("Cookie", cs, false); // "false" because merge syntax breaks Cookie header
+ },
+
+
+ cookiesCleanup: function(refCookie) {
+ var downgraded = [];
+
+ var ignored = this.secureCookiesExceptions;
+ var disabled = !this.secureCookies;
+ var bi = DOM.createBrowserIterator();
+ var unsafe, k, c, total, deleted;
+ for (var browser; browser = bi.next();) {
+ unsafe = this.getUnsafeCookies(browser);
+ if (!unsafe) continue;
+ total = deleted = 0;
+ for (k in unsafe) {
+ c = unsafe[k];
+ total++;
+ if (disabled || (refCookie ? c.belongsTo(refCookie.host) : ignored && ignored.test(c.rawHost))) {
+ if (c.exists()) {
+ this.log("Cleaning Secure flag from " + c);
+ c.secure = false;
+ c.save();
+ }
+ delete unsafe[k];
+ deleted++;
+ }
+ }
+ if (total == deleted) this.setUnsafeCookies(browser, null);
+ if (!this.cookiesPerTab) break;
+ }
+ },
+
+ get cookiesPerTab() {
+ return ns.getPref("secureCookies.perTab", false);
+ },
+
+ _globalUnsafeCookies: {},
+ getUnsafeCookies: function(browser) {
+ return this.cookiesPerTab
+ ? browser && ns.getExpando(browser, "unsafeCookies")
+ : this._globalUnsafeCookies;
+ },
+ setUnsafeCookies: function(browser, value) {
+ return this.cookiesPerTab
+ ? browser && ns.setExpando(browser, "unsafeCookies", value)
+ : this._globalUnsafeCookies = value;
+ },
+
+ _getParent: function(req, w) {
+ return w && w.frameElement || DOM.findBrowserForNode(w || IOUtil.findWindow(req));
+ }
+
+};
+
+
+["secureCookies", "secureCookiesExceptions", "secureCookiesForced"].forEach(function(p) {
+ var v = HTTPS[p];
+ delete HTTPS[p];
+ HTTPS.__defineGetter__(p, function() {
+ return v;
+ });
+ HTTPS.__defineSetter__(p, function(n) {
+ v = n;
+ if (HTTPS.ready) HTTPS.cookiesCleanup();
+ return v;
+ });
+});
+
+["secureCookies", "secureCookiesExceptions", "secureCookiesForced",
+ "httpsForcedBuiltIn", "httpsForced", "httpsForcedExceptions",
+ "httpsDefWhitelist",
+ ]
+ .forEach(function(p) {
+ try {
+ ns.syncPrefs(ns.prefs, p);
+ } catch(e) {
+ ns.dump(e.message + ":" + e.stack + " setting " + p + "\n");
+ }
+});
+
+
+HTTPS.ready = true;
diff --git a/extensions/noscript/chrome/content/noscript/IO.js b/extensions/noscript/chrome/content/noscript/IO.js
new file mode 100644
index 0000000..2b93cce
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/IO.js
@@ -0,0 +1,53 @@
+var IO = {
+ readFile: function(file, charset) {
+ var res;
+
+ const is = Cc["@mozilla.org/network/file-input-stream;1"]
+ .createInstance(Ci.nsIFileInputStream );
+ is.init(file ,0x01, 256 /*0400*/, null);
+ const sis = Cc["@mozilla.org/scriptableinputstream;1"]
+ .createInstance(Ci.nsIScriptableInputStream);
+ sis.init(is);
+
+ res = sis.read(sis.available());
+ is.close();
+
+ if (charset !== null) { // use "null" if you want uncoverted data...
+ const unicodeConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+ .createInstance(Ci.nsIScriptableUnicodeConverter);
+ try {
+ unicodeConverter.charset = charset || "UTF-8";
+ } catch(ex) {
+ unicodeConverter.charset = "UTF-8";
+ }
+ res = unicodeConverter.ConvertToUnicode(res);
+ }
+
+ return res;
+ },
+ writeFile: function(file, content, charset) {
+ const unicodeConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+ .createInstance(Ci.nsIScriptableUnicodeConverter);
+ try {
+ unicodeConverter.charset = charset || "UTF-8";
+ } catch(ex) {
+ unicodeConverter.charset = "UTF-8";
+ }
+
+ content = unicodeConverter.ConvertFromUnicode(content);
+ const os = Cc["@mozilla.org/network/file-output-stream;1"]
+ .createInstance(Ci.nsIFileOutputStream);
+ os.init(file, 0x02 | 0x08 | 0x20, 448 /*0700*/, 0);
+ os.write(content, content.length);
+ os.close();
+ },
+
+ safeWriteFile: function(file, content, charset) {
+ var tmp = file.clone();
+ var name = file.leafName;
+ tmp.leafName = name + ".tmp";
+ tmp.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, file.exists() ? file.permissions : 384 /*0600*/);
+ this.writeFile(tmp, content, charset);
+ tmp.moveTo(file.parent, name);
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/IOUtil.js b/extensions/noscript/chrome/content/noscript/IOUtil.js
new file mode 100644
index 0000000..72daac0
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/IOUtil.js
@@ -0,0 +1,290 @@
+var IOUtil = {
+ asyncNetworking: true,
+ proxiedDNS: 0,
+
+ attachToChannel(channel, key, data) {
+ if (channel instanceof Ci.nsIWritablePropertyBag2) {
+ channel.setPropertyAsInterface(key, data);
+ }
+ return data;
+ },
+ extractFromChannel(channel, key, remove = false) {
+ if (channel instanceof Ci.nsIPropertyBag2) {
+ let p = channel.get(key);
+ if (p) {
+ if (remove && (channel instanceof Ci.nsIWritablePropertyBag)) channel.deleteProperty(key);
+ if (p.wrappedJSObject) return p.wrappedJSObject;
+ p instanceof Ci.nsIURL || p instanceof Ci.nsIURI;
+ return p;
+ }
+ }
+ return null;
+ },
+
+ reqData(req, key, remove = false) {
+ let data = IOUtil.extractFromChannel(req, key, remove);
+ if (data) return data.wrappedJSObject;
+ if (remove) return null;
+
+ data = {};
+ data.wrappedJSObject = data;
+ return IOUtil.attachToChannel(req, key, data);
+ },
+
+ extractInternalReferrer: function(channel) {
+ if (channel instanceof Ci.nsIPropertyBag2) {
+ const key = "docshell.internalReferrer";
+ if (channel.hasKey(key))
+ try {
+ return channel.getPropertyAsInterface(key, Ci.nsIURL);
+ } catch(e) {}
+ }
+ return null;
+ },
+ extractInternalReferrerSpec: function(channel) {
+ var ref = this.extractInternalReferrer(channel);
+ return ref && ref.spec || null;
+ },
+
+ getProxyInfo: function(channel) {
+ return Ci.nsIProxiedChannel && (channel instanceof Ci.nsIProxiedChannel)
+ ? channel.proxyInfo
+ : Cc["@mozilla.org/network/protocol-proxy-service;1"]
+ .getService(Ci.nsIProtocolProxyService)
+ .resolve(channel.URI, 0);
+ },
+
+
+ canDoDNS: function(channel) {
+ if (!channel || IOS.offline) return false;
+
+ var proxyInfo = this.getProxyInfo(channel);
+ switch(this.proxiedDNS) {
+ case 1:
+ return !(proxyInfo && (proxyInfo.flags & Ci.nsIProxyInfo.TRANSPARENT_PROXY_RESOLVES_HOST));
+ case 2:
+ return true;
+ default:
+ return !proxyInfo || proxyInfo.type == "direct";
+ }
+
+ },
+
+ abort: function(channel) {
+ if (ns.consoleDump) ns.dump("Aborting " + channel.name + " @ " + new Error().stack);
+ channel.cancel(Cr.NS_ERROR_ABORT);
+ this.resumeParentChannel(channel, true);
+ },
+
+ _suspendedChannelsMap: new Map(),
+ _suspendedChannelId: 1,
+ resumeParentChannel(channelOrID, abort = false) {
+ let id;
+ if (channelOrID instanceof Ci.nsIChannel) {
+ id = ns.reqData(channelOrID).requestID;
+ } else {
+ id = channelOrID;
+ }
+ if (id) {
+ if (IPC.parent) {
+ let map = this._suspendedChannelsMap;
+ if (map.has(id)) {
+ let channel = map.get(id).get();
+ map.delete(id);
+ if (channel) {
+ try {
+ if (abort) {
+ this.abort(channel);
+ }
+ channel.resume();
+ } catch(e) {
+ ns.dump(e);
+ }
+ }
+ }
+ } else {
+ Services.cpmm.sendSyncMessage(IPC_P_MSG.RESUME, {id, abort });
+ }
+ }
+ },
+ suspendChannel(channel) {
+ let map = this._suspendedChannelsMap;
+ let reqData = ns.reqData(channel);
+ let id = reqData.requestID;
+ if (!id) {
+ id = reqData.requestID = this._suspendedChannelId++;
+ }
+ map.set(id, Cu.getWeakReference(channel));
+ channel.suspend();
+ },
+
+ isMediaDocOrFrame(channel, contentType) {
+ try {
+ let cpType = channel.loadInfo.externalContentPolicyType;
+ if (cpType === 7 || (cpType === 6 &&
+ /^(?:video|audio|application)\//i.test(contentType === undefined ? channel.contentType : contentType))) {
+ try {
+ return !/^attachment\b/i.test(req.getResponseHeader("Content-disposition"));
+ } catch(e) {
+ }
+ return true;
+ }
+ } catch (e) {
+ }
+ return false;
+ },
+
+ findWindow: function(channel) {
+ for (var cb of [channel.notificationCallbacks,
+ channel.loadGroup && channel.loadGroup.notificationCallbacks]) {
+ if (cb instanceof Ci.nsIInterfaceRequestor) {
+ if (Ci.nsILoadContext) try {
+ // For Gecko 1.9.1
+ return cb.getInterface(Ci.nsILoadContext).associatedWindow;
+ } catch(e) {}
+
+ try {
+ // For Gecko 1.9.0
+ return cb.getInterface(Ci.nsIDOMWindow);
+ } catch(e) {}
+ }
+ }
+ return null;
+ },
+
+ findBrowser: function(channel) {
+ try {
+ let b = channel.notificationCallbacks.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsILoadContext).topFrameElement;
+ if (b) return b;
+ } catch (e) {
+ }
+ return DOM.findBrowserForNode(this.findWindow(channel));
+ },
+
+ _protocols: {}, // caching them we gain a 33% speed boost in URI creation :)
+ newURI: function(url, originCharset, baseUri) {
+ try {
+ let scheme = url.substring(0, url.indexOf(':'));
+ return (this._protocols[scheme] ||
+ (this._protocols[scheme] =
+ Cc["@mozilla.org/network/protocol;1?name=" + scheme]
+ .getService(Ci.nsIProtocolHandler)))
+ .newURI(url, originCharset, baseUri);
+ } catch(e) {
+ return IOS.newURI(url, originCharset, baseUri);
+ }
+ },
+
+ newChannel: function(url, originCharset, baseUri, loadingNode, loadingPrincipal, triggeringPrincipal, securityFlags, contentPolicyType) {
+ return ("newChannel2" in IOS)
+ ? (this.newChannel = this.newChannel2).apply(this, arguments)
+ : IOS.newChannel(url, originCharset, baseUri);
+ },
+ newChannel2: function(url, originCharset, baseUri, loadingNode, loadingPrincipal, triggeringPrincipal, securityFlags, contentPolicyType) {
+ return IOS.newChannel2(url, originCharset, baseUri, loadingNode, loadingPrincipal, triggeringPrincipal, securityFlags, contentPolicyType);
+ },
+
+ unwrapURL: function(url) {
+ try {
+ if (!(url instanceof Ci.nsIURI))
+ url = this.newURI(url);
+
+ switch (url.scheme) {
+ case "view-source":
+ return this.unwrapURL(url.spec.replace(/^.*?:/, ''));
+ case "feed":
+ case "pcast":
+ let u = url.spec.substring(url.scheme.length + 1);
+ if (u.substring(0, 2) == '//') u = "http:" + u;
+ return this.unwrapURL(u);
+ case "wyciwyg":
+ return this.unwrapURL(url["path" in url ? "path" : "pathQueryRef"].replace(/^\/\/\d+\//, ""));
+ case "jar":
+ if (url instanceof Ci.nsIJARURI)
+ return this.unwrapURL(url.JARFile);
+ }
+ }
+ catch (e) {}
+
+ return url;
+ },
+
+
+ get _channelFlags() {
+ delete this._channelFlags;
+ const constRx = /^[A-Z_]+$/;
+ const ff = {};
+ [Ci.nsIHttpChannel, Ci.nsICachingChannel].forEach(function(c) {
+ for (var p in c) {
+ if (constRx.test(p)) ff[p] = c[p];
+ }
+ });
+ return this._channelFlags = ff;
+ },
+ humanFlags: function(loadFlags) {
+ var hf = [];
+ var c = this._channelFlags;
+ for (var p in c) {
+ if (loadFlags & c[p]) hf.push(p + "=" + c[p]);
+ }
+ return hf.join("\n");
+ },
+
+ queryNotificationCallbacks: function(chan, iid) {
+ var cb;
+ try {
+ cb = chan.notificationCallbacks.getInterface(iid);
+ if (cb) return cb;
+ } catch(e) {}
+
+ try {
+ return chan.loadGroup && chan.loadGroup.notificationCallbacks.getInterface(iid);
+ } catch(e) {}
+
+ return null;
+ },
+
+ anonymizeChannel(channel) {
+ channel.setRequestHeader("Cookie", '', false);
+ channel.setRequestHeader("Authorization", '', false);
+ channel.loadFlags |= channel.LOAD_ANONYMOUS;
+ },
+ anonymizeURI: function(uri, cookie) {
+ if (uri instanceof Ci.nsIURL) {
+ uri.query = this.anonymizeQS(uri.query, cookie);
+ } else return this.anonymizeURL(uri, cookie);
+ return uri;
+ },
+ anonymizeURL: function(url, cookie) {
+ var parts = url.split("?");
+ if (parts.length < 2) return url;
+ parts[1] = this.anonymizeQS(parts[1], cookie);
+ return parts.join("?");
+ },
+
+ _splitName: (nv) => nv.split("=")[0],
+ _qsRx: /[&=]/,
+ _anonRx: /(?:auth|s\w+(?:id|key)$)/,
+ anonymizeQS: function(qs, cookie) {
+ if (!qs) return qs;
+ if (!this._qsRx.test(qs)) return '';
+
+ var cookieNames, hasCookies;
+ if ((hasCookies = !!cookie)) cookieNames = cookie.split(/\s*;\s*/).map(this._splitName)
+
+ let parms = qs.split("&");
+ for (let j = parms.length; j-- > 0;) {
+ let nv = parms[j].split("=");
+ let name = nv[0];
+ if (this._anonRx.test(name) || cookie && cookieNames.indexOf(name) > -1)
+ parms.splice(j, 1);
+ }
+ return parms.join("&");
+ },
+
+ get TLDService() {
+ delete this.TLDService;
+ return (this.TLDService = Cc["@mozilla.org/network/effective-tld-service;1"].getService(Ci.nsIEffectiveTLDService));
+ }
+
+};
diff --git a/extensions/noscript/chrome/content/noscript/InjectionChecker.js b/extensions/noscript/chrome/content/noscript/InjectionChecker.js
new file mode 100644
index 0000000..fa96c93
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/InjectionChecker.js
@@ -0,0 +1,1734 @@
+
+const wordCharRx = /\w/g;
+function fuzzify(s) {
+ return s.replace(wordCharRx, '\\W*(?:/[*/][^]*)?$&');
+}
+
+const IC_COMMENT_PATTERN = '\\s*(?:\\/[\\/\\*][^]+)?';
+const IC_WINDOW_OPENER_PATTERN = fuzzify("alert|confirm|prompt|open(?:URL)?|print|show") + "\\w*" + fuzzify("Dialog");
+const IC_EVAL_PATTERN = "\\b(?:" +
+ fuzzify('eval|set(?:Timeout|Interval)|(?:f|F)unction|Script|toString|Worker|document|constructor|generateCRMFRequest|jQuery|fetch|write(?:ln)?|__(?:define(?:S|G)etter|noSuchMethod)__|definePropert(?:y|ies)') +
+ "|\\$|" + IC_WINDOW_OPENER_PATTERN + ")\\b";
+const IC_EVENT_PATTERN = "on(?:c(?:o(?:n(?:nect(?:i(?:on(?:statechanged|available)|ng)|ed)?|t(?:rollerchange|extmenu))|m(?:p(?:osition(?:update|start|end)|lete)|mand(?:update)?)|py)|h(?:a(?:r(?:ging(?:time)?change|acteristicchanged)|nge)|ecking)|a(?:n(?:play(?:through)?|cel)|(?:llschang|ch)ed|rdstatechange)|u(?:rrent(?:channel|source)changed|echange|t)|l(?:i(?:rmodechange|ck)|ose)|fstatechange)|p(?:o(?:inter(?:l(?:ock(?:change|error)|eave)|o(?:ver|ut)|cancel|enter|down|move|up)|p(?:up(?:hid(?:den|ing)|show(?:ing|n)|positioned)|state))|a(?:i(?:ring(?:con(?:firmation|sent)req|aborted)|nt)|ge(?:hide|show)|(?:st|us)e)|u(?:ll(?:vcard(?:listing|entry)|phonebook)req|sh(?:subscriptionchange)?)|(?:[is]|ending|ty)change|lay(?:ing)?|rogress|hoto)|s(?:t(?:a(?:t(?:uschanged|echange)|lled|rt)|o(?:rage(?:areachanged)?|p)|k(?:sessione|comma)nd)|e(?:lect(?:ionchange|start)?|ek(?:ing|ed)|n(?:ding|t)|t)|ou(?:rce(?:(?:clos|end)ed|open)|nd(?:start|end))|c(?:(?:anningstate|ostatus)changed|roll)|pe(?:akerforcedchange|ech(?:start|end))|h(?:ipping(?:address|option)change|ow)|u(?:ccess|spend|bmit))|d(?:e(?:vice(?:p(?:roximity|aired)|(?:orienta|mo)tion|(?:unpaire|foun)d|change|light)|l(?:ivery(?:success|error)|eted))|i(?:s(?:c(?:hargingtimechange|onnect(?:ing|ed)?)|playpasskeyreq|abled)|aling)|r(?:a(?:g(?:e(?:n(?:ter|d)|xit)|(?:gestur|leav)e|start|drop|over)?|in)|op)|ata(?:(?:availabl|chang)e|error)?|urationchange|ownloading|blclick)|m(?:o(?:z(?:pointerlock(?:change|error)|fullscreen(?:change|error)|key(?:down|up)onplugin|accesskeynotfound|orientationchange)|use(?:l(?:ongtap|eave)|o(?:ver|ut)|enter|wheel|down|move|up))|a(?:p(?:se(?:tmessagestatus|ndmessage)|message(?:slisting|update)|folderlisting|getmessage)req|rk)|(?:idimessag|ut)e|essage(?:error)?)|a(?:n(?:imation(?:iteration|cancel|start|end)|tennaavailablechange)|d(?:d(?:sourcebuffer|track)|apter(?:remov|add)ed)|ttribute(?:(?:write|read)req|changed)|u(?:dio(?:process|start|end)|xclick)|b(?:solutedeviceorientation|ort)|(?:2dpstatuschang|ppinstall)ed|fter(?:scriptexecute|print)|ctiv(?:estatechanged|ate)|lerting)|r(?:e(?:s(?:ourcetimingbufferfull|u(?:m(?:ing|e)|lt)|ponseprogress|ize|et)|mo(?:ve(?:sourcebuffer|track)|te(?:resume|hel)d)|ad(?:y(?:statechange)?|success|error)|quest(?:mediaplaystatu|progres)s|pea(?:tEven)?t|loadpage|trieving|ceived)|(?:(?:adiost)?ate|t)change|ds(?:dis|en)abled)|Moz(?:S(?:wipeGesture(?:(?:May)?Start|Update|End)?|crolledAreaChanged)|M(?:agnifyGesture(?:Update|Start)?|ouse(?:PixelScroll|Hittest))|EdgeUI(?:C(?:omplet|ancel)|Start)ed|RotateGesture(?:Update|Start)?|(?:Press)?TapGesture|AfterPaint)|w(?:eb(?:kit(?:Animation(?:Iteration|Start|End)|animation(?:iteration|start|end)|(?:TransitionE|transitione)nd)|socket)|a(?:iting(?:forkey)?|rning)|heel)|DOM(?:Node(?:Inserted(?:IntoDocument)?|Removed(?:FromDocument)?)|(?:CharacterData|Subtree)Modified|A(?:ttrModified|ctivate)|Focus(?:Out|In)|MouseScroll)|b(?:e(?:fore(?:(?:evicte|unloa)d|p(?:aste|rint)|scriptexecute|c(?:opy|ut))|gin(?:Event)?)|u(?:fferedamountlow|sy)|l(?:ocked|ur)|roadcast|oundary)|v(?:rdisplay(?:(?:presentchang|activat)e|d(?:eactivate|isconnect)|connect)|o(?:ice(?:schanged|change)|lumechange)|(?:isibility|ersion)change)|e(?:n(?:ter(?:pincodereq)?|(?:crypt|abl)ed|d(?:Event|ed)?)|m(?:ergencycbmodechange|ptied)|(?:itbroadcas|vic)ted|rror|xit)|t(?:o(?:uch(?:cancel|start|move|end)|ggle)|ransition(?:cancel|start|end|run)|ime(?:update|out)|e(?:rminate|xt)|ypechange)|l(?:o(?:ad(?:e(?:d(?:meta)?data|nd)|ing(?:error|done)?|start)?|stpointercapture)|(?:anguage|evel)change|y)|u(?:p(?:date(?:(?:fou|e)nd|ready|start)?|gradeneeded)|s(?:erproximity|sdreceived)|n(?:derflow|load|mute))|o(?:(?:(?:rientation|tastatus)chang|(?:ff|n)lin)e|b(?:expasswordreq|solete)|verflow(?:changed)?|pen)|g(?:amepad(?:(?:dis)?connected|button(?:down|up)|axismove)|(?:otpointercaptur|roupchang)e|et)|f(?:ullscreen(?:change|error)|ocus(?:out|in)?|requencychange|(?:inis|etc)h|ailed)|i(?:cc(?:(?:info)?change|(?:un)?detected)|n(?:coming|stall|valid|put))|h(?:(?:fp|id)statuschanged|e(?:adphoneschange|ld)|ashchange|olding)|n(?:o(?:tificationcl(?:ick|ose)|update|match)|ewrdsgroup)|SVG(?:(?:Unl|L)oad|Resize|Scroll|Zoom)|key(?:statuseschange|press|down|up)|R(?:adioStateChange|equest)|CheckboxStateChange|(?:AppComman|Loa)d|zoom)"
+ // autogenerated from nsGkAtomList.h
+ ;
+const IC_EVENT_DOS_PATTERN =
+ "\\b(?:" + IC_EVENT_PATTERN + ")[^]*=[^]*\\b(?:" + IC_WINDOW_OPENER_PATTERN + ")\\b" +
+ "|\\b(?:" + IC_WINDOW_OPENER_PATTERN + ")\\b[^]+\\b(?:" + IC_EVENT_PATTERN + ")[^]*=";
+
+var InjectionChecker = {
+ reset: function () {
+
+ this.isPost =
+ this.base64 =
+ this.nameAssignment = false;
+
+ this.base64tested = [];
+
+ },
+
+ fuzzify: fuzzify,
+ syntax: new SyntaxChecker(),
+ _log: function(msg, t, i) {
+ if (msg) msg = this._printable(msg);
+ if(!(i || t)) {
+ msg += " - LINES: ";
+ var lines = [];
+ for (var stack = Components.stack; (stack = stack.caller);) {
+ lines.push(stack.lineNumber);
+ }
+ msg += lines.join(", ");
+ }
+ else {
+ if (t) msg += " - TIME: " + (Date.now() - t);
+ if (i) msg += " - ITER: " + i;
+ }
+ this.dump("[NoScript InjectionChecker] " + msg + "\n");
+ },
+
+ _printable: function (msg) {
+ return msg.toString().replace(/[^\u0020-\u007e]/g, function(s) { return "{" + s.charCodeAt(0).toString(16) + "}"; });
+ },
+
+ dump: dump,
+ log: function() {},
+ get logEnabled() { return this.log == this._log; },
+ set logEnabled(v) { this.log = v ? this._log : function() {}; },
+
+ escalate: function(msg) {
+ this.log(msg);
+ ns.log("[NoScript InjectionChecker] " + msg);
+ },
+
+ bb: function(brac, s, kets) {
+ for(var j = 3; j-- > 0;) {
+ s = brac + s + kets;
+ if (this.checkJSSyntax(s)) return true;
+ }
+ return false;
+ },
+
+ checkJSSyntax(s) {
+ // bracket balancing for micro injections like "''), e v a l (name,''"
+ if (/^(?:''|"")?[^\('"]*\)/.test(s)) return this.bb("x(\n", s, "\n)");
+ if (/^(?:''|"")?[^\['"]*\\]/.test(s)) return this.bb("y[\n", s, "\n]");
+ if (/^(?:''|"")?[^\{'"]*\}/.test(s)) return this.bb("function z() {\n", s, "\n}");
+
+ let syntax = this.syntax;
+ s += " /* COMMENT_TERMINATOR */\nDUMMY_EXPR";
+ if (syntax.check(s)) {
+ this.log("Valid fragment " + s);
+ return true;
+ }
+ return false;
+ },
+
+ checkTemplates(script) {
+ let templateExpressions = script.replace(/[[\]{}]/g, ";");
+ return templateExpressions !== script &&
+ (this.maybeMavo(script) ||
+ (this.maybeJS(templateExpressions, true) &&
+ (this.syntax.check(templateExpressions) ||
+ /[^><=]=[^=]/.test(templateExpressions) && this.syntax.check(
+ templateExpressions.replace(/([^><=])=(?=[^=])/g, '$1=='))
+ )));
+ },
+
+ maybeMavo(s) {
+ return /\[[^]*\([^]*\)[^]*\]/.test(s) && /\b(?:and|or|mod|\$url\b)/.test(s) &&
+ this.maybeJS(s.replace(/\b(?:and|or|mod|[[\]])/g, ',').replace(/\$url\b/g, 'location'), true);
+ },
+ get breakStops() {
+ var def = "\\/\\?&#;\\s\\x00}<>"; // we stop on URL, JS and HTML delimiters
+ var bs = {
+ nq: new RegExp("[" + def + "]")
+ };
+ Array.forEach("'\"`", // special treatment for quotes
+ function(c) { bs[c] = new RegExp("[" + def + c + "]"); }
+ );
+ delete this.breakStops;
+ return (this.breakStops = bs);
+ },
+
+ collapseChars: (s) => s.replace(/\;+/g, ';').replace(/\/{4,}/g, '////')
+ .replace(/\s+/g, (s) => /\n/g.test(s) ? '\n' : ' '),
+
+ _reduceBackslashes: (bs) => bs.length % 2 ? "\\" : "",
+
+ reduceQuotes: function(s) {
+ if (s[0] == '/') {
+ // reduce common leading path fragment resembling a regular expression or a comment
+ s = s.replace(/^\/[^\/\n\r]+\//, '_RX_').replace(/^\/\/[^\r\n]*/, '//_COMMENT_');
+ }
+
+ if (/\/\*/.test(s) || // C-style comments, would make everything really tricky
+ /\w\s*(\/\/[\s\S]*)?\[[\s\S]*\w[\s\S]*\]/.test(s)) { // property accessors, risky
+ return s;
+ }
+
+ if (/['"\/]/.test(s)) {
+
+ // drop noisy backslashes
+ s = s.replace(/\\{2,}/g, this._reduceBackslashes);
+
+ // drop escaped quotes
+ s = s.replace(/\\["'\/]/g, " EQ ");
+ var expr;
+ for(;;) {
+ expr = s.replace(/(^[^'"\/]*[;,\+\-=\(\[]\s*)\/[^\/]+\//g, "$1 _RX_ ")
+ .replace(/(^[^'"\/]*)(["']).*?\2/g, "$1 _QS_ ");
+ if(expr == s) break;
+ s = expr;
+ }
+ }
+
+ // remove c++ style comments
+ return s.replace(/^([^'"`\\]*?)\/\/[^\r\n]*/g, "$1//_COMMENT_");
+ },
+
+ reduceURLs: function(s) {
+ // nested URLs with protocol are parsed as C++ style comments, and since
+ // they're potentially very expensive, we preemptively remove them if possible
+ while (/^[^'"]*?:\/\//.test(s)) {
+ s = s.replace(/:\/\/[^*\s]*/, ':');
+ }
+ s = s.replace(/:\/\/[^'"*\n]*/g, ':');
+
+ return (/\bhttps?:$/.test(s) && !/\bh\W*t\W*t\W*p\W*s?.*=/.test(s))
+ ? s.replace(/\b(?:[\w.]+=)?https?:$/, '')
+ : s;
+ },
+
+ reduceJSON: function(s) {
+ const toStringRx = /^function\s*toString\(\)\s*{\s*\[native code\]\s*\}$/;
+ // optimistic case first, one big JSON block
+ for (;;) {
+
+ let m = s.match(/{[^]+}|\[[^]*{[^]+}[^]*\]/);
+ if (!m) return s;
+
+ let whole = s;
+ let expr = m[0];
+ try {
+ if (toStringRx.test(JSON.parse(expr).toString)) {
+ this.log("Reducing big JSON " + expr);
+ return this.reduceJSON(s.replace(expr, '{}'));
+ }
+ } catch(e) {}
+
+
+ // heavier duty, scattered JSON blocks
+ while((m = s.match(/{[^{}:]+:[^{}]+}/g))) {
+ let prev = s;
+
+ for (expr of m) {
+ try {
+ if (!toStringRx.test(JSON.parse(expr).toString))
+ continue;
+
+ this.log("Reducing JSON " + expr);
+ s = s.replace(expr, '{}');
+ continue;
+ } catch(e) {}
+
+ if (/\btoString\b[\s\S]*:/.test(expr)) continue;
+
+ let qred = this.reduceQuotes(expr);
+ if (/\{(?:\s*(?:(?:\w+:)+\w+)+;\s*)+\}/.test(qred)) {
+ this.log("Reducing pseudo-JSON " + expr);
+ s = s.replace(expr, '{}');
+ } else if (!/[(=.]|[^:\s]\s*\[|:\s*(?:location|document|set(?:Timeout|Interval)|eval|open|show\w*Dialog|alert|confirm|prompt)\b|(?:\]|set)\s*:/.test(qred) &&
+ this.checkJSSyntax("JSON = " + qred) // no-assignment JSON fails with "invalid label"
+ ) {
+ this.log("Reducing slow JSON " + expr);
+ s = s.replace(expr, '{}');
+ }
+ }
+
+ if (s === prev) break;
+ }
+
+ if (s === whole) break;
+ }
+
+ return s;
+ },
+
+ reduceXML: function reduceXML(s) {
+ var res;
+
+ for (let pos = s.indexOf("<"); pos !== -1; pos = s.indexOf("<", 1)) {
+
+ let head = s.substring(0, pos);
+ let tail = s.substring(pos);
+
+ let qnum = 0;
+ for (pos = -1; (pos = head.indexOf('"', ++pos)) > -1; ) {
+ if (pos === 0 || head[pos - 1] != '\\') qnum++;
+ }
+ if (qnum % 2) break; // odd quotes
+
+ let t = tail.replace(/^<(\??\s*\/?[a-zA-Z][\w:-]*)(?:[\s+]+[\w:-]+="[^"]*")*[\s+]*(\/?\??)>/, '<$1$2>');
+
+ (res || (res = [])).push(head);
+ s = t;
+ }
+ if (res) {
+ res.push(s);
+ s = res.join('');
+ }
+
+ return s;
+ }
+,
+
+ _singleAssignmentRx: new RegExp(
+ "(?:\\b" + fuzzify('document') + "\\b[^]*\\.|\\s" + fuzzify('setter') + "\\b[^]*=)|/.*/[^]*(?:\\.(?:" +
+ "\\b" + fuzzify("onerror") + "\\b[^]*=|" +
+ + fuzzify('source|toString') + ")|\\[)|" + IC_EVENT_DOS_PATTERN
+ ),
+ _riskyAssignmentRx: new RegExp(
+ "\\b(?:" + fuzzify('location|innerHTML|outerHTML') + ")\\b[^]*="
+ ),
+ _nameRx: new RegExp(
+ "=[^]*\\b" + fuzzify('name') + "\\b|" +
+ fuzzify("hostname") + "[^]*=[^]*(?:\\b\\d|[\"'{}~^|<*/+-])"
+ ),
+ _evalAliasingRx: new RegExp(
+ "=[^]+\\[" + IC_EVAL_PATTERN + "\\W*\\]" // TODO: check if it can be coalesced into _maybeJSRx
+ ),
+
+ _maybeJSRx: new RegExp(
+ '(?:(?:\\[[^]+\\]|\\.\\D)(?:[^]*\\([^]*\\)|[^*]`[^]+`|[^=]*=[^=][^]*\\S)' +
+ // double function call
+ '|\\([^]*\\([^]*\\)' +
+ ')|(?:^|\\W)(?:' + IC_EVAL_PATTERN +
+ ')(?:\\W+[^]*|)[(`]|(?:[=(]|\\{[^]+:)[^]*(?:' + // calling eval-like functions directly or...
+ IC_EVAL_PATTERN + // ... assigning them to another function possibly called by the victim later
+ ')[^]*[\\n,;:|]|\\b(?:' +
+ fuzzify('setter|location|innerHTML|outerHTML') + // eval-like assignments
+ ')\\b[^]*=|' +
+ '.' + IC_COMMENT_PATTERN + "src" + IC_COMMENT_PATTERN + '=' +
+ IC_EVENT_DOS_PATTERN +
+ "|\\b" + fuzzify("onerror") + "\\b[^]*=" +
+ "|=[s\\\\[ux]?\d{2}" + // escape (unicode/ascii/octal)
+ "|\\b(?:toString|valueOf)\\b" + IC_COMMENT_PATTERN + "=[^]*(?:" + IC_EVAL_PATTERN + ")" +
+ "|(?:\\)|(?:[^\\w$]|^)[$a-zA-Z_\\u0ff-\\uffff][$\\w\\u0ff-\\uffff]*)" + IC_COMMENT_PATTERN + '=>' + // concise function definition
+ "|(?:[^\\w$]|^)" + IC_EVENT_PATTERN + IC_COMMENT_PATTERN + "="
+ )
+ ,
+
+ _riskyParensRx: new RegExp(
+ "(?:^|\\W)(?:(?:" + IC_EVAL_PATTERN + "|on\\w+)\\s*[(`]|" +
+ fuzzify("with") + "\\b[^]*\\(|" +
+ fuzzify("for") + "\\b[^]*\\([^]*[\\w$\\u0080-\\uffff]+[^]*\\b(?:" +
+ fuzzify ("in|of") + ")\\b)"
+ ),
+
+ _dotRx: /\./g,
+ _removeDotsRx: /^openid\.[\w.-]+(?==)|(?:[?&#\/]|^)[\w.-]+(?=[\/\?&#]|$)|[\w\.]*\.(?:\b[A-Z]+|\w*\d|[a-z][$_])[\w.-]*|=[a-z.-]+\.(?:com|net|org|biz|info|xxx|[a-z]{2})(?:[;&/]|$)/g,
+ _removeDots: (p) => p.replace(InjectionChecker._dotRx, '|'),
+ _arrayAccessRx: /\s*\[\d+\]/g,
+ _riskyOperatorsRx: /[+-]{2}\s*(?:\/[*/][\s\S]+)?(?:\w+(?:\/[*/][\s\S]+)?[[.]|location)|(?:\]|\.\s*(?:\/[*/][\s\S]+)?\w+|location)\s*(?:\/[*/][\s\S]+)?([+-]{2}|[+*\/<>~-]+\s*(?:\/[*/][\s\S]+)?=)/, // inc/dec/self-modifying assignments on DOM props
+ _assignmentRx: /^(?:[^()="'\s]+=(?:[^(='"\[+]+|[?a-zA-Z_0-9;,&=/]+|[\d.|]+))$/,
+ _badRightHandRx: /=[\s\S]*(?:_QS_\b|[|.][\s\S]*source\b|<[\s\S]*\/[^>]*>)/,
+ _wikiParensRx: /^(?:[\w.|-]+\/)*\(*[\w\s-]+\([\w\s-]+\)[\w\s-]*\)*$/,
+ _neutralDotsRx: /(?:^|[\/;&#])[\w-]+\.[\w-]+[\?;\&#]/g,
+ _openIdRx: /^scope=(?:\w+\+)\w/, // OpenID authentication scope parameter, see http://forums.informaction.com/viewtopic.php?p=69851#p69851
+ _gmxRx: /\$\(clientName\)-\$\(dataCenter\)\.(\w+\.)+\w+/, // GMX webmail, see http://forums.informaction.com/viewtopic.php?p=69700#p69700
+
+ maybeJS(expr, mavoChecked = false) {
+ if (!mavoChecked && this.maybeMavo(expr)) return true;
+
+ if (/`[\s\S]*`/.test(expr) || // ES6 templates, extremely insidious!!!
+ this._evalAliasingRx.test(expr) ||
+ this._riskyOperatorsRx.test(expr) // this must be checked before removing dots...
+ ) return true;
+
+ expr = // dotted URL components can lead to false positives, let's remove them
+ expr.replace(this._removeDotsRx, this._removeDots)
+ .replace(this._arrayAccessRx, '_ARRAY_ACCESS_')
+ .replace(/<([\w:]+)>[^</(="'`]+<\/\1>/g, '<$1/>') // reduce XML text nodes
+ .replace(/<!--/g, '') // remove HTML comments preamble (see next line)
+ .replace(/(^(?:[^/]*[=;.+-])?)\s*[\[(]+/g, '$1') // remove leading parens and braces
+ .replace(this._openIdRx, '_OPENID_SCOPE_=XYZ')
+ .replace(/^[^=]*OPENid\.(\w+)=/gi, "OPENid_\1")
+ .replace(this._gmxRx, '_GMX_-_GMX_')
+ ;
+
+ if (expr.indexOf(")") !== -1) expr += ")"; // account for externally balanced parens
+ if(this._assignmentRx.test(expr) && !this._badRightHandRx.test(expr)) // commonest case, single assignment or simple chained assignments, no break
+ return this._singleAssignmentRx.test(expr) || this._riskyAssignmentRx.test(expr) && this._nameRx.test(expr);
+
+ return this._riskyParensRx.test(expr) ||
+ this._maybeJSRx.test(expr.replace(this._neutralDotsRx, '')) &&
+ !this._wikiParensRx.test(expr);
+
+ },
+
+ checkNonTrivialJSSyntax: function(expr) {
+ return this.maybeJS(this.reduceQuotes(expr)) && this.checkJSSyntax(expr);
+ },
+
+
+ wantsExpression: (s) => /(?:^[+-]|[!%&(,*/:;<=>?\[^|]|[^-]-|[^+]\+)\s*$/.test(s),
+
+ stripLiteralsAndComments: function(s) {
+ "use strict";
+
+ const MODE_NORMAL = 0;
+ const MODE_REGEX = 1;
+ const MODE_SINGLEQUOTE = 2;
+ const MODE_DOUBLEQUOTE = 3;
+ const MODE_BLOCKCOMMENT = 4;
+ const MODE_LINECOMMENT = 6;
+ const MODE_INTERPOLATION = 7;
+
+ let mode = MODE_NORMAL;
+ let escape = false;
+ let res = [];
+ function handleQuotes(c, q, type) {
+ if (escape) {
+ escape = false;
+ } else if (c == '\\') {
+ escape = true;
+ } else if (c === q) {
+ res.push(type);
+ mode = MODE_NORMAL;
+ }
+ }
+ for (let j = 0, l = s.length; j < l; j++) {
+
+ switch(mode) {
+ case MODE_REGEX:
+ handleQuotes(s[j], '/', "_REGEXP_");
+ break;
+ case MODE_SINGLEQUOTE:
+ handleQuotes(s[j], "'", "_QS_");
+ break;
+ case MODE_DOUBLEQUOTE:
+ handleQuotes(s[j], '"', "_DQS_");
+ break;
+ case MODE_INTERPOLATION:
+ handleQuotes(s[j], '`', "``");
+ break;
+ case MODE_BLOCKCOMMENT:
+ if (s[j] === '/' && s[j-1] === '*') {
+ res.push("/**/");
+ mode = MODE_NORMAL;
+ }
+ break;
+ case MODE_LINECOMMENT:
+ if (s[j] === '\n') {
+ res.push("//\n");
+ mode = MODE_NORMAL;
+ }
+ break;
+ default:
+ switch(s[j]) {
+ case '"':
+ mode = MODE_DOUBLEQUOTE;
+ break;
+ case "'":
+ mode = MODE_SINGLEQUOTE;
+ break;
+ case "`":
+ mode = MODE_INTERPOLATION;
+ break;
+ case '/':
+ switch(s[j+1]) {
+ case '*':
+ mode = MODE_BLOCKCOMMENT;
+ j+=2;
+ break;
+ case '/':
+ mode = MODE_LINECOMMENT;
+ break;
+ default:
+ let r = res.join('');
+ res = [r];
+ if (this.wantsExpression(r)) mode = MODE_REGEX;
+ else res.push('/'); // after a self-contained expression: division operator
+ }
+ break;
+ default:
+ res.push(s[j]);
+ }
+
+ }
+ }
+ return res.join('');
+ },
+
+ checkLastFunction: function() {
+ var fn = this.syntax.lastFunction;
+ if (!fn) return false;
+ var m = fn.toSource().match(/\{([\s\S]*)\}/);
+ if (!m) return false;
+ var expr = this.stripLiteralsAndComments(m[1]);
+ return /=[\s\S]*cookie|\b(?:setter|document|location|(?:inn|out)erHTML|\.\W*src)[\s\S]*=|[\w$\u0080-\uffff\)\]]\s*[\[\(]/.test(expr) ||
+ this.maybeJS(expr);
+ },
+
+ _createInvalidRanges: function() {
+ function x(n) { return '\\u' + ("0000" + n.toString(16)).slice(-4); }
+
+ var ret = "";
+ var first = -1;
+ var last = -1;
+ var cur = 0x7e;
+ while(cur++ <= 0xffff) {
+ try {
+ eval("var _" + String.fromCharCode(cur) + "_=1");
+ } catch(e) {
+ if (!/illegal char/.test(e.message)) continue;
+ if (first == -1) {
+ first = last = cur;
+ ret += x(cur);
+ continue;
+ }
+ if (cur - last == 1) {
+ last = cur;
+ continue;
+ }
+
+ if(last != first) ret += "-" + x(last);
+ ret+= x(cur);
+ last = first = cur;
+ }
+ }
+ return ret;
+ },
+
+ get invalidCharsRx() {
+ delete this.invalidCharsRx;
+ return this.invalidCharsRx = new RegExp("^[^\"'`/<>]*[" + this._createInvalidRanges() + "]");
+ },
+
+ checkJSBreak: function InjectionChecker_checkJSBreak(s) {
+ // Direct script injection breaking JS string literals or comments
+
+
+ // cleanup most urlencoded noise and reduce JSON/XML
+ s = ';' + this.reduceXML(this.reduceJSON(this.collapseChars(
+ s.replace(/\%\d+[a-z\(]\w*/gi, '§')
+ .replace(/[\r\n\u2028\u2029]+/g, "\n")
+ .replace(/[\x01-\x09\x0b-\x20]+/g, ' ')
+ )));
+
+ if (s.indexOf("*/") > 0 && /\*\/[\s\S]+\/\*/.test(s)) { // possible scrambled multi-point with comment balancing
+ s += ';' + s.match(/\*\/[\s\S]+/);
+ }
+
+ if (!this.maybeJS(s)) return false;
+
+ const MAX_TIME = 8000, MAX_LOOPS = 1200;
+
+ const logEnabled = this.logEnabled;
+
+ const
+ invalidCharsRx = /[\u007f-\uffff]/.test(s) && this.invalidCharsRx,
+ dangerRx = /\(|(?:^|[+-]{2}|[+*/<>~-]+\\s*=)|`[\s\S]*`|\[[^\]]+\]|(?:setter|location|(?:inn|out)erHTML|cookie|on\w{3,}|\.\D)[^&]*=[\s\S]*?(?:\/\/|[\w$\u0080-\uFFFF.[\]})'"-]+)/,
+ exprMatchRx = /^[\s\S]*?(?:[=\)]|`[\s\S]*`|[+-]{2}|[+*/<>~-]+\\s*=)/,
+ safeCgiRx = /^(?:(?:[\.\?\w\-\/&:§\[\]]+=[\w \-:\+%#,§\.]*(?:[&\|](?=[^&\|])|$)){2,}|\w+:\/\/\w[\w\-\.]*)/,
+ // r2l, chained query string parameters, protocol://domain
+ headRx = /^(?:[^'"\/\[\(]*[\]\)]|[^"'\/]*(?:§|[^&]&[\w\.]+=[^=]))/
+ // irrepairable syntax error, such as closed parens in the beginning
+ ;
+
+ const injectionFinderRx = /(['"`#;>:{}]|[/?=](?![?&=])|&(?![\w-.[\]&!-]*=)|\*\/)(?!\1)/g;
+ injectionFinderRx.lastIndex = 0;
+
+ const t = Date.now();
+ var iterations = 0;
+
+ for (let dangerPos = 0, m; (m = injectionFinderRx.exec(s));) {
+
+ let startPos = injectionFinderRx.lastIndex;
+ let subj = s.substring(startPos);
+ if (startPos > dangerPos) {
+ dangerRx.lastIndex = startPos;
+ if (!dangerRx.exec(s)) {
+ this.log("Can't find any danger in " + s);
+ return false;
+ }
+ dangerPos = dangerRx.lastIndex;
+ }
+
+ let breakSeq = m[1];
+ let quote = breakSeq in this.breakStops ? breakSeq : '';
+
+ if (!this.maybeJS(quote ? quote + subj : subj)) {
+ this.log("Fast escape on " + subj, t, iterations);
+ return false;
+ }
+
+ let script = this.reduceURLs(subj);
+
+ if (script.length < subj.length) {
+ if (!this.maybeJS(script)) {
+ this.log("Skipping to first nested URL in " + subj, t, iterations);
+ injectionFinderRx.lastIndex += subj.indexOf("://") + 1;
+ continue;
+ }
+ subj = script;
+ script = this.reduceURLs(subj.substring(0, dangerPos - startPos));
+ } else {
+ script = subj.substring(0, dangerPos - startPos);
+ }
+
+ let expr = subj.match(exprMatchRx);
+
+ if (expr) {
+ expr = expr[0];
+ if (expr.length < script.length) {
+ expr = script;
+ }
+ } else {
+ expr = script;
+ }
+
+ // quickly skip (mis)leading innocuous CGI patterns
+ if ((m = subj.match(safeCgiRx))) {
+
+ this.log("Skipping CGI pattern in " + subj);
+
+ injectionFinderRx.lastIndex += m[0].length - 1;
+ continue;
+ }
+
+ let bs = this.breakStops[quote || 'nq']
+
+ for (let len = expr.length, moved = false, hunt = !!expr, lastExpr = ''; hunt;) {
+
+ if (Date.now() - t > MAX_TIME) {
+ this.log("Too long execution time! Assuming DOS... " + (Date.now() - t), t, iterations);
+ return true;
+ }
+
+ hunt = expr.length < subj.length;
+
+ if (moved) {
+ moved = false;
+ } else if (hunt) {
+ let pos = subj.substring(len).search(bs);
+ if (pos < 0) {
+ expr = subj;
+ hunt = false;
+ } else {
+ len += pos;
+ if (quote && subj[len] === quote) {
+ len++;
+ } else if (subj[len - 1] === '<') {
+ // invalid JS, and maybe in the middle of XML block
+ len++;
+ continue;
+ }
+ expr = subj.substring(0, len);
+ if (pos === 0) len++;
+ }
+ }
+
+ if(lastExpr === expr) {
+ lastExpr = '';
+ continue;
+ }
+
+ lastExpr = expr;
+
+ if(invalidCharsRx && invalidCharsRx.test(expr)) {
+ this.log("Quick skipping invalid chars");
+ break;
+ }
+
+
+
+ if (quote) {
+ if (this.checkNonTrivialJSSyntax(expr)) {
+ this.log("Non-trivial JS inside quoted string detected", t, iterations);
+ return true;
+ }
+ script = this.syntax.unquote(quote + expr, quote);
+ if(script && this.maybeJS(script) &&
+ (this.checkNonTrivialJSSyntax(script) ||
+ /'./.test(script) && this.checkNonTrivialJSSyntax("''" + script + "'") ||
+ /"./.test(script) && this.checkNonTrivialJSSyntax('""' + script + '"')
+ ) && this.checkLastFunction()
+ ) {
+ this.log("JS quote Break Injection detected", t, iterations);
+ return true;
+ }
+ script = quote + quote + expr + quote;
+ } else {
+ script = expr;
+ }
+
+ if (headRx.test(script.split("//")[0])) {
+ let balanced = script.replace(/^[^"'{}(]*\)/, 'P ');
+ if (balanced !== script && balanced.indexOf('(') > -1) {
+ script = balanced + ")";
+ } else {
+ this.log("SKIP (head syntax) " + script, t, iterations);
+ break; // unrepairable syntax error in the head, move left cursor forward
+ }
+ }
+
+ if (this.maybeJS(this.reduceQuotes(script))) {
+
+ if (this.checkJSSyntax(script) && this.checkLastFunction()) {
+ this.log("JS Break Injection detected", t, iterations);
+ return true;
+ }
+
+ if (this.checkTemplates(script)) {
+ this.log("JS template expression injection detected", t, iterations);
+ return true;
+ }
+
+ if (++iterations > MAX_LOOPS) {
+ this.log("Too many syntax checks! Assuming DOS... " + s, t, iterations);
+ return true;
+ }
+ if(this.syntax.lastError) { // could be null if we're here thanks to checkLastFunction()
+ let errmsg = this.syntax.lastError.message;
+ if (logEnabled) this.log(errmsg + " --- " + this.syntax.sandbox.script + " --- ", t, iterations);
+ if(!quote) {
+ if (errmsg.indexOf("left-hand") !== -1) {
+ let m = subj.match(/^([^\]\(\\'"=\?]+?)[\w$\u0080-\uffff\s]+[=\?]/);
+ if (m) {
+ injectionFinderRx.lastIndex += m[1].length - 1;
+ }
+ break;
+ } else if (errmsg.indexOf("unterminated string literal") !== -1) {
+ let quotePos = subj.substring(len).search(/["']/);
+ if(quotePos > -1) {
+ expr = subj.substring(0, len += ++quotePos);
+ moved = true;
+ } else break;
+ } else if (errmsg.indexOf("syntax error") !== -1) {
+ let dblSlashPos = subj.indexOf("//");
+ if (dblSlashPos > -1) {
+ let pos = subj.search(/['"\n\\\(]|\/\*/);
+ if (pos < 0 || pos > dblSlashPos)
+ break;
+ }
+ if (/^([\w\[\]]*=)?\w*&[\w\[\]]*=/.test(subj)) { // CGI param concatenation
+ break;
+ }
+ }
+ } else if (errmsg.indexOf("left-hand") !== -1) break;
+
+ if (/invalid .*\bflag\b|missing ; before statement|invalid label|illegal character|identifier starts immediately/.test(errmsg)) {
+ if (errmsg.indexOf("illegal character") === -1 && /#\d*\s*$/.test(script)) { // sharp vars exceptional behavior
+ if (!quote) break;
+ // let's retry without quotes
+ quote = lastExpr = '';
+ hunt = moved = true;
+ } else break;
+ }
+ else if((m = errmsg.match(/\b(?:property id\b|missing ([:\]\)\}]) )/))) {
+ let char = m[1] || '}';
+ let newLen = subj.indexOf(char, len);
+ let nextParamPos = subj.substring(len).search(/[^&]&(?!&)/)
+ if (newLen !== -1 && (nextParamPos === -1 || newLen <= len + nextParamPos)) {
+ this.log("Extending to next " + char);
+ expr = subj.substring(0, len = ++newLen);
+ moved = char !== ':';
+ } else if (char !== ':') {
+ let lastChar = expr[expr.length - 1];
+ if (lastChar === char && (len > subj.length || lastChar != subj[len - 1])) break;
+ expr += char;
+ moved = hunt = true;
+ len++;
+ this.log("Balancing " + char, t, iterations);
+ } else {
+ break;
+ }
+ }
+ else if (/finally without try/.test(errmsg)) {
+ expr = "try{" + expr;
+ hunt = moved = true;
+ }
+ }
+ }
+ }
+ }
+ this.log(s, t, iterations);
+ return false;
+ },
+
+
+ checkJS: function(s, unescapedUni) {
+ this.log(s);
+
+ if (/\?name\b[\s\S]*:|[^&?]\bname\b/.test(s)) {
+ this.nameAssignment = true;
+ }
+
+ var hasUnicodeEscapes = !unescapedUni && /\\u(?:[0-9a-f]{4}|\{[0-9a-f]+\})/i.test(s);
+ if (hasUnicodeEscapes && /\\u(?:\{0*|00)[0-7][0-9a-f]/i.test(s)) {
+ this.escalate("Unicode-escaped lower ASCII");
+ return true;
+ }
+
+ if (/\\x[0-9a-f]{2}[\s\S]*['"]/i.test(s)) {
+ this.escalate("Obfuscated string literal");
+ return true;
+ }
+
+ if (/`[\s\S]*\$\{[\s\S]+[=(][\s\S]+\}[\s\S]*`/.test(s)) {
+ this.escalate("ES6 string interpolation");
+ return true;
+ }
+
+ this.syntax.lastFunction = null;
+ let ret = this.checkAttributes(s) ||
+ (/[\\\(]|=[^=]/.test(s) || this._riskyOperatorsRx.test(s)) && this.checkJSBreak(s) || // MAIN
+ hasUnicodeEscapes && this.checkJS(this.unescapeJS(s), true); // optional unescaped recursion
+ if (ret) {
+ let msg = "JavaScript Injection in " + s;
+ if (this.syntax.lastFunction) {
+ msg += "\n" + this.syntax.lastFunction.toSource();
+ }
+ this.escalate(msg);
+ }
+ return ret;
+ },
+
+ unescapeJS: function(s) {
+ return s.replace(/\\u([0-9a-f]{4})/gi, function(s, c) {
+ return String.fromCharCode(parseInt(c, 16));
+ });
+ },
+ unescapeJSLiteral: function(s) {
+ return s.replace(/\\x([0-9a-f]{2})/gi, function(s, c) {
+ return String.fromCharCode(parseInt(c, 16));
+ });
+ },
+
+ unescapeCSS: function(s) {
+ // see http://www.w3.org/TR/CSS21/syndata.html#characters
+ return s.replace(/\\([\da-f]{0,6})\s?/gi, function($0, $1) {
+ try {
+ return String.fromCharCode(parseInt($1, 16));
+ } catch(e) {
+ return "";
+ }
+ });
+ },
+
+ reduceDashPlus: function(s) {
+ // http://forums.mozillazine.org/viewtopic.php?p=5592865#p5592865
+ return s.replace(/\-+/g, "-")
+ .replace(/\++/g, "+")
+ .replace(/\s+/g, ' ')
+ .replace(/(?: \-)+/g, ' -')
+ .replace(/(?:\+\-)+/g, '+-');
+ },
+
+ _rxCheck: function(checker, s) {
+ var rx = this[checker + "Checker"];
+ var ret = rx.exec(s);
+ if (ret) {
+ this.escalate(checker + " injection:\n" + ret + "\nmatches " + rx.source);
+ return true;
+ }
+ return false;
+ },
+
+ AttributesChecker: new RegExp(
+ "(?:\\W|^)(?:javascript:(?:[^]+[=\\\\\\(`\\[\\.<]|[^]*(?:\\bname\\b|\\\\[ux]\\d))|" +
+ "data:(?:(?:[a-z]\\w+/\\w[\\w+-]+\\w)?[;,]|[^]*;[^]*\\b(?:base64|charset=)|[^]*,[^]*<[^]*\\w[^]*>))|@" +
+ ("import\\W*(?:\\/\\*[^]*)?(?:[\"']|url[^]*\\()" +
+ "|-moz-binding[^]*:[^]*url[^]*\\(|\\{\\{[^]+\\}\\}")
+ .replace(/[a-rt-z\-]/g, "\\W*$&"),
+ "i"),
+ checkAttributes: function(s) {
+ s = this.reduceDashPlus(s);
+ if (this._rxCheck("Attributes", s)) return true;
+ if (/\\/.test(s) && this._rxCheck("Attributes", this.unescapeCSS(s))) return true;
+ let dataPos = s.search(/data:\S*\s/i);
+ if (dataPos !== -1) {
+ let data = this.urlUnescape(s.substring(dataPos).replace(/\s/g, ''));
+ if (this.checkHTML(data) || this.checkAttributes(data)) return true;
+ }
+ return false;
+ },
+
+ GlobalsChecker: /https?:\/\/[\S\s]+["'\s\0](?:id|class|data-\w+)[\s\0]*=[\s\0]*("')?\w{3,}(?:[\s\0]|\1|$)|(?:id|class|data-\w+)[\s\0]*=[\s\0]*("')?\w{3,}(?:[\s\0]|\1)[\s\S]*["'\s\0]href[\s\0]*=[\s\0]*(?:"')?https?:\/\//i
+ ,
+ HTMLChecker: new RegExp("<[^\\w<>]*(?:[^<>\"'\\s]*:)?[^\\w<>]*(?:" + // take in account quirks and namespaces
+ fuzzify("script|form|style|svg|marquee|(?:link|object|embed|applet|param|i?frame|base|body|meta|ima?ge?|video|audio|bindings|set|isindex|animate|template") +
+ ")[^>\\w])|['\"\\s\\0/](?:formaction|style|background|src|lowsrc|ping|innerhtml|data-bind|(?:data-)?mv-(?:\\w+[\\w-]*)|" + IC_EVENT_PATTERN +
+ ")[\\s\\0]*=|<%[^]+[=(][^]+%>", "i"),
+
+ checkHTML(s) {
+ let links = s.match(/\b(?:href|src|base|(?:form)?action|\w+-\w+)\s*=\s*(?:(["'])[\s\S]*?\1|(?:[^'">][^>\s]*)?[:?\/#][^>\s]*)/ig);
+ if (links) {
+ for (let l of links) {
+ l = l.replace(/[^=]*=\s*/i, '').replace(/[\u0000-\u001f]/g, '');
+ l = /^["']/.test(l) ? l.replace(/^(['"])([^]*?)\1[^]*/g, '$2') : l.replace(/[\s>][^]*/, '');
+
+ if (/^(?:javascript|data):|\[[^]+\]/i.test(l) || /[<'"(]/.test(unescape(l)) && this.checkURL(l)) return true;
+ }
+ }
+ return this._rxCheck("HTML", s) || this._rxCheck("Globals", s);
+ },
+
+ checkNoscript: function(s) {
+ this.log(s);
+ return s.indexOf("\x1b(J") !== -1 && this.checkNoscript(s.replace(/\x1b\(J/g, '')) || // ignored in iso-2022-jp
+ s.indexOf("\x7e\x0a") !== -1 && this.checkNoscript(s.replace(/\x7e\x0a/g, '')) || // ignored in hz-gb-2312
+ this.checkHTML(s) || this.checkSQLI(s) || this.checkHeaders(s);
+ },
+
+ HeadersChecker: /[\r\n]\s*(?:content-(?:type|encoding))\s*:/i,
+ checkHeaders: function(s) { return this._rxCheck("Headers", s); },
+ SQLIChecker: /(?:(?:(?:\b|[^a-z])union[^a-z]|\()[\w\W]*(?:\b|[^a-z])select[^a-z]|(?:updatexml|extractvalue)(?:\b|[^a-z])[\w\W]*\()[\w\W]+(?:(?:0x|x')[0-9a-f]{16}|(?:0b|b')[01]{64}|\(|\|\||\+)/i
+ ,
+ checkSQLI: function(s) { return this._rxCheck("SQLI", s); },
+
+ base64: false,
+ base64tested: [],
+ get base64Decoder() { return Base64; }, // exposed here just for debugging purposes
+
+
+ checkBase64: function(url) {
+ this.base64 = false;
+
+ const MAX_TIME = 8000;
+ const DOS_MSG = "Too long execution time, assuming DOS in Base64 checks";
+
+ this.log(url);
+
+
+ var parts = url.split("#"); // check hash
+ if (parts.length > 1 && this.checkBase64FragEx(unescape(parts[1])))
+ return true;
+
+ parts = parts[0].split(/[&;]/); // check query string
+ if (parts.length > 0 && parts.some(function(p) {
+ var pos = p.indexOf("=");
+ if (pos > -1) p = p.substring(pos + 1);
+ return this.checkBase64FragEx(unescape(p));
+ }, this))
+ return true;
+
+ url = parts[0];
+ parts = Base64.purify(url).split("/");
+ if (parts.length > 255) {
+ this.log("More than 255 base64 slash chunks, assuming DOS");
+ return true;
+ }
+
+
+ var t = Date.now();
+ if (parts.some(function(p) {
+ if (Date.now() - t > MAX_TIME) {
+ this.log(DOS_MSG);
+ return true;
+ }
+ return this.checkBase64Frag(Base64.purify(Base64.alt(p)));
+ }, this))
+ return true;
+
+
+ var uparts = Base64.purify(unescape(url)).split("/");
+
+ t = Date.now();
+ while(parts.length) {
+ if (Date.now() - t > MAX_TIME) {
+ this.log(DOS_MSG);
+ return true;
+ }
+ if (this.checkBase64Frag(parts.join("/")) ||
+ this.checkBase64Frag(uparts.join("/")))
+ return true;
+
+ parts.shift();
+ uparts.shift();
+ }
+
+ return false;
+ },
+
+
+ checkBase64Frag: function(f) {
+ if (this.base64tested.indexOf(f) < 0) {
+ this.base64tested.push(f);
+ try {
+ var s = Base64.decode(f);
+ if(s && s.replace(/[^\w\(\)]/g, '').length > 7 &&
+ (this.checkHTML(s) ||
+ this.checkAttributes(s))
+ // this.checkJS(s) // -- alternate, whose usefulness is doubious but which easily leads to DOS
+ ) {
+ this.log("Detected BASE64 encoded injection: " + f + " --- (" + s + ")");
+ return this.base64 = true;
+ }
+ } catch(e) {}
+ }
+ return false;
+ },
+
+ checkBase64FragEx: function(f) {
+ return this.checkBase64Frag(Base64.purify(f)) || this.checkBase64Frag(Base64.purify(Base64.alt(f)));
+ },
+
+
+ checkURL: function(url) {
+ return this.checkRecursive(url
+ // assume protocol and host are safe, but keep the leading double slash to keep comments in account
+ .replace(/^[a-z]+:\/\/.*?(?=\/|$)/, "//")
+ // Remove outer parenses from ASP.NET cookieless session's AppPathModifier
+ .replace(/\/\((S\(\w{24}\))\)\//, '/$1/')
+ );
+ },
+
+ checkRecursive: function(s, depth, isPost) {
+ if (typeof(depth) != "number")
+ depth = 3;
+
+ this.reset();
+ this.isPost = isPost || false;
+
+ if (ASPIdiocy.affects(s)) {
+ if (this.checkRecursive(ASPIdiocy.process(s), depth, isPost))
+ return true;
+ } else if (ASPIdiocy.hasBadPercents(s) && this.checkRecursive(ASPIdiocy.removeBadPercents(s), depth, isPost))
+ return true;
+
+ if (FlashIdiocy.affects(s)) {
+ let purged = FlashIdiocy.purgeBadEncodings(s);
+ if (purged !== s && this.checkRecursive(purged, depth, isPost))
+ return true;
+ let decoded = FlashIdiocy.platformDecode(purged);
+ if (decoded !== purged && this.checkRecursive(decoded, depth, isPost))
+ return true;
+ }
+
+ if (s.indexOf("coalesced:") !== 0) {
+ let coalesced = ASPIdiocy.coalesceQuery(s);
+ if (coalesced !== s && this.checkRecursive("coalesced:" + coalesced, depth, isPost))
+ return true;
+ }
+
+ if (isPost) {
+ s = this.formUnescape(s);
+ if (this.checkBase64Frag(Base64.purify(s))) return true;
+
+ if (s.indexOf("<") > -1) {
+ // remove XML-embedded Base64 binary data
+ s = s.replace(/<((?:\w+:)?\w+)>[0-9a-zA-Z+\/]+=*<\/\1>/g, '');
+ }
+
+ s = "#" + s;
+ } else {
+ if (this.checkBase64(s.replace(/^\/{1,3}/, ''))) return true;
+ }
+
+ if (isPost) s = "#" + s; // allows the string to be JS-checked as a whole
+ return this._checkRecursive(s, depth);
+ },
+
+ _checkRecursive: function(s, depth) {
+
+ if (this.checkHTML(s) || this.checkJS(s) || this.checkSQLI(s) || this.checkHeaders(s))
+ return true;
+
+ if (s.indexOf("&") !== -1) {
+ let unent = Entities.convertAll(s);
+ if (unent !== s && this._checkRecursive(unent, depth)) return true;
+ }
+
+ if (--depth <= 0)
+ return false;
+
+ if (s.indexOf('+') !== -1 && this._checkRecursive(this.formUnescape(s), depth))
+ return true;
+
+ var unescaped = this.urlUnescape(s);
+ let badUTF8 = this.utf8EscapeError;
+
+ if (this._checkOverDecoding(s, unescaped))
+ return true;
+
+ if (/[\u0000-\u001f]|&#/.test(unescaped)) {
+ let unent = Entities.convertAll(unescaped).replace(/[\u0000-\u001f]+/g, '');
+ if (unescaped != unent && this._checkRecursive(unent, depth)) {
+ this.log("Trash-stripped nested URL match!");
+ return true;
+ }
+ }
+
+ if (/\\x[0-9a-f]/i.test(unescaped)) {
+ let literal = this.unescapeJSLiteral(unescaped);
+ if (unescaped !== literal && this._checkRecursive(literal, depth)) {
+ this.log("Escaped literal match!");
+ return true;
+ }
+ }
+
+ if (unescaped.indexOf("\x1b(J") !== -1 && this._checkRecursive(unescaped.replace(/\x1b\(J/g, ''), depth) || // ignored in iso-2022-jp
+ unescaped.indexOf("\x7e\x0a") !== -1 && this._checkRecursive(unescaped.replace(/\x7e\x0a/g, '')) // ignored in hz-gb-2312
+ )
+ return true;
+
+ if (badUTF8) {
+ try {
+ let legacyEscaped = unescape(unescaped);
+ if (legacyEscaped !== unescaped && this._checkRecursive(unescape(unescaped))) return true;
+ } catch (e) {}
+ }
+
+ if (unescaped !== s && this._checkRecursive(unescaped, depth)) {
+ return true;
+ }
+
+ s = this.ebayUnescape(unescaped);
+ if (s != unescaped && this._checkRecursive(s, depth))
+ return true;
+
+ return false;
+ },
+
+ _checkOverDecoding: function(s, unescaped) {
+ if (/%[8-9a-f]/i.test(s)) {
+ const rx = /[<'"]/g;
+ var m1 = unescape(this.utf8OverDecode(s, false)).match(rx);
+ if (m1) {
+ unescaped = unescaped || this.urlUnescape(s);
+ var m0 = unescaped.match(rx);
+ if (!m0 || m0.length < m1.length) {
+ this.log("Potential utf8_decode() exploit!");
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+
+ utf8OverDecode: function(url, strict) {
+ return url.replace(strict
+ ? /%(?:f0%80%80|e0%80|c0)%[8-b][0-f]/gi
+ : /%(?:f[a-f0-9](?:%[0-9a-f]0){2}|e0%[4-9a-f]0|c[01])%[a-f0-9]{2}/gi,
+ function(m) {
+ var hex = m.replace(/%/g, '');
+ if (strict) {
+ for (var j = 2; j < hex.length; j += 2) {
+ if ((parseInt(hex.substring(j, j + 2), 16) & 0xc0) != 0x80) return m;
+ }
+ }
+ switch (hex.length) {
+ case 8:
+ hex = hex.substring(2);
+ case 6:
+ c = (parseInt(hex.substring(0, 2), 16) & 0x3f) << 12 |
+ (parseInt(hex.substring(2, 4), 16) & 0x3f) << 6 |
+ parseInt(hex.substring(4, 6), 16) & 0x3f;
+ break;
+ default:
+ c = (parseInt(hex.substring(0, 2), 16) & 0x3f) << 6 |
+ parseInt(hex.substring(2, 4), 16) & 0x3f;
+ }
+ return encodeURIComponent(String.fromCharCode(c & 0x3f));
+ }
+ );
+ },
+
+ toUnicode: function(s, charset) {
+ let sis = Cc["@mozilla.org/io/string-input-stream;1"]
+ .createInstance(Ci.nsIStringInputStream);
+ sis.setData(s, s.length);
+ let is = Cc["@mozilla.org/intl/converter-input-stream;1"]
+ .createInstance(Ci.nsIConverterInputStream);
+ is.init(sis, charset || null, 0, is.DEFAULT_REPLACEMENT_CHARACTER);
+ let str = {};
+ if (is.readString(4096, str) === 0) return str.value;
+ let ret = [str.value];
+ while (is.readString(4096, str) !== 0) {
+ ret.push(str.value);
+ }
+ return ret.join('');
+ },
+
+ utf8EscapeError: true,
+ urlUnescape: function(url, brutal) {
+ var od = this.utf8OverDecode(url, !brutal);
+ this.utf8EscapeError = false;
+ try {
+ return decodeURIComponent(od);
+ } catch(warn) {
+ this.utf8EscapeError = true;
+ if (url != od) url += " (" + od + ")";
+ this.log("Problem decoding " + url + ", maybe not an UTF-8 encoding? " + warn.message);
+ return unescape(brutal ? ASPIdiocy.filter(od) : od);
+ }
+ },
+
+ formUnescape: function(s, brutal) {
+ return this.urlUnescape(s.replace(/\+/g, ' '), brutal);
+ },
+
+ aspUnescape: function(s) {
+ return unescape(ASPIdiocy.filter(s).replace(/\+/g, ' '));
+ },
+
+ ebayUnescape: function(url) {
+ return url.replace(/Q([\da-fA-F]{2})/g, function(s, c) {
+ return String.fromCharCode(parseInt(c, 16));
+ });
+ },
+
+ checkPost: function(channel, skip) {
+ if (!((channel instanceof Ci.nsIUploadChannel)
+ && channel.uploadStream && (channel.uploadStream instanceof Ci.nsISeekableStream)))
+ return false;
+
+ var clen = -1;
+ try {
+ clen = channel.getRequestHeader("Content-length");
+ } catch(e) {}
+ MaxRunTime.increase(clen < 0 || clen > 300000 ? 60 : Math.ceil(20 * clen / 100000));
+
+ this.log("Extracting post data...");
+ return this.checkPostStream(channel.URI.spec, channel.uploadStream, skip);
+ },
+
+ checkPostStream: function(url, stream, skip) {
+ var ic = this;
+ var pc = new PostChecker(url, stream, skip);
+ return pc.check(
+ function(chunk) {
+ return chunk.length > 6 &&
+ ic.checkRecursive(chunk, 2, !pc.isFile) && chunk;
+ }
+ );
+ },
+
+ testCheckPost: function(url, strData) {
+ var stream = Cc["@mozilla.org/io/string-input-stream;1"].
+ createInstance(Ci.nsIStringInputStream);
+ stream.setData(strData, strData.length);
+ return this.checkPostStream(url, stream);
+ },
+
+
+ checkWindowName: function (window, url) {
+ var originalAttempt = window.name;
+ try {
+ if (/^https?:\/\/(?:[^/]*\.)?\byimg\.com\/rq\/darla\//.test(url) &&
+ ns.getPref("filterXExceptions.darla_name")) {
+ window.name = "DARLA_JUNK";
+ return;
+ }
+
+ if (/\s*{[\s\S]+}\s*/.test(originalAttempt)) {
+ try {
+ JSON.parse(originalAttempt); // fast track for crazy JSON in name like on NYT
+ return;
+ } catch(e) {}
+ }
+
+ if (/[%=\(\\<]/.test(originalAttempt) && InjectionChecker.checkURL(originalAttempt)) {
+ window.name = originalAttempt.replace(/[%=\(\\<]/g, " ");
+ }
+
+ if (originalAttempt.length > 11) {
+ try {
+ if ((originalAttempt.length % 4 === 0)) {
+ var bin = window.atob(window.name);
+ if(/[%=\(\\]/.test(bin) && InjectionChecker.checkURL(bin)) {
+ window.name = "BASE_64_XSS";
+ }
+ }
+ } catch(e) {}
+ }
+ } finally {
+ if (originalAttempt != window.name) {
+ ns.log('[NoScript XSS]: sanitized window.name, "' + originalAttempt + '"\nto\n"' + window.name + '"\nURL: ' + url);
+ ns.log(url + "\n" + window.location.href);
+ }
+ }
+ },
+
+};
+
+function PostChecker(url, uploadStream, skip) {
+ this.url = url;
+ this.uploadStream = uploadStream;
+ this.skip = skip || false;
+}
+
+PostChecker.prototype = {
+ boundary: null,
+ isFile: false,
+ postData: '',
+ check: function(callback) {
+ var m, chunks, data, size, available, ret;
+ const BUF_SIZE = 3 * 1024 * 1024; // 3MB
+ const MAX_FIELD_SIZE = BUF_SIZE;
+ try {
+ var us = this.uploadStream;
+ us.seek(0, 0);
+ const sis = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
+ sis.setInputStream(us);
+
+ // reset status
+ delete this.boundary;
+ delete this.isFile;
+ delete this.postData;
+
+ if ((available = sis.available())) do {
+ size = this.postData.length;
+ if (size >= MAX_FIELD_SIZE) return size + " bytes or more in one non-file field, assuming memory DOS attempt!";
+
+ data = sis.readBytes(Math.min(available, BUF_SIZE));
+
+ if (size !== 0) {
+ this.postData += data;
+ } else {
+ if (data.length === 0) return false;
+ this.postData = data;
+ }
+ available = sis.available();
+ chunks = this.parse(!available);
+
+ for (var j = 0, len = chunks.length; j < len; j++) {
+ ret = callback(chunks[j]);
+ if (ret) return ret;
+ }
+ } while(available)
+ } catch(ex) {
+ dump(ex + "\n" + ex.stack + "\n");
+ return ex;
+ } finally {
+ try {
+ us.seek(0, 0); // rewind
+ } catch(e) {}
+ }
+ return false;
+ },
+
+ parse: function(eof) {
+ var postData = this.postData;
+ var m;
+
+ if (typeof(this.boundary) != "string") {
+ m = postData.match(/^Content-type: multipart\/form-data;\s*boundary=(\S*)/i);
+ this.boundary = m && m[1] || '';
+ if (this.boundary) this.boundary = "--" + this.boundary;
+ postData = postData.substring(postData.indexOf("\r\n\r\n") + 2);
+ }
+
+ this.postData = '';
+
+ var boundary = this.boundary;
+
+ var chunks = [];
+ var j, len, name;
+
+ var skip = this.skip;
+
+ if (boundary) { // multipart/form-data, see http://www.faqs.org/ftp/rfc/rfc2388.txt
+ if(postData.indexOf(boundary) < 0) {
+ // skip big file chunks
+ return chunks;
+ }
+ var parts = postData.split(boundary);
+
+ var part, last;
+ for(j = 0, len = parts.length; j < len;) {
+ part = parts[j];
+ last = ++j == len;
+ if (j == 1 && part.length && this.isFile) {
+ // skip file internal terminal chunk
+ this.isFile = false;
+ continue;
+ }
+ m = part.match(/^\s*Content-Disposition: form-data; name="(.*?)"(?:;\s*filename="(.*)"|[^;])\r?\n(Content-Type: \w)?.*\r?\n/i);
+
+ if (m) {
+ // name and filename are backslash-quoted according to RFC822
+ name = m[1];
+ if (name) {
+ chunks.push(name.replace(/\\\\/g, "\\")); // name and file name
+ }
+ if (m[2]) {
+ chunks.push(m[2].replace(/\\\\/g, "\\")); // filename
+ if (m[3]) {
+ // Content-type: skip, it's a file
+ this.isFile = true;
+
+ if (last && !eof)
+ this.postData = part.substring(part.length - boundary.length);
+
+ continue;
+ }
+ }
+ if (eof || !last) {
+ if (!(skip && skip.indexOf(name) !== -1))
+ chunks.push(part.substring(m[0].length)); // parameter body
+ } else {
+ this.postData = part;
+ }
+ this.isFile = false;
+ } else {
+ // malformed part, check it all or push it back
+ if (eof || !last) {
+ chunks.push(part)
+ } else {
+ this.postData = this.isFile ? part.substring(part.length - boundary.length) : part;
+ }
+ }
+ }
+ } else {
+ this.isFile = false;
+
+ parts = postData.replace(/^\s+/, '').split("&");
+ if (!eof) this.postData = parts.pop();
+
+ for (j = 0, len = parts.length; j < len; j++) {
+ m = parts[j].split("=");
+ name = m[0];
+ if (skip && skip.indexOf(name) > -1) continue;
+ chunks.push(name, m[1] || '');
+ }
+ }
+ return chunks;
+ }
+}
+
+
+function XSanitizer(primaryBlacklist, extraBlacklist) {
+ this.primaryBlacklist = primaryBlacklist;
+ this.extraBlacklist = extraBlacklist;
+ this.injectionChecker = InjectionChecker;
+}
+
+XSanitizer.prototype = {
+ brutal: false,
+ base64: false,
+ sanitizeURL: function(url) {
+ var original = url.clone();
+ this.brutal = this.brutal || this.injectionChecker.checkURL(url.spec);
+ this.base64 = this.injectionChecker.base64;
+
+ const changes = { minor: false, major: false, qs: false };
+ // sanitize credentials
+ if (url.username) url.username = this.sanitizeEnc(url.username);
+ if (url.password) url.password = this.sanitizeEnc(url.password);
+ url.host = this.sanitizeEnc(url.host);
+ let pathProp = ["path" in url ? "path" : "pathQueryRef"];
+ let urlPath = url[pathProp];
+ if (url instanceof Ci.nsIURL) {
+ // sanitize path
+
+ if (url.param) {
+ urlPath = url[pathProp] = this.sanitizeURIComponent(urlPath); // param is the URL part after filePath and a semicolon ?!
+ } else if(url.filePath) {
+ url.filePath = this.sanitizeURIComponent(url.filePath); // true == lenient == allow ()=
+ }
+ // sanitize query
+ if (url.query) {
+ url.query = this.sanitizeQuery(url.query, changes);
+ if (this.brutal) {
+ url.query = this.sanitizeWholeQuery(url.query, changes);
+ }
+ }
+ // sanitize fragment
+ var fragPos = urlPath.indexOf("#");
+ if (url.ref || fragPos > -1) {
+ if (fragPos >= url.filePath.length + url.query.length) {
+ urlPath = url[pathProp] = urlPath.substring(0, fragPos) + "#" + this.sanitizeEnc(urlPath.substring(fragPos + 1));
+ } else {
+ url.ref = this.sanitizeEnc(url.ref);
+ }
+ }
+ } else {
+ // fallback for non-URL URIs, we should never get here anyway
+ if (urlPath) urlPath = url[pathProp] = this.sanitizeURIComponent(urlPath);
+ }
+
+ var urlSpec = url.spec;
+ var neutralized = Entities.neutralizeAll(urlSpec, /[^\\'"\x00-\x07\x09\x0B\x0C\x0E-\x1F\x7F<>]/);
+ if (urlSpec != neutralized) url.spec = neutralized;
+
+ if (this.base64 ||
+ FlashIdiocy.affects(urlSpec) ||
+ FlashIdiocy.affects(unescape(urlSpec))
+ ) {
+ url.spec = url.prePath; // drastic, but with base64 / FlashIdiocy we cannot take the risk!
+ }
+
+ if (url.getRelativeSpec(original) && unescape(url.spec) != unescape(original.spec)) { // ok, this seems overkill but take my word, the double check is needed
+ changes.minor = true;
+ changes.major = changes.major || changes.qs ||
+ unescape(original.spec.replace(/\?.*/g, ""))
+ != unescape(url.spec.replace(/\?.*/g, ""));
+ url.spec = url.spec.replace(/'/g, "%27")
+ if (changes.major) {
+ url.ref = Math.random().toString().concat(Math.round(Math.random() * 999 + 1)).replace(/0./, '') // randomize URI
+ }
+ } else {
+ changes.minor = false;
+ url.spec = original.spec.replace(/'/g, "%27");
+ }
+ return changes;
+ },
+
+ sanitizeWholeQuery: function(query, changes) {
+ var original = query;
+ query = Entities.convertAll(query);
+ if (query === original) return query;
+ var unescaped = InjectionChecker.urlUnescape(original, true);
+ query = this.sanitize(unescaped);
+ if (query === unescaped) return original;
+ if(changes) changes.qs = true;
+ return escape(query);
+ },
+
+ _queryRecursionLevel: 0,
+ sanitizeQuery: function(query, changes, sep) {
+ const MAX_RECUR = 2;
+
+ var canRecur = this._queryRecursionLevel++ < MAX_RECUR;
+ // replace every character matching noscript.filterXGetRx with a single ASCII space (0x20)
+ changes = changes || {};
+ if (!sep) {
+ sep = query.indexOf("&") > -1 || this.brutal ? "&" : ";"
+ }
+ const parms = query.split(sep);
+
+ for (let j = parms.length; j-- > 0;) {
+ let pieces = parms[j].split("=");
+
+ try {
+ for (let k = pieces.length; k-- > 0;) {
+
+ let encodedPz = InjectionChecker.utf8OverDecode(pieces[k]);
+
+ let pz = null, encodeURL = null;
+ if (encodedPz.indexOf("+") < 0) {
+ try {
+ pz = decodeURIComponent(encodedPz);
+ encodeURL = encodeURIComponent;
+ } catch(e) {}
+ }
+ if (pz == null) {
+ pz = unescape(ASPIdiocy.filter(encodedPz));
+ encodeURL = escape;
+ }
+
+ let origPz = pz;
+
+ // recursion for nested (partial?) URIs
+
+ let nestedURI = null;
+
+ if (canRecur && /^https?:\/\//i.test(pz)) {
+ // try to sanitize as a nested URL
+ try {
+ nestedURI = IOUtil.newURI(pz).QueryInterface(Ci.nsIURL);
+ changes.qs = changes.qs || this.sanitizeURL(nestedURI).major;
+ if (unescape(pz).replace(/\/+$/, '') != unescape(nestedURI.spec).replace(/\/+$/, '')) pz = nestedURI.spec;
+ } catch(e) {
+ nestedURI = null;
+ }
+ }
+
+ if (!nestedURI) {
+ let qpos;
+ if (canRecur &&
+ (qpos = pz.indexOf("?")) > - 1 &&
+ (spos = pz.search(/[&;]/) > qpos)) {
+ // recursive query string?
+ // split, sanitize and rejoin
+ pz = [ this.sanitize(pz.substring(0, qpos)),
+ this.sanitizeQuery(pz.substring(qpos + 1), changes)
+ ].join("?")
+
+ } else {
+ pz = this.sanitize(pz);
+ }
+ if (origPz != pz) changes.qs = true;
+ }
+
+ if (origPz != pz) pieces[k] = encodeURL(pz);
+
+ }
+ parms[j] = pieces.join("=");
+ } catch(e) {
+ // decoding exception, skip this param
+ parms.splice(j, 1);
+ }
+ }
+ this._queryRecursionLevel--;
+ return parms.join(sep);
+ },
+
+ sanitizeURIComponent: function(s) {
+ try {
+ var unescaped = InjectionChecker.urlUnescape(s, this.brutal);
+ var sanitized = this.sanitize(unescaped);
+ return sanitized == unescaped ? s : encodeURI(sanitized);
+ } catch(e) {
+ return "";
+ }
+ },
+ sanitizeEnc: function(s) {
+ try {
+ return encodeURIComponent(this.sanitize(decodeURIComponent(s)));
+ } catch(e) {
+ return "";
+ }
+ },
+ sanitize: function(unsanitized) {
+ var s, orig;
+ orig = s = Entities.convertDeep(unsanitized);
+
+ if (s.indexOf('"') > -1 && !this.brutal) {
+ // try to play nice on search engine queries with grouped quoted elements
+ // by allowing double quotes but stripping even more aggressively other chars
+
+ // Google preserves "$" and recognizes ~, + and ".." as operators
+ // All the other non alphanumeric chars (aside double quotes) are ignored.
+ // We will preserve the site: modifier as well
+ // Ref.: http://www.google.com/help/refinesearch.html
+ s = s.replace(/[^\w\$\+\.\~"&;\- :\u0080-\uffff]/g,
+ " " // strip everything but alphnum and operators
+ ).replace(":",
+ function(k, pos, s) { // strip colons as well, unless it's the site: operator
+ return (s.substring(0, pos) == "site" || s.substring(pos - 5) == " site") ? ":" : " "
+ }
+ );
+ if (s.replace(/[^"]/g, "").length % 2) s += '"'; // close unpaired quotes
+ return s;
+ }
+
+ if (this.brutal) {
+ s = s.replace(/\x1bJ\(/g, '').replace(/\x7e\x0a/g, ''); // ignored in some encodings
+ }
+ // regular duty
+ s = s.replace(this.primaryBlacklist, " ")
+ .replace(/\bjavascript:+|\bdata:[^,]+,(?=[^<]*<|%25%20|%\s+[2-3][0-9a-f])|-moz-binding|@import/ig,
+ function(m) { return m.replace(/(.*?)(\w)/, "$1#no$2"); });
+
+ if (this.extraBlacklist) { // additional user-defined blacklist for emergencies
+ s = s.replace(this.extraBlacklist, " ");
+ }
+
+ if (this.brutal) { // injection checks were positive
+ s = InjectionChecker.reduceDashPlus(s)
+ .replace(/\bdata:/ig, "nodata:")
+ .replace(/['\(\)\=\[\]<\r\n`]/g, " ")
+ .replace(/0x[0-9a-f]{16,}|0b[01]{64,}/gi, " ")
+ .replace(this._dangerousWordsRx, this._dangerousWordsReplace)
+ .replace(/Q[\da-fA-Fa]{2}/g, "Q20") // Ebay-style escaping
+ .replace(/%[\n\r\t]*[0-9a-f][\n\r\t]*[0-9a-f]/gi, " ")
+ // .replace(/percnt/, 'percent')
+ ;
+ }
+
+ return s == orig ? unsanitized : s;
+ },
+
+ _regularReplRx: new RegExp(
+ fuzzify('(?:javascript|data)') + '\\W*:+|' +
+ fuzzify('-moz-binding|@import'),
+ "ig"
+ ),
+ _dangerousWordsRx: new RegExp(
+ '\\b(?:' + fuzzify('setter|location|innerHTML|outerHTML|cookie|name|document|toString|') +
+ IC_EVAL_PATTERN + '|' + IC_EVENT_PATTERN + ')\\b',
+ "g"
+ ),
+ _dangerousWordsReplace: (s) => s.replace(/\S/g, "$&\u2063")
+
+};
+
+// we need this because of https://bugzilla.mozilla.org/show_bug.cgi?id=439276
+
+var Base64 = {
+
+ purify: function(input) {
+ return input.replace(/[^A-Za-z0-9\+\/=]+/g, '');
+ },
+
+ alt: function(s) {
+ // URL base64 variant, see http://en.wikipedia.org/wiki/Base64#URL_applications
+ return s.replace(/-/g, '+').replace(/_/g, '/')
+ },
+
+ decode: function (input, strict) {
+ var output = '';
+ var chr1, chr2, chr3;
+ var enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ // if (/[^A-Za-z0-9\+\/\=]/.test(input)) return ""; // we don't need this, caller checks for us
+
+ const k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+ while (i < input.length) {
+
+ enc1 = k.indexOf(input.charAt(i++));
+ enc2 = k.indexOf(input.charAt(i++));
+ enc3 = k.indexOf(input.charAt(i++));
+ enc4 = k.indexOf(input.charAt(i++));
+
+ chr1 = (enc1 << 2) | (enc2 >> 4);
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+ chr3 = ((enc3 & 3) << 6) | enc4;
+
+ output += String.fromCharCode(chr1);
+
+ if (enc3 != 64) {
+ output += String.fromCharCode(chr2);
+ }
+ if (enc4 != 64) {
+ output += String.fromCharCode(chr3);
+ }
+
+ }
+ return output;
+
+ }
+};
+
+
+
+
+var ASPIdiocy = {
+ _replaceRx: /%u([0-9a-fA-F]{4})/g,
+ _affectsRx: /%u[0-9a-fA-F]{4}/,
+ _badPercentRx: /%(?!u[0-9a-fA-F]{4}|[0-9a-fA-F]{2})|%(?:00|u0000)[^&=]*/g,
+
+ hasBadPercents: function(s) { return this._badPercentRx.test(s) },
+ removeBadPercents: function(s) { return s.replace(this._badPercentRx, ''); },
+ affects: function(s) { return this._affectsRx.test(s); },
+ process: function(s) {
+ s = this.filter(s);
+ return /[\uff5f-\uffff]/.test(s) ? s + '&' + s.replace(/[\uff5f-\uffff]/g, '?') : s;
+ },
+ filter: function(s) { return this.removeBadPercents(s).replace(this._replaceRx, this._replace) },
+
+ coalesceQuery: function(s) { // HPP protection, see https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf
+ let qm = s.indexOf("?");
+ if (qm < 0) return s;
+ let p = s.substring(0, qm);
+ let q = s.substring(qm + 1);
+ if (!q) return s;
+
+ let unchanged = true;
+ let emptyParams = false;
+
+ let pairs = (function rearrange(joinNames) {
+ let pairs = q.split("&");
+ let accumulator = { __proto__: null };
+ for (let j = 0, len = pairs.length; j < len; j++) {
+ let nv = pairs[j];
+ let eq = nv.indexOf("=");
+ if (eq === -1) {
+ emptyParams = true;
+ if (joinNames && j < len - 1) {
+ pairs[j + 1] = nv + "&" + pairs[j + 1];
+ delete pairs[j];
+ }
+ continue;
+ }
+ let key = "#" + unescape(nv.substring(0, eq)).toLowerCase();
+ if (key in accumulator) {
+ delete pairs[j];
+ pairs[accumulator[key]] += ", " + nv.substring(eq + 1);
+ unchanged = false;
+ } else {
+ accumulator[key] = j;
+ }
+ }
+ return (emptyParams && !(unchanged || joinNames))
+ ? pairs.concat(rearrange(true).filter(p => pairs.indexOf(p) === -1))
+ : pairs;
+ })();
+
+ if (unchanged) return s;
+ for (let j = pairs.length; j-- > 0;) if (!pairs[j]) pairs.splice(j, 1);
+ return p + pairs.join("&");
+ },
+
+ _replace: function(match, hex) {
+ // lazy init
+ INCLUDE("ASPIdiocy");
+ return ASPIdiocy._replace(match, hex);
+ }
+}
+
+var FlashIdiocy = {
+ _affectsRx: /%(?:[8-9a-f]|[0-7]?[^0-9a-f])/i, // high (non-ASCII) percent encoding or invalid second digit
+ affects: function(s) { return this._affectsRx.test(s); },
+
+ purgeBadEncodings: function(s) {
+ INCLUDE("FlashIdiocy");
+ return this.purgeBadEncodings(s);
+ }
+}
+
diff --git a/extensions/noscript/chrome/content/noscript/JSURL.js b/extensions/noscript/chrome/content/noscript/JSURL.js
new file mode 100644
index 0000000..6ea001c
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/JSURL.js
@@ -0,0 +1,88 @@
+var JSURL = {
+ JS_VERSION: "1.8",
+ load: function(url, document) {
+ this._run(document, url.substring("javascript:".length)
+ .replace(/(?:%[0-9a-f]{2})+/gi, function(m) {
+ try {
+ return decodeURIComponent(m);
+ } catch (e) {}
+ return unescape(m);
+ }));
+ },
+
+ _patch: (function() {
+ (function patchAll(w) {
+ if (!w || w.open && w.open._bypass)
+ return w;
+
+ var d = w.document;
+
+ function op(data) {
+ var code = "Object.getPrototypeOf(document)." +
+ (typeof(data) === "string"
+ ? 'write.call(document, ' + JSON.stringify(data) + ')'
+ : 'open.call(document)'
+ );
+ var s = d.createElement("script");
+ s.appendChild(d.createTextNode(code));
+ var p = d.documentElement;
+ p.appendChild(s);
+ p.removeChild(s);
+ if (d.write === Object.getPrototypeOf(d).write) {
+ patchAll(w);
+ }
+ }
+ function patch(o, m, f) {
+ var saved = o[m];
+ f._restore = function() { o[m] = saved };
+ f._bypass = saved;
+ o[m] = f;
+ }
+
+ patch(d, "open", function() { op(null) });
+ patch(d, "write", function(s) {
+ op(typeof(s) === "string" ? s : "" + s);
+ });
+ patch(d, "writeln", function(s) { this.write(s + "\n") });
+
+ patch(w, "open", function() {
+ return patchAll(w.open._bypass.apply(w, arguments));
+ });
+
+ return w;
+ })(window);
+ }).toSource() + "()",
+ _restore: (function() {
+ var d = window.document;
+ d.writeln._restore();
+ d.write._restore();
+ d.open._restore();
+ }).toSource() + "()",
+
+ _run: function(document, code) {
+ var w = document.defaultView;
+ var p = document.nodePrincipal;
+ var s = ScriptSurrogate.createSandboxForWindow(w, p, {
+ sandboxName: "NoScript::JSURL@" + document.documentURI,
+ sandboxPrototype: w,
+ wantXrays: false,
+ });
+ var e = (script) => Cu.evalInSandbox("with(window) {" + script + "}", s);
+ try {
+ e(this._patch);
+ let ret = e(code);
+ if (typeof ret !== "undefined" &&
+ !DOM.getDocShellForWindow(w).isLoadingDocument) {
+ s._ret_ = ret;
+ e("window.location.href = 'javascript:' + JSON.stringify('' + this._ret_)");
+ delete s._ret_;
+ Thread.yieldAll();
+ }
+ } catch (e) {
+ try { w.console.error("" + e) } catch(consoleError) { Cu.reportError(e) }
+ } finally {
+ try { e(this._restore) } catch(e) {}
+ }
+ },
+
+}
diff --git a/extensions/noscript/chrome/content/noscript/Lang.js b/extensions/noscript/chrome/content/noscript/Lang.js
new file mode 100644
index 0000000..71a74e9
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Lang.js
@@ -0,0 +1,17 @@
+// language utilities
+
+const Lang = {
+ memoize: function(obj, funcs) {
+ for (var p in funcs) {
+ this._memoizeMember(obj, p, funcs[p]);
+ }
+ return obj;
+ },
+ _memoizeMember: function(obj, prop, func) {
+ obj.__defineGetter__(prop, function() {
+ var r = func.apply(this);
+ this.__defineGetter__(prop, function() { return r; });
+ return r;
+ });
+ }
+}
diff --git a/extensions/noscript/chrome/content/noscript/MSEInterception.js b/extensions/noscript/chrome/content/noscript/MSEInterception.js
new file mode 100644
index 0000000..f3086cc
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/MSEInterception.js
@@ -0,0 +1,98 @@
+var MSEInterception = {
+ sites: {},
+ handler(ev) {
+ if (typeof ns === "undefined") {
+ ev.currentTarget.removeEventListener(ev.type, argument.callee, true);
+ return;
+ }
+ let target = ev.target;
+ let mime = ev.detail.mime;
+ let doc = target.ownerDocument || target;
+ let url = doc.documentURI;
+ let site = ns.getSite(url);
+ if (ns.forbidMedia && ns.contentBlocker && !(ns.isAllowedObject(url, mime, site, site) || ns.isAllowedMime(mime, site))) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ ev.detail.blocked = true;
+ MSEInterception.record(target, url, site, mime, true);
+ }
+ },
+ record(ctx, url, site, mime, fromDOM) {
+ let data = {
+ url,
+ site,
+ originSite: site,
+ mime
+ };
+ ns.tagForReplacement(ctx, data);
+ ns.countObject(ctx, url);
+ let doc = ctx.ownerDocument || ctx;
+ if (fromDOM) {
+ let ds = DOM.getDocShellForWindow(doc.defaultView);
+ if (ds.isLoadingDocument) { // prevent fallback redirection from hiding us
+ let sites = this.sites;
+ sites[site] = data;
+ doc.defaultView.addEventListener("load", () => delete sites[site], false);
+ }
+ }
+ ns.recordBlocked(url, site);
+ },
+
+ get interceptionDef() {
+ delete this.interceptionDef;
+ return (this.interceptionDef = function() {
+ let urlMap = new WeakMap();
+ let createObjectURL = URL.createObjectURL;
+ URL.createObjectURL = function(o, ...args) {
+ let url = createObjectURL.call(this, o, ...args);
+ if (o instanceof MediaSource) {
+ let urls = urlMap.get(o);
+ if (!urls) urlMap.set(o, urls = new Set());
+ urls.add(url);
+ }
+ return url;
+ };
+ let proto = MediaSource.prototype;
+ let addSourceBuffer = proto.addSourceBuffer;
+ proto.addSourceBuffer = function(mime, ...args) {
+ let ms = this;
+ let urls = urlMap.get(ms);
+ let me = Array.from(document.querySelectorAll("video,audio")).find(e => e.srcObject === ms || urls && urls.has(e.src));
+ let exposedMime = `${mime} (MSE)`;
+ let ev = new CustomEvent("NoScript:MSE", {cancelable: true, detail: { mime: exposedMime, blocked: false }});
+
+ (me || document).dispatchEvent(ev);
+
+ if (ev.detail.blocked) {
+ throw new Error(`${exposedMime} blocked by NoScript`);
+ }
+ return addSourceBuffer.call(ms, mime, ...args);
+ };
+ }.toSource() + "()");
+ },
+ reloadAllowed(docShell) {
+ let curURL = docShell.currentURI.spec;
+ let site = ns.getSite(curURL);
+ if (site in this.sites) {
+ let {url} = this.sites[site];
+ delete this.sites[site];
+ if (url !== curURL) {
+ docShell.loadURI(url, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);
+ return true;
+ }
+ }
+ return false;
+ },
+ hook(doc, site) {
+ let url = doc.documentURI;
+ if (!(ns.isAllowedObject(url, "MSE", site, site) || ns.isAllowedMime("MSE", url))) {
+ DOM.getFrameMM(doc.defaultView).addEventListener("NoScript:MSE", this.handler, true, true);
+ if (site in this.sites) {
+ let data = this.sites[site];
+ this.record(doc, data.url, data.site, data.mime);
+ }
+ return this.interceptionDef;
+ }
+ return null;
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/Main.js b/extensions/noscript/chrome/content/noscript/Main.js
new file mode 100644
index 0000000..c96be47
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Main.js
@@ -0,0 +1,4530 @@
+const CLASS_NAME="NoScript Service";
+const SERVICE_CTRID = "@maone.net/noscript-service;1";
+const SERVICE_ID = "{31aec909-8e86-4397-9380-63a59e0c5ff5}";
+const EXTENSION_ID = "{73a6fe31-595d-460b-a920-fcc0f8843232}";
+
+const CP_OK = 1;
+const CP_REJECT = -2; // CP_REJECT_TYPE doesn't cause the -moz-suppressed CSS pseudo class to be added
+const CP_NOP = () => CP_OK;
+const CP_FRAMECHECK = 2;
+const CP_SHOULDPROCESS = 4;
+const CP_OBJECTARC = 8;
+const CP_EXTERNAL = 0;
+
+const nsIWebProgress = Ci.nsIWebProgress;
+const nsIWebProgressListener = Ci.nsIWebProgressListener;
+const WP_STATE_START = nsIWebProgressListener.STATE_START;
+const WP_STATE_STOP = nsIWebProgressListener.STATE_STOP;
+const WP_STATE_DOC = nsIWebProgressListener.STATE_IS_DOCUMENT;
+const WP_STATE_START_DOC = WP_STATE_START | WP_STATE_DOC;
+const WP_STATE_RESTORING = nsIWebProgressListener.STATE_RESTORING;
+
+const LF_VALIDATE_ALWAYS = Ci.nsIRequest.VALIDATE_ALWAYS;
+const LF_LOAD_BYPASS_ALL_CACHES = Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE;
+
+const NS_OK = 0;
+const NS_BINDING_ABORTED = 0x804b0002;
+const NS_BINDING_REDIRECTED = 0x804b0003;
+const NS_ERROR_UNKNOWN_HOST = 0x804b001e;
+const NS_ERROR_REDIRECT_LOOP = 0x804b001f;
+const NS_ERROR_CONNECTION_REFUSED = 0x804b000e;
+const NS_ERROR_NOT_AVAILABLE = 0x804b0111;
+
+const LOG_CONTENT_BLOCK = 1;
+const LOG_CONTENT_CALL = 2;
+const LOG_CONTENT_INTERCEPT = 4;
+const LOG_CHROME_WIN = 8;
+const LOG_XSS_FILTER = 16;
+const LOG_INJECTION_CHECK = 32;
+const LOG_DOM = 64; // obsolete, reuse me
+const LOG_JS = 128;
+const LOG_LEAKS = 1024;
+const LOG_SNIFF = 2048;
+const LOG_CLEARCLICK = 4096;
+const LOG_ABE = 8192;
+const LOG_IPC = 16384;
+
+const HTML_NS = "http://www.w3.org/1999/xhtml";
+
+const WHERE_UNTRUSTED = 1;
+const WHERE_TRUSTED = 2;
+const ANYWHERE = 3;
+
+const DUMMY_OBJ = {};
+DUMMY_OBJ.wrappedJSObject = DUMMY_OBJ;
+const DUMMY_FUNC = function() {};
+const DUMMY_ARRAY = [];
+
+const SERVICE_IIDS =
+[
+Ci.nsIContentPolicy,
+Ci.nsIObserver,
+Ci.nsISupportsWeakReference,
+Ci.nsIChannelEventSink,
+nsIWebProgressListener,
+Ci.nsIWebProgressListener2,
+Ci.nsIFactory
+];
+
+INCLUDE("e10sIPC", "SiteUtils", "AddressMatcher");
+
+function nsISupportsWrapper(wrapped) {
+ this.wrappedJSObject = wrapped;
+}
+nsISupportsWrapper.prototype = {
+ QueryInterface: XPCOMUtils.generateQI([])
+};
+
+LAZY_INCLUDE(
+ "Bug",
+ "DNS",
+ "HTTPS",
+ "ScriptSurrogate",
+ "DOM",
+ "URIValidator",
+ "ClearClickHandler",
+ "ChannelReplacement",
+ "WinScript",
+ "JSURL",
+ "IOUtil",
+ "Thread",
+ "SyntaxChecker",
+ "RequestWatchdog",
+ "InjectionChecker",
+ "Entities",
+ "DoNotTrack",
+ "WebGLInterception",
+ "MSEInterception"
+);
+
+this.__defineGetter__("ABE", function() {
+ if (ns.consoleDump) ns.dump("ABE kickstart at " + (new Error().stack));
+ delete this.ABE;
+ INCLUDE("ABE");
+ ABE.consoleDump = !!(ns.consoleDump & LOG_ABE);
+ ABE.init("noscript.");
+ ns.onDisposal(() => ABE.dispose());
+ DNS.logEnabled = ns.getPref("logDNS");
+ return ABE;
+});
+
+const ns = {
+ VERSION: "5.1.8.5",
+ classDescription: CLASS_NAME,
+ classID: Components.ID(SERVICE_ID),
+ contractID: SERVICE_CTRID,
+ QueryInterface: XPCOMUtils.generateQI(SERVICE_IIDS),
+
+ categoryManager: Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager),
+ get ABE() { return ABE; },
+
+ // nsIFactory implementation
+ createInstance: function(outer, iid) {
+ if (outer)
+ throw Cr.NS_ERROR_NO_AGGREGATION;
+ return this;
+ },
+ // nsIObserver implementation
+ observe: function(subject, topic, data) {
+
+ switch (topic) {
+ case "content-document-global-created":
+ this.onWindowCreated(subject, data);
+ return;
+ case "document-element-inserted":
+ this.beforeScripting(subject, data);
+ return;
+ }
+
+ if (subject instanceof Ci.nsIPrefBranch) {
+ this.syncPrefs(subject, data);
+ } else {
+ switch (topic) {
+
+ case "xpcom-shutdown":
+ this.shutdown(true);
+ break;
+
+ case "profile-before-change":
+ this.dispose();
+ break;
+
+ case "profile-after-change":
+ try {
+ this.init();
+ } catch(e) {
+ this.dump("Init error -- " + e + "\n" + e.stack);
+ }
+ break;
+ case "sessionstore-windows-restored":
+ ns.checkVersion(true);
+ break;
+
+ case "private-browsing":
+ if (data == "enter") {
+ if (!("_realDump_" in this)) this._realDump_ = this.dump;
+ this.dump = DUMMY_FUNC;
+ }
+ if (data == "exit") {
+ this.eraseTemp();
+ this.dump = this._realDump_ || DUMMY_FUNC;
+ }
+ // break;
+ case "browser:purge-session-history":
+ this.eraseTemp();
+ break;
+
+
+ }
+ }
+ },
+
+
+ IPC: IPC,
+ bootstrap: function() {
+ this.childProcess = (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT);
+
+ let log = msg => this.log(msg);
+ INCLUDE_MIXIN(this, "MainChild");
+ if (!this.childProcess) {
+ INCLUDE_MIXIN(this, "MainParent");
+ }
+
+ try {
+ IPC.autoSync(this, "Main", ["setJSEnabled", "setTemp", "eraseTemp", "allowObject", "resetAllowedObjects", "shutdown"]);
+ } catch (e) {
+ log(e);
+ }
+ this.startup();
+ },
+
+ OBSERVED_TOPICS: ["profile-before-change", "xpcom-shutdown", "profile-after-change", "sessionstore-windows-restored",
+ "browser:purge-session-history", "private-browsing",
+ "content-document-global-created", "document-element-inserted"],
+ _started: false,
+ startup: function() {
+ if (this._started) return;
+ this._started = true;
+ this.registerComponent();
+ for (let topic of this.OBSERVED_TOPICS) {
+ let observer = this[topic] || this;
+ OS.addObserver(observer, topic, observer instanceof Ci.nsISupportsWeakReference);
+ }
+ },
+ shutdown: function(exiting = false) {
+ if (!this._started) return;
+ this._started = false;
+
+
+ if (exiting) {
+ this.resetJSCaps();
+ this.savePrefs();
+ return;
+ }
+
+ this.dump("NoScript shutting down");
+
+ if (!this.childProcess) {
+ try {
+ this.prefService.getDefaultBranch("noscript.").setCharPref("snapshot", JSON.stringify(this.getSnapshot()));
+ } catch (e) {
+ Cu.reportError(e);
+ }
+ }
+
+ this.dispose();
+ for (let topic of this.OBSERVED_TOPICS) {
+ try {
+ OS.removeObserver(this[topic] || this, topic);
+ } catch (e) {}
+ }
+ this.observe = () => {};
+ this.dump("NoScript shutdown done");
+ },
+
+ // Preference driven properties
+ autoAllow: false,
+
+ consoleDump: 0,
+ consoleLog: false,
+
+ truncateTitle: true,
+ truncateTitleLen: 255,
+
+ showBlankSources: false,
+ showPlaceholder: true,
+ showUntrustedPlaceholder: true,
+ collapseObject: false,
+ clearClick: 3,
+
+
+ forbidSomeContent: true,
+ contentBlocker: false,
+
+ forbidJava: true,
+ forbidFlash: true,
+ forbidPlugins: true,
+ forbidMedia: true,
+ forbidFonts: true,
+ forbidWebGL: false,
+ forbidIFrames: false,
+ forbidIFramesContext: 2, // 0 = all iframes, 1 = different site, 2 = different domain, 3 = different base domain
+ forbidFrames: false,
+
+ alwaysBlockUntrustedContent: true,
+
+ forbidXBL: 4,
+ forbidXHR: 1,
+ injectionCheck: 2,
+ injectionCheckSubframes: true,
+
+ jsredirectIgnore: false,
+ jsredirectFollow: false,
+ jsredirectForceShow: false,
+ emulateFrameBreak: true,
+
+ jsHack: null,
+ jsHackRegExp: null,
+
+ dropXssProtection: true,
+ flashPatch: true,
+ silverlightPatch: true,
+
+ nselNever: false,
+ nselForce: true,
+
+ filterXGetRx: "(?:<+(?=[^<>=\\d\\. ])|[\\\\'\"\\x00-\\x07\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F])",
+ filterXGetUserRx: "",
+
+
+ whitelistRegExp: null,
+ allowedMimeRegExp: null,
+ hideOnUnloadRegExp: null,
+ requireReloadRegExp: null,
+ ignorePorts: true,
+
+ inclusionTypeChecking: true,
+ nosniff: true,
+
+ fakeScriptLoadEvents: {},
+
+ resetDefaultPrefs: function(prefs, exclude) {
+ exclude = exclude || [];
+ const root = prefs.root;
+ const keys = prefs.getChildList("", {});
+ for (let j = keys.length; j-- > 0;) {
+ let k = keys[j];
+ if (exclude.indexOf(k) === -1) {
+ if (prefs.prefHasUserValue(k)) {
+ dump("Resetting " + root + k + "\n");
+ try {
+ prefs.clearUserPref(k);
+ } catch(e) {
+ dump(`${e}\n`);
+ }
+ }
+ }
+ }
+ this.savePrefs();
+ },
+
+ resetDefaultGeneralPrefs: function() {
+ this.resetDefaultPrefs(this.prefs, ['version']);
+ },
+
+ resetDefaultSitePrefs: function() {
+ this.eraseTemp();
+ this.setJSEnabled(this.splitList(this.getPref("default")), true, true);
+ },
+
+ resetDefaults: function() {
+ this.resetDefaultGeneralPrefs();
+ this.jsEnabled = false;
+ this.resetDefaultSitePrefs();
+ },
+
+ syncPrefs: function(branch, name) {
+ switch (name) {
+ case "sites":
+ if (this.jsPolicySites.settingPref) return;
+ if (this.locked) try {
+ this.defaultCaps.lockPref(this.POLICY_NAME + ".sites");
+ } catch (e) {
+ }
+ if (!this.jsPolicySites.fromPref(this.policyPB)) {
+ this.resetDefaultSitePrefs();
+ }
+ this.jsPolicySites.add(this.tempSites.sitesList);
+ break;
+ case "untrusted":
+ this.untrustedSites.fromPref(branch, name);
+ break;
+ case "default.javascript.enabled":
+ if (IPC.parent) {
+ let dc = this.defaultCaps;
+ if (dc.getCharPref(name) != "noAccess") {
+ dc.unlockPref(name);
+ dc.setCharPref(name, "noAccess");
+ }
+ dc.lockPref(name);
+ }
+ break;
+ case "enabled":
+ try {
+ this.mozJSEnabled = this.mozJSPref.getBoolPref("enabled");
+ } catch(ex) {
+ this.mozJSPref.setBoolPref("enabled", this.mozJSEnabled = true);
+ }
+ break;
+ case "forbidJava":
+ case "forbidFlash":
+ case "forbidSilverlight":
+ case "forbidPlugins":
+ case "forbidMedia":
+ case "forbidFonts":
+ case "forbidWebGL":
+ case "forbidIFrames":
+ case "forbidFrames":
+ this[name]=this.getPref(name, this[name]);
+ this.forbidSomeContent = this.forbidJava || this.forbidFlash ||
+ this.forbidSilverlight || this.forbidPlugins ||
+ this.forbidMedia || this.forbidFonts ||
+ this.forbidIFrames || this.forbidFrames;
+ break;
+
+ case "emulateFrameBreak":
+ case "filterXPost":
+ case "filterXGet":
+ case "autoAllow":
+ case "contentBlocker":
+ case "alwaysShowObjectSources":
+
+ case "showUntrustedPlaceholder":
+ case "collapseObject":
+ case "truncateTitle":
+ case "truncateTitleLen":
+ case "forbidMetaRefresh":
+ case "forbidIFramesContext":
+ case "forbidXBL":
+ case "forbidXHR":
+ case "ignorePorts":
+ case "injectionCheck":
+ case "jsredirectFollow":
+ case "jsredirectIgnore":
+ case "jsredirectForceShow":
+ case "jsHack":
+ case "consoleLog":
+ case "dropXssProtection":
+ case "flashPatch":
+ case "silverlightPatch":
+ case "inclusionTypeChecking":
+ case "nosniff":
+ case "showBlankSources":
+ case "audioApiInterception":
+ case "allowHttpsOnly":
+ case "restrictSubdocScripting":
+ case "globalHttpsWhitelist":
+ this[name] = this.getPref(name, this[name]);
+ break;
+
+ case "cascadePermissions":
+ this[name] = this.geckoVersionCheck("24") >= 0 && this.getPref(name, this[name]);
+ break;
+
+ case "fakeScriptLoadEvents.enabled":
+ case "fakeScriptLoadEvents.onlyRequireJS":
+ case "fakeScriptLoadEvents.exceptions":
+ case "fakeScriptLoadEvents.docExceptions":
+ let sub = name.split('.')[1];
+ let value = this.getPref(name);
+ this.fakeScriptLoadEvents[sub] = typeof value === "boolean" ? value : AddressMatcher.create(value);
+ break;
+
+ case "liveConnectInterception":
+ this[name] = this.geckoVersionCheck("16.0") === -1 && this.getPref(name, this[name]);
+ break;
+
+ case "sync.enabled":
+ this._updateSync();
+ break;
+
+ case "subscription.trustedURL":
+ case "subscription.untrustedURL":
+ this.setPref("subscription.lastCheck", 0);
+ break;
+
+ case "proxiedDNS":
+ case "asyncNetworking":
+ IOUtil[name] = this.getPref(name, IOUtil[name]);
+ break;
+
+ case "consoleDump":
+ this[name] = this.getPref(name, this[name]);
+ if (this.httpStarted) {
+ this.injectionChecker.logEnabled = !!(this.consoleDump & LOG_INJECTION_CHECK);
+ ABE.consoleDump = !!(this.consoleDump & LOG_ABE);
+ }
+ IPC.logger = (this.consoleDump & LOG_IPC) ? (...args) => ns.log(...args) : null;
+ break;
+ case "global":
+ this.globalJS = this.getPref(name, false);
+ break;
+
+ case "alwaysBlockUntrustedContent":
+ this[name] = this.getPref(name, this[name]);
+ this.initContentPolicy();
+ break;
+
+ case "forbidMetaRefreshRemember":
+ if (!this.getPref(name)) this.metaRefreshWhitelist = {};
+ break;
+
+ // single rx
+ case "filterXGetRx":
+ case "filterXGetUserRx":
+ this.updateRxPref(name, this[name], "g");
+ break;
+
+ // multiple rx
+ case "filterXExceptions":
+ case "jsHackRegExp":
+ this.updateRxPref(name, "", "", this.rxParsers.multi);
+ break;
+
+ // multiple rx autoanchored
+ case "hideOnUnloadRegExp":
+ this.updateStyleSheet(`.${this.hideObjClassName} {display: none !important}`, true);
+ case "requireReloadRegExp":
+ case "whitelistRegExp":
+ this.updateRxPref(name, "", "^", this.rxParsers.multi);
+ break;
+
+ case "allowedMimeRegExp":
+ this.updateRxPref(name, "", "^i", this.rxParsers.multi);
+ break;
+
+ case "safeJSRx":
+ this.initSafeJSRx();
+ break;
+
+ case "allowClipboard":
+ this.updateExtraPerm(name, "Clipboard", ["cutcopy", "paste"]);
+ break;
+ case "allowLocalLinks":
+ this.updateExtraPerm(name, "checkloaduri", ["enabled"]);
+ break;
+ case "nselForce":
+ case "nselNever":
+ case "showPlaceholder":
+ case "clearClick":
+ this.updateCssPref(name);
+ break;
+
+ case "policynames":
+ this.setupJSCaps();
+ break;
+
+ case "clearClick.exceptions":
+ case "clearClick.subexceptions":
+ ClearClickHandler.prototype[name.split('.')[1]] = AddressMatcher.create(this.getPref(name, ''));
+ break;
+
+ case "secureCookies":
+ case "httpsDefWhitelist":
+ HTTPS[name] = this.getPref(name, HTTPS[name]);
+ break;
+ case "secureCookiesExceptions":
+ case "secureCookiesForced":
+ case "httpsForced":
+ case "httpsForcedExceptions":
+ case "httpsForcedBuiltIn":
+ HTTPS[name] = AddressMatcher.create(this.getPref(name, ''));
+ break;
+
+
+ }
+ },
+
+ rxParsers: {
+ simple: function(s, flags) {
+ var anchor = /\^/.test(flags);
+ return new RegExp(anchor ? ns.rxParsers.anchor(s) : s,
+ anchor ? flags.replace(/\^/g, '') : flags);
+ },
+ anchor: function(s) {
+ return /^\^|\$$/.test(s) ? s : "^" + s + "$";
+ },
+ multi: function(s, flags) {
+ var anchor = /\^/.test(flags);
+ var lines = s.split(anchor ? /\s+/ : /[\n\r]+/).filter(l => /\S/.test(l));
+ return new RegExp((anchor ? lines.map(ns.rxParsers.anchor) : lines).join('|'),
+ anchor ? flags.replace(/\^/g, '') : flags);
+ }
+ },
+ updateRxPref: function(name, def, flags, parseRx) {
+ parseRx = parseRx || this.rxParsers.simple;
+ var s = this.getPref(name, def);
+ if (!s) {
+ this[name] = null;
+ } else
+ {
+
+ try {
+ this[name] = parseRx(this.getPref(name, def), flags);
+ } catch(e) {
+ if(this.consoleDump) this.dump("Error parsing regular expression " + name + ", " + e);
+ this[name] = parseRx(def, flags);
+ }
+ }
+ },
+
+
+ updateExtraPerm: function(prefName, baseName, names) {
+ var cpName;
+ var enabled = this.getPref(prefName, false);
+ this[prefName] = enabled;
+ for (var j = names.length; j-- > 0;) {
+ cpName = this.POLICY_NAME + "." + baseName + "." + names[j];
+ try {
+ if (enabled) {
+ this.caps.setCharPref(cpName, "allAccess");
+ } else {
+ if (this.caps.prefHasUserValue(cpName)) {
+ this.caps.clearUserPref(cpName);
+ }
+ }
+ } catch(ex) {}
+ }
+ if (!this._batchPrefs) {
+ this.setupJSCaps();
+ }
+ },
+
+ updateCssPref: function(name) {
+ var value = this[name] = this.getPref(name);
+ var sheet;
+ switch(name) {
+ case "nselForce":
+ sheet = "noscript.noscript-show, span.noscript-show { display: inline !important } span.noscript-show { padding: 0px; margin: 0px; border: none; background: inherit; color: inherit }";
+ break;
+ case "nselNever":
+ sheet = "noscript, noscript * { display: none !important }";
+ break;
+ case "showPlaceholder":
+ let bim = "background-image: -moz-image-rect(url(" + this.skinBase + "close.png),";
+ sheet = '.__noscriptPlaceholder__ { direction: ltr !important; display: inline-block !important; } ' +
+ '.__noscriptPlaceholder__ > .__noscriptPlaceholder__1 { display: inline-block !important; position: relative !important;' +
+ 'outline-color: #fc0 !important; outline-style: solid !important; outline-width: 1px !important; outline-offset: -1px !important;' +
+ 'cursor: pointer !important; background: #ffffe0 url("' +
+ this.pluginPlaceholder + '") no-repeat left top !important; opacity: 0.6 !important; margin-top: 0px !important; margin-bottom: 0px !important;} ' +
+ '.__noscriptPlaceholder__1 > .__noscriptPlaceholder__2 { display: inline-block !important; background-repeat: no-repeat !important; background-color: transparent !important; width: 100%; height: 100%; display: block; margin: 0px; border: none } ' +
+ 'noscript .__noscriptPlaceholder__ { display: inline !important; }' +
+ '.__noscriptPlaceholder__1 > .closeButton { display: block !important; position: absolute !important; top: 0 !important; right: 0 !important;' +
+ bim + "0,25%,100%,0) !important; width: 16px !important; height: 16px !important; opacity: .8 !important}" +
+ '.__noscriptPlaceholder__1 > .closeButton:hover {' + bim + '0,50%,100%,25%) !important; opacity: 1 !important}' +
+ '.__noscriptPlaceholder__1 > .closeButton:hover:active {' + bim + '0,75%,100%,50%) !important; opacity: 1 !important}' +
+ '.__noscriptPlaceholder__1 > .msg { text-align: center !important; bottom: 0 !important; left: 0 !important; width: 100% !important; position: absolute !important; font-size: 12px !important; font-weight: bold !important; font-family: sans-serif !important; }';
+ break;
+ case "clearClick":
+ sheet = "body:not([id]) { cursor: auto !important } " +
+ ".__noscriptOpaqued__ { opacity: 1 !important; visibility: visible; filter: none !important } " +
+ "iframe.__noscriptOpaqued__ { display: block !important; } " +
+ "object.__noscriptOpaqued__, embed.__noscriptOpaqued__ { display: inline !important } " +
+ ".__noscriptJustOpaqued__ { opacity: 1 !important } " +
+ ".__noscriptScrolling__ { overflow: auto !important; min-width: 52px !important; min-height: 52px !important } " +
+ ".__noscriptNoScrolling__ { overflow: hidden !important } " +
+ ".__noscriptHidden__ { visibility: hidden !important } " +
+ ".__noscriptBlank__ { background-color: white !important; color: white !important; border-color: white !important; background-image: none !important }";
+
+ break;
+ default:
+ return;
+ }
+ this.updateStyleSheet(sheet, value);
+ },
+
+ get sss() {
+ delete this.sss;
+ try {
+ return (this.sss = Cc["@mozilla.org/content/style-sheet-service;1"]
+ .getService(Ci.nsIStyleSheetService));
+ } catch(e) {
+ return (this.sss = null);
+ }
+ },
+
+ _sheets: new Set(),
+ updateStyleSheet: function(sheet, enabled) {
+ const sss = this.sss;
+ if (!sss) return;
+ const SHEET_TYPE = sss.AGENT_SHEET;
+ ns.dump(`${enabled ? "Adding" : "Removing"} CSS:\n${sheet}`);
+ const uri = IOS.newURI("data:text/css;charset=utf8," + encodeURIComponent(sheet), null, null);
+ if (sss.sheetRegistered(uri, SHEET_TYPE)) {
+ if (!enabled) {
+ sss.unregisterSheet(uri, SHEET_TYPE);
+ this._sheets.delete(sheet);
+ }
+ } else {
+ try {
+ if (enabled) {
+ sss.loadAndRegisterSheet(uri, SHEET_TYPE);
+ this._sheets.add(sheet);
+ }
+ } catch(e) {
+ this.log("[NoScript CSS] Can't register " + uri + ", " + e);
+ }
+ }
+ },
+ disposeStyleSheets() {
+ for (let sheet of this._sheets) this.updateStyleSheet(sheet, false);
+ },
+
+ get getString() {
+ delete this.getString;
+ const ss = new this.Strings("noscript");
+ return (this.getString = (name, parms) => ss.getString(name, parms));
+ },
+
+ get Strings() {
+ delete this.Strings;
+ INCLUDE('Strings');
+ return (this.Strings = Strings);
+ },
+
+ _inited: false,
+ POLICY_NAME: "maonoscript",
+ prefService: null,
+ caps: null,
+ defaultCaps: null,
+ policyPB: null,
+ prefs: null,
+ mozJSPref: null,
+ mozJSEnabled: true,
+ disabled: false,
+
+ // random resource aliases
+ contentBase: null,
+ skinBase: null,
+ hideObjClassName: "__noscriptHideObj__",
+ get hideObjClassNameRx() {
+ const v = new RegExp("\\b" + this.hideObjClassName + "\\s*", "g");
+ this.__defineGetter__("hideObjClassNameRx", function() { return v; });
+ return v;
+ },
+ pluginPlaceholder: "",
+
+ _initResources: function() {
+ const ios = IOS;
+ var resProt = ios.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
+ var base;
+ for (var r of ["skin", "content"]) {
+ base = "noscript_" + Math.random();
+ resProt.setSubstitution(base, ios.newURI("chrome:noscript/" + r + "/", null, null));
+ this[r + "Base"] = "resource://" + base + "/";
+ }
+ this.pluginPlaceholder = this.skinBase + "icon32.png";
+ },
+
+ childProcess: false,
+ init: function() {
+ if (this._inited) return false;
+
+ let t = Date.now();
+
+ Thread.hostRunning = true;
+
+ this._inited = true;
+
+ this.beforeInit();
+
+ this._initResources();
+
+ const prefSrv = this.prefService = Cc["@mozilla.org/preferences-service;1"]
+ .getService(Ci.nsIPrefService).QueryInterface(Ci.nsIPrefBranch);
+
+ this.caps = prefSrv.getBranch("capability.policy.");
+ this.defaultCaps = prefSrv.getDefaultBranch(this.caps.root);
+
+ this.policyPB = prefSrv.getBranch("capability.policy." + this.POLICY_NAME + ".");
+ this.prefs = prefSrv.getBranch("noscript.");
+
+ this.policyPB.addObserver("sites", this, true);
+
+ this.prefs.addObserver("", this, true);
+ this.mozJSPref = prefSrv.getBranch("javascript.");
+ this.mozJSPref.addObserver("enabled", this, true);
+
+ this.mandatorySites.sitesString = this.getPref("mandatory", "chrome: about: resource: [System Principal]");
+
+ this.captureExternalProtocols();
+
+ this._batchPrefs = true;
+ for (var p of [
+ "consoleDump", "consoleLog", // first, so we can log side effects
+ "autoAllow",
+ "allowedMimeRegExp", "hideOnUnloadRegExp", "requireReloadRegExp",
+ "contentBlocker", "alwaysShowObjectSources",
+ "filterXPost", "filterXGet",
+ "filterXGetRx", "filterXGetUserRx",
+ "filterXExceptions",
+ "forbidJava", "forbidFlash", "forbidSilverlight", "forbidPlugins", "forbidMedia", "forbidFonts", "forbidWebGL",
+ "forbidIFrames", "forbidIFramesContext", "forbidFrames",
+ "forbidMetaRefresh",
+ "forbidXBL", "forbidXHR",
+ "liveConnectInterception", "audioApiInterception",
+ "inclusionTypeChecking", "nosniff",
+ "alwaysBlockUntrustedContent",
+ "global", "ignorePorts",
+ "injectionCheck", "injectionCheckSubframes",
+ "jsredirectIgnore", "jsredirectFollow", "jsredirectForceShow",
+ "jsHack", "jsHackRegExp",
+ "emulateFrameBreak",
+ "nselNever", "nselForce",
+ "showBlankSources", "showPlaceholder", "showUntrustedPlaceholder",
+ "collapseObject",
+ "temp", "untrusted", "gtemp",
+ "dropXssProtection",
+ "flashPatch", "silverlightPatch",
+ "allowHttpsOnly",
+ "truncateTitle", "truncateTitleLen",
+ "whitelistRegExp", "proxiedDNS", "asyncNetworking",
+ "fakeScriptLoadEvents.enabled", "fakeScriptLoadEvents.onlyRequireJS", "fakeScriptLoadEvents.exceptions", "fakeScriptLoadEvents.docExceptions",
+ "restrictSubdocScripting", "cascadePermissions", "globalHttpsWhitelist"
+ ]) {
+ try {
+ this.syncPrefs(this.prefs, p);
+ } catch(e) {
+ dump("[NoScript init error] " + e.message + ":" + e.stack + " setting " + p + "\n");
+ }
+ }
+ this._batchPrefs = false;
+
+ this.setupJSCaps();
+
+ if (!this.locked) {
+ // init jsPolicySites from prefs
+ this.syncPrefs(this.policyPB, "sites");
+ }
+
+ this.syncPrefs(this.mozJSPref, "enabled");
+ if (this.consoleDump) ns.dump("T1 " + (Date.now() - t));
+ if (this.getPref("tempGlobal", false))
+ this.jsEnabled = false;
+
+ this.afterInit();
+
+ if (this.consoleDump) this.dump(`Init done in ${Date.now() - t}`);
+ return true;
+ },
+
+
+ onContentInit: function() {
+ this._batchPrefs = true;
+ ["allowClipboard", "allowLocalLinks"].forEach((p) => this.syncPrefs(this.pref, p), this);
+ this._batchPrefs = false;
+ this.setupJSCaps();
+ },
+ getService() {
+ try {
+ return Cc[this.contractID].getService().wrappedJSObject;
+ } catch(e) {
+ }
+ return null;
+ },
+ _registered: false,
+ registerComponent() {
+ if (this._registered) return;
+ this.dump("Registering NoScript Service");
+ let current = this.getService();
+ if (current) {
+ try {
+ current.unregisterComponent();
+ } catch (e) {
+ Cu.reportError(e);
+ }
+ }
+ let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
+ try {
+ registrar.registerFactory(this.classID, this.classDescription, this.contractID, this);
+ this.onDisposal(() => this.unregisterComponent());
+ } catch(e) {
+ if (!registrar.isCIDRegistered(this.classID)) Cu.reportError(e);
+ return;
+ }
+ OS.notifyObservers(this, "NoScript.ServiceReady", null);
+ this._registered = true;
+ },
+ unregisterComponent() {
+ if (!this._registered) return;
+ this._registered = false;
+ let current = this.getService();
+ if (current !== this) {
+ Cu.reportError("Current NoScript service is different than this: live update?");
+ return;
+ }
+ let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
+ if (registrar.isCIDRegistered(this.classID)) {
+ registrar.unregisterFactory(this.classID, this);
+ }
+ },
+
+ _disposalTasks: [],
+ onDisposal: function(task) {
+ this._disposalTasks.push(task);
+ },
+ dispose: function() {
+ try {
+ if(!this._inited) return;
+ this._inited = false;
+ OS.notifyObservers(this, "NoScript.Dispose", null);
+ for (let t of this._disposalTasks) try {
+ ns.dump(`Executing disposal task ${t}`);
+ t();
+ } catch (e) {
+ Cu.reportError(e);
+ }
+
+ this.shouldLoad = this.shouldProcess = CP_NOP;
+ let catMan = this.categoryManager;
+ try {
+ catMan.deleteCategoryEntry("content-policy", this.contractID, false);
+ } catch (e) {}
+
+ if (this.httpStarted) {
+ this.requestWatchdog.dispose();
+ try {
+ catMan.deleteCategoryEntry("net-channel-event-sinks", this.contractID, false);
+ } catch (e) {}
+
+ }
+ try {
+ Cc['@mozilla.org/docloaderservice;1'].getService(nsIWebProgress).removeProgressListener(this);
+ } catch (e) {}
+
+ this.prefs.removeObserver("", this);
+ this.mozJSPref.removeObserver("enabled", this);
+ this.resetJSCaps();
+
+ this.savePrefs();
+ this.disposeStyleSheets();
+ if(this.consoleDump & LOG_LEAKS) this.reportLeaks();
+ if (typeof PolicyState === "object") PolicyState.reset();
+ } catch(e) {
+ Cu.reportError(e);
+ this.dump(e + " while disposing.");
+ } finally {
+ Thread.hostRunning = false;
+ }
+
+ },
+
+
+ global: this,
+ reportLeaks: function() {
+ for (let k of Object.keys(global)) {
+ this.dump(`${k} = ${global[k]}\n`);
+ }
+ },
+
+ get profiler() {
+ delete this.profiler;
+ INCLUDE("Profiler");
+ return (this.profiler = Profiler);
+ },
+
+ httpStarted: false,
+ get requestWatchdog() {
+ if (ns.consoleDump) ns.dump("RW kickstart at " + new Error().stack);
+ this.httpStarted = true;
+ this.initContentPolicy(true);
+
+ delete this.requestWatchdog;
+ return (this.requestWatchdog = new RequestWatchdog());
+ },
+
+ captureExternalProtocols: function() {
+ try {
+ const pb = this.prefService.getDefaultBranch("network.protocol-handler.");
+ if (this.getPref("fixURI", true)) {
+ try {
+ pb.setBoolPref("expose-all", true);
+ } catch(e1) {}
+ var prots = [];
+ for (var key of pb.getChildList("expose.", {})) {
+ try {
+ pb.setBoolPref(key, true);
+ prots.push(key.replace("expose.", ""));
+ if (pb.prefHasUserValue(key)) pb.clearUserPref(key);
+ } catch(e1) {}
+ }
+ if (prots.length) this.extraCapturedProtocols = prots;
+ }
+ } catch(e) {}
+ },
+
+ extraCapturedProtocols: null,
+
+ mandatorySites: new PolicySites(),
+ isMandatory: function(s) {
+ return s && this.mandatorySites.matches(s);
+ },
+
+ tempSites: new PolicySites(),
+ gTempSites: new PolicySites(),
+ isTemp: function(s) {
+ return s in (this.globalJS ? this.gTempSites : this.tempSites).sitesMap;
+ },
+ setTemp: function(s, b) {
+ const sites = {
+ "temp": this.tempSites,
+ "gtemp": this.gTempSites
+ };
+ for (let p in sites) {
+ if (b) {
+ if (p[0] !== "g" || this.globalJS) {
+ sites[p].add(s);
+ }
+ } else {
+ sites[p].remove(s, true, true); // keeps up and down, see #eraseTemp()
+ }
+ }
+ return b;
+ },
+
+ untrustedSites: new PolicySites(),
+ isUntrusted: function(s) {
+ return !!this.untrustedSites.matches(s);
+ },
+ setUntrusted: function(s, b) {
+ var change = b ? this.untrustedSites.add(s) : this.untrustedSites.remove(s, false, true);
+ if (change) {
+ this.persistUntrusted();
+ }
+ return b;
+ },
+ persistUntrusted: function(snapshot) {
+ if (typeof(snapshot) === "string") {
+ this.untrustedSites.sitesString = snapshot;
+ }
+ this.untrustedSites.toPref(this.prefs, "untrusted");
+ },
+
+ manualSites: new PolicySites(),
+ isManual: function(s) {
+ return !!this.manualSites.matches(s);
+ },
+ setManual: function(ss, b) {
+ if (b) this.manualSites.add(ss);
+ else {
+ if (!ss.push) ss = [ss];
+ try {
+ this.manualSites.sitesString = this.manualSites.sitesString.replace(
+ new RegExp("(^|\\s)(?:" +
+ ss.map(function(k) {
+ k = k.replace(/[\.\-]/g, '\\$&');
+ if (k.indexOf(":") < 0) k = "(?:[a-z\\-]+:\/\/)?(?:[^\\s/]+\.)?" + k; // match protocols and subdomains
+ if (!/:\d+$/.test(k)) k += "(?::\\d+)?"; // match ports
+ return k;
+ }).join("|") +
+ ")(?=\\s|$)", "ig"),
+ "$1"
+ );
+ } catch(e) {
+ this.manualSites.remove(ss);
+ }
+ }
+ return b;
+ },
+
+ autoTemp: function(site) {
+ if (!(this.isUntrusted(site) || this.isManual(site) || this.isJSEnabled(site))) {
+ this.setTemp(site, true);
+ this.setJSEnabled(site, true);
+ return true;
+ }
+ return false;
+ },
+
+ mustCascadeTrust: function(sites, temp) {
+ var untrustedGranularity = this.getPref("untrustedGranularity", 3);
+ /* noscript.untrustedGranularity controls how manually whitelisting
+ a domain affects the untrusted blacklist status of descendants:
+ 0 - always delist descendants from the untrusted blacklist
+ 1 - keep descendants blacklisted for temporary allow actions
+ 2 - keep descendants blacklisted for permanent allow actions
+ 3 - (default) always keep descendants blacklisted
+ 4 - delist blacklisted descendants of a site marked as untrusted
+ All these values can be put in OR (the 3 default is actually 2 | 1)
+ */
+ var single = !(typeof(site) == "object" && ("push" in site)); // not an array
+ return !((untrustedGranularity & 1) && !temp || (untrustedGranularity & 2) && temp) ||
+ (untrustedGranularity & 4) && single && this.isUntrusted(site);
+ },
+
+ _unsafeSchemeRx: /^(?:ht|f)tp:\/\//,
+ isForbiddenByHttpsStatus: function(site) {
+ switch(this.allowHttpsOnly) {
+ case 0:
+ return false;
+ case 1:
+ return this._unsafeSchemeRx.test(site) && this.isProxied(site);
+ case 2:
+ return this._unsafeSchemeRx.test(site);
+ }
+ return false;
+ },
+ _isHttpsAndNotUntrusted: function(s) {
+ return /^https:/i.test(s) && !this.isUntrusted(s);
+ },
+ isGlobalHttps: function(win, /*optional */ s) {
+ let allow = false;
+ if (s && !this._isHttpsAndNotUntrusted(s)) return false;
+ if (!win) return !!s;
+ for (;; win = win.parent) {
+ let site = this.getDocSite(win.document);
+ if (!(allow = s && site === s || this._isHttpsAndNotUntrusted(site)) || win === win.parent)
+ break;
+ s = site;
+ }
+
+ return allow;
+ },
+ get proxyService() {
+ delete this.proxyService;
+ return (this.proxyService = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService(Ci.nsIProtocolProxyService));
+ },
+
+ isProxied: function(site) {
+ this.isProxied = "proxyConfigType" in this.proxyService ? this._isProxied : this._isProxiedSite;
+ return this.isProxied();
+ },
+ _isProxied: function() {
+ switch (this.proxyService.proxyConfigType) {
+ case 0: // direct
+ case 5: // system
+ return false;
+ }
+ return true;
+ },
+ _isProxiedSite: function(uri) { // Gecko < 2 has no proxyConfigType, so we must resolve per URI
+ try {
+ if (!(uri instanceof Ci.nsIURI)) {
+ uri = IOS.newURI(uri || "https://noscript.net/", null, null);
+ }
+ return this.proxyService.resolve(uri, 0).type != "direct";
+ } catch(e) {
+ return false;
+ }
+ },
+
+ jsPolicySites: new PolicySites(),
+ isJSEnabled: function (s, window) {
+ if (this.globalJS) {
+ return !(this.alwaysBlockUntrustedContent && this.untrustedSites.matches(s));
+ }
+
+ if (this.untrustedSites.matches(s) || this.isForbiddenByHttpsStatus(s)) return false;
+
+ let enabled = !!(this.jsPolicySites.matches(s));
+
+ if (window) {
+ let top = window.top;
+ enabled = enabled ||
+ this.globalHttpsWhitelist && s.startsWith("https:") && (window === top || this.isGlobalHttps(window));
+ if (enabled ? this.restrictSubdocScripting : this.cascadePermissions) {
+ let topOrigin = this.getPrincipalOrigin(this.getPrincipal(top.document));
+ if (this.isBrowserOrigin(topOrigin)) {
+ enabled = true;
+ } else {
+ let topSite = this.getSite(topOrigin);
+ if (topSite !== s) enabled = this.isJSEnabled(topSite, enabled && this.restrictSubdocScripting && window);
+ }
+ }
+ }
+ return enabled;
+ },
+ setJSEnabled: function(site, is, fromScratch, cascadeTrust) {
+ const ps = this.jsPolicySites;
+ if (fromScratch) ps.sitesString = this.mandatorySites.sitesString;
+ if (is) {
+ ps.add(site);
+ if (!fromScratch) {
+ if (this.untrustedSites.remove(site, false, !cascadeTrust))
+ this.persistUntrusted();
+
+ this.setManual(site, false);
+ }
+ } else {
+ ps.remove(site, false, true);
+
+ if (typeof(site) == "string") {
+ this._removeAutoPorts(site);
+ }
+
+ if (this.forbidImpliesUntrust) {
+ this.setUntrusted(site, true);
+ } else {
+ this.setManual(site, true);
+ }
+ }
+
+ this.flushCAPS();
+
+ return is;
+ },
+
+ _buggyIPV6rx: /^[^/:]+:\/\/[^[](?:[0-9a-f]*:){2}/,
+ getPrincipal(nodeOrWindow) {
+ return nodeOrWindow &&
+ (nodeOrWindow.nodePrincipal || nodeOrWindow.document && nodeOrWindow.document.nodePrincipal) ||
+ null;
+ },
+ getPrincipalOrigin(p) {
+ try {
+ let origin = p.originNoSuffix || p.origin;
+ if (this._buggyIPV6rx.test(origin)) {
+ try {
+ let uri = p.URI;
+ let hostPort = uri.hostPort;
+ if (hostPort && hostPort[0] === '[') origin = uri.scheme + "://" + hostPort;
+ } catch (e) {
+ ns.log(e);
+ }
+ }
+ return origin;
+ } catch (e) {
+ if (ns.consoleDump) ns.dump(`${e} grabbing origin for ${p.URI.spec}, falling back to full URI`);
+ }
+ return p.URI.spec;
+ },
+
+ _removeAutoPorts: function(site) {
+ // remove temporary permissions implied by this site for non-standard ports
+
+ const portRx = /:\d+$/;
+
+ if (portRx.test(site)) {
+ if (/:0$/.test(site)) site = site.replace(portRx, '');
+ else return;
+ }
+
+ const tempSites = this.tempSites;
+ var portSites = this.tempSites.sitesString.match(/\S+:[1-9]\d*(?=\s|$)/g);
+ if (!portSites) return;
+
+
+ var domain = SiteUtils.domainMatch(site);
+ var filter;
+
+ if (domain) {
+ const dotDomain = "." + domain;
+ const dLen = dotDomain.length;
+ filter = function(d) {
+ d = this.getDomain(d);
+ return d === domain || d.length > dLen && d.slice(- dLen) === dotDomain;
+ };
+ } else {
+ filter = function(s) { return s.replace(portRx, '') === site; };
+ }
+
+ var doomedSites = portSites.filter(filter, this);
+
+ if (doomedSites.length) {
+ tempSites.remove(doomedSites);
+ this.jsPolicySites.remove(doomedSites);
+ }
+ },
+
+ get forbidImpliesUntrust() {
+ return this.globalJS || this.autoAllow || this.getPref("forbidImpliesUntrust", false);
+ },
+
+ portRx: /:\d+$/,
+ _ipShorthandRx: /^(https?:\/\/)((\d+\.\d+)\.\d+)\.\d+(?::\d|$)/,
+ checkShorthands: function(site, policy) {
+ if (!site) return false;
+
+ if (this.whitelistRegExp && this.whitelistRegExp.test(site)) {
+ return true;
+ }
+
+ if (!policy) policy = this.jsPolicySites;
+
+ if (this.ignorePorts && policy.matches(site.replace(/:\d+$/, '')))
+ return true;
+
+ let map = policy.sitesMap;
+ let portRx = this.portRx;
+ let hasPort = portRx.test(site);
+
+ // port matching, with "0" as port wildcard and * as nth level host wildcard
+ let key = hasPort ? site.replace(portRx, ":0") : site;
+ if (key in map || site in map) return true;
+ var keys = site.split(".");
+ if (keys.length > 1) {
+ let prefixMatch = keys[0].match(/^(?:ht|f)tps?:\/\//i);
+ if (prefixMatch) {
+ let prefix = prefixMatch[0] + "*.";
+ while (keys.length > 2) {
+ keys.shift();
+ key = prefix + keys.join(".");
+ if (key in map || hasPort && key.replace(portRx, ":0") in map) return true;
+ }
+ }
+ }
+
+ // check IP leftmost portion up to 2nd byte (e.g. [http://]192.168 or [http://]10.0.0)
+ let m = site.match(this._ipShorthandRx);
+ return m && (m[2] in map || m[3] in map || (m[1] + m[2]) in map || (m[1] + m[3]) in map);
+ },
+ flushCAPS: function(sitesString) {
+ const ps = this.getPermanentSites();
+ if (sitesString) ps.sitesString = sitesString;
+ try {
+ ps.toPref(this.policyPB);
+ } catch (e) {
+ if (!this.childProcess) throw e;
+ }
+ },
+ get injectionChecker() { return this. requestWatchdog.injectionChecker; },
+
+ splitList: function(s) {
+ return s ?/^[,\s]*$/.test(s) ? [] : s.split(/\s*[,\s]\s*/) : [];
+ },
+
+ savePrefs: function() {
+ if (this.childProcess) return false;
+ if (this.webExt && this.webExt.started) {
+ try {
+ this.webExt.saveData();
+ } catch (e) {
+ Cu.reportError(e);
+ }
+ }
+ var res = this.prefService.savePrefFile(null);
+ return res;
+ },
+
+ sortedSiteSet: function(s) { return SiteUtils.sortedSet(s); },
+ globalJS: false,
+ get jsEnabled() {
+ return this.mozJSEnabled && this.globalJS;
+ },
+
+ set jsEnabled(enabled) {
+ try {
+ if (this.locked || this.prefs.prefIsLocked("global")) {
+ enabled = false;
+ }
+ } catch (e) {}
+ this.globalJS = enabled;
+ const prefName = "default.javascript.enabled";
+ try {
+ this.caps.clearUserPref(prefName);
+ } catch(e) {}
+
+ this.setPref("global", enabled);
+ if (enabled) {
+ try {
+ this.mozJSPref.setBoolPref("enabled", true);
+ } catch (e) {}
+ }
+ return enabled;
+ },
+
+ getSite(url) {
+ return SiteUtils.getSite(url);
+ },
+ getDocSite(doc) {
+ return this.getSite(this.getPrincipalOrigin(this.getPrincipal(doc)));
+ },
+
+ getQuickSite: function(url, level) {
+ var site = null;
+ if (level > 0 && !this.jsEnabled) {
+ site = this.getSite(url);
+ var domain;
+ if (level > 1 && (domain = this.getDomain(site))) {
+ site = level > 2 ? this.getBaseDomain(domain) : domain;
+ }
+ }
+ return site;
+ },
+
+ get preferredSiteLevel() {
+ return this.getPref("showAddress", false) ? 1 : this.getPref("showDomain", false) ? 2 : 3;
+ },
+
+
+ getDomain: function(site, force) {
+ try {
+ let url = site;
+ if (typeof site === "string") {
+ if (site.endsWith(":")) return "";
+ url = IOUtil.newURI(site);
+ }
+ const host = url.host;
+ return force || (this.ignorePorts || url.port === -1) && host[host.length - 1] != "." &&
+ (host.lastIndexOf(".") > 0 || host === "localhost") ? host : '';
+ } catch(e) {
+ return "";
+ }
+ },
+
+ get _tldService() {
+ delete this._tldService;
+ return (this._tldService = IOUtil.TLDService);
+ },
+
+ getBaseDomain: function(domain) {
+ if (!domain || DNS.isIP(domain)) return domain; // IP
+
+ var pos = domain.lastIndexOf('.');
+ if (pos < 1 || (pos = domain.lastIndexOf('.', pos - 1)) < 1) return domain;
+
+ try {
+ return this._tldService.getBaseDomainFromHost(domain);
+ } catch(e) {
+ this.dump(e);
+ }
+ return domain;
+ },
+ getPublicSuffix: function(domain) {
+ try {
+ return this._tldService.getPublicSuffixFromHost(domain);
+ } catch(e) {}
+ return "";
+ },
+
+ delayExec: function(callback, time) {
+ Thread.delay(callback, time, this, Array.slice(arguments, 2));
+ },
+
+ RELOAD_NO: -1,
+ RELOAD_CURRENT: 1,
+ RELOAD_ALL: 0,
+ safeCapsOp: function(callback, reloadPolicy, nosave) {
+ this.delayExec(function() {
+ try {
+ callback(this);
+ if (!nosave) this.savePrefs();
+ this.reloadWhereNeeded(reloadPolicy);
+ } catch(e) {
+ this.dump("FAILED TO SAVE PERMISSIONS! " + e + "," + e.stack);
+ }
+ }, 0);
+ },
+
+ getSnapshot() {
+ return {
+ trusted: this.jsPolicySites.sitesString,
+ untrusted: this.untrustedSites.sitesString,
+ manual: this.manualSites.sitesString,
+ temp: this.tempSites.sitesString,
+ objectWhitelist: this.objectWhitelist,
+ };
+ },
+ setSnapshot(snapshot) {
+ this.jsPolicySites.sitesString = snapshot.trusted;
+ this.untrustedSites.sitesString = snapshot.untrusted;
+ this.manualSites.sitesString = snapshot.manual;
+ this.tempSites.sitesString = snapshot.temp;
+ this.objectWhitelist = snapshot.objectWhitelist;
+ this.objectWhitelistLen = Object.keys(this.objectWhitelist).length;
+ },
+
+ getPermanentSites: function(whitelist, templist) {
+ whitelist = (whitelist || this.jsPolicySites).clone();
+ whitelist.remove((templist || this.tempSites).sitesList, true, true);
+ return whitelist;
+ },
+
+ eraseTemp: function() {
+ // remove temporary PUNCTUALLY:
+ // keeps ancestors because the may be added as permanent after the temporary allow;
+ // keeps descendants because they may already have been made permanent before the temporary, and then shadowed
+ this.jsPolicySites.remove(this.tempSites.sitesList, true, true);
+ // if allowed in blacklist mode, put back temporarily allowed in blacklist
+ if (this.untrustedSites.add(this.gTempSites.sitesList)) {
+ this.persistUntrusted();
+ }
+
+ this.tempSites.sitesString = this.gTempSites.sitesString = "";
+
+ this.setPref("temp", "");
+ this.setPref("gtemp", "");
+
+ this.setJSEnabled(this.mandatorySites.sitesList, true); // add mandatory
+ this.resetAllowedObjects();
+ if (this.hasClearClickHandler) this.clearClickHandler.resetWhitelist();
+ },
+
+ _observingPolicies: false,
+ _editingPolicies: false,
+ setupJSCaps: function() {
+ if (this._editingPolicies) return;
+
+ this.resetJSCaps();
+ if (!(this.allowLocalLinks || this.allowClipboard)) return;
+
+ this._editingPolicies = true;
+ try {
+ const POLICY_NAME = this.POLICY_NAME;
+ var prefArray;
+ var prefString = "", originalPrefString = "";
+ var exclusive = this.getPref("excaps", true);
+ try {
+
+ prefArray = this.splitList(prefString = originalPrefString =
+ (this.caps.prefHasUserValue("policynames") ? this.caps.getCharPref("policynames")
+ : this.getPref("policynames") // saved value from dirty exit
+ )
+ );
+ var pcount = prefArray.length;
+ while (pcount-- > 0 && prefArray[pcount] != POLICY_NAME);
+ if (pcount == -1) { // our policy is not installed, should always be so unless dirty exit
+ this.setPref("policynames", originalPrefString);
+ if (exclusive || prefArray.length === 0) {
+ prefString = POLICY_NAME;
+ } else {
+ prefArray.push(POLICY_NAME);
+ prefString = prefArray.join(' ');
+ }
+ }
+ prefString = prefString.replace(/,/g, ' ').replace(/\s+/g, ' ').replace(/^\s+/, '').replace(/\s+$/, '');
+
+ } catch(ex) {
+ prefString = POLICY_NAME;
+ }
+
+ this.caps.setCharPref(POLICY_NAME + ".javascript.enabled", "allAccess");
+
+ try {
+ this.caps.clearUserPref("policynames");
+ } catch(e) {}
+ this.defaultCaps.setCharPref("policynames", prefString);
+
+
+ if (!this._observingPolicies) {
+ this.caps.addObserver("policynames", this, true);
+ this._observingPolicies = true;
+ }
+ } catch(ex) {
+ dump(ex.message);
+ }
+ this._editingPolicies = false;
+ },
+ resetJSCaps: function() {
+ try {
+ this.caps.clearUserPref("default.javascript.enabled");
+ } catch(ex) {}
+ if (this._observingPolicies) {
+ this.caps.removeObserver("policynames", this, false);
+ this._observingPolicies = false;
+ }
+ try {
+ let POLICY_NAME = this.POLICY_NAME;
+ let exclusive = this.getPref("excaps", true) && (this.allowLocalLinks || this.allowClipboard);
+ let prefString = SiteUtils.splitString(
+ exclusive ? this.getPref("policynames", "") : this.caps.getCharPref("policynames")
+ ).filter((s) => s && s !== POLICY_NAME).join(" ");
+
+ if (prefString) {
+ this.caps.setCharPref("policynames", prefString);
+ } else {
+ try {
+ this.caps.clearUserPref("policynames");
+ } catch(ex) {}
+ }
+ } catch(ex) {}
+ },
+
+ getPref: function(name, def) {
+ const PREFS = Ci.nsIPrefBranch;
+ const prefs = this.prefs;
+ try {
+ switch (prefs.getPrefType(name)) {
+ case PREFS.PREF_STRING:
+ return prefs.getCharPref(name);
+ case PREFS.PREF_INT:
+ return prefs.getIntPref(name);
+ case PREFS.PREF_BOOL:
+ return prefs.getBoolPref(name);
+ }
+ } catch(e) {}
+ return def || "";
+ },
+
+ setPref: function(name, value) {
+ const prefs = this.prefs;
+ try {
+ switch (typeof(value)) {
+ case "string":
+ prefs.setCharPref(name,value);
+ break;
+ case "boolean":
+ prefs.setBoolPref(name,value);
+ break;
+ case "number":
+ prefs.setIntPref(name,value);
+ break;
+ default:
+ throw new Error("Unsupported type " + typeof(value) + " for preference " + name);
+ }
+ } catch(e) {
+ const PREFS = Ci.nsIPrefBranch;
+ try {
+ switch (prefs.getPrefType(name)) {
+ case PREFS.PREF_STRING:
+ prefs.setCharPref(name, value);
+ break;
+ case PREFS.PREF_INT:
+ prefs.setIntPref(name, parseInt(value));
+ break;
+ case PREFS.PREF_BOOL:
+ prefs.setBoolPref(name, !!value && value != "false");
+ break;
+ }
+ } catch(e2) {}
+ }
+ },
+
+ getAllowObjectMessage: function(extras) {
+ let url = SiteUtils.crop(extras.url).replace(/\S{80}/g, "$&\n");
+ let details = extras.mime + " " + (extras.tag || (extras.mime === "WebGL" ? "<CANVAS>" : "<OBJECT>")) + " / " + extras.originSite;
+ return this.getString("allowTemp", [url + "\n(" + details + ")\n"]);
+ },
+
+ get dom() {
+ delete this.dom;
+ return (this.dom = DOM);
+ },
+ get wan() {
+ delete this.wan;
+ ABE; // kickstart
+ return (this.wan = WAN);
+ },
+
+ os: OS,
+ siteUtils: SiteUtils,
+ mimeService: null,
+
+ shouldLoad: function(aContentType) {
+ if (aContentType === 5) {
+ this.requestWatchdog;
+ return this.shouldLoad.apply(this, arguments);
+ }
+ return CP_OK;
+ },
+ shouldProcess: CP_NOP,
+
+ initContentPolicy: function(force) {
+ if (force) INCLUDE("Policy");
+ else if (!this.httpStarted) return;
+
+ const last = this.getPref("cp.last");
+ const catMan = this.categoryManager;
+ const cat = "content-policy";
+ if (last)
+ try {
+ catMan.deleteCategoryEntry(cat, this.contractID, false);
+ } catch (e) {}
+
+ let cpMixin;
+
+ if (this.httpStarted || force) {
+ cpMixin = this.disabled ||
+ (this.globalJS &&
+ !(this.alwaysBlockUntrustedContent || this.contentBlocker || HTTPS.httpsForced)) ? NOPContentPolicy
+ : MainContentPolicy;
+ MIXIN(this, cpMixin);
+ } else cpMixin = null;
+
+ if (cpMixin !== NOPContentPolicy && (last || this.mimeService)) {
+ // removing and adding the category late in the game allows to be the latest policy to run,
+ // and nice to AdBlock Plus
+ if (this.consoleDump) this.dump("Adding content policy.");
+ catMan.addCategoryEntry(cat, this.contractID, this.contractID, false, true);
+ } else this.dump("No category?!" + (cpMixin === NOPContentPolicy) + ", " + last + ", " + this.mimeService);
+
+ catMan.addCategoryEntry("net-channel-event-sinks", this.contractID, this.contractID, false, true);
+
+
+ if (!this.mimeService) {
+ this.initSafeJSRx();
+ INCLUDE(`MimeService${IPC.child ? '' : 'Parent'}`);
+ this.mimeService = MimeService;
+ }
+ },
+
+ REQDATA_HEADER: "X-NoScript-ReqData",
+ REQDATA_SERIALIZABLE: ["checkWindowName", "protectName"],
+ serializeReqData(req) {
+ let reqData = this.reqData(req);
+ if (!reqData.policyHints) try {
+ req.setResponseHeader(this.REQDATA_HEADER,
+ JSON.stringify(reqData, this.REQDATA_SERIALIZABLE),
+ false);
+ } catch (e) {
+ this.log(`Cannot serialize reqData: ${uneval(reqData)}`);
+ }
+ },
+ unserializeReqData: IPC.parent ? function() {} : function(req) {
+ if (req instanceof Ci.nsIHttpChannel) {
+ try {
+ Object.assign(ns.reqData(req), JSON.parse(req.getResponseHeader(this.REQDATA_HEADER)));
+ } catch (e) {
+ //Cu.reportError(e);
+ return;
+ }
+ }
+ },
+ reqData(req, remove = false) {
+ return IOUtil.reqData(req, "net.noscript.channelData", remove);
+ },
+
+ guessMime: function(uriOrExt) {
+ try {
+ let ext = (uriOrExt instanceof Ci.nsIURL) ? uriOrExt.fileExtension
+ : (uriOrExt instanceof Ci.nsIURI) ? ((ext = uriOrExt["path" in uriOrExt ? "path" : "pathQueryRef"]).includes(".") ? ext.split(".").pop() : "")
+ : uriOrExt;
+ return typeof ext === "string" && this.mimeService.getTypeFromExtension(ext) || "";
+ } catch(e) {
+ return "";
+ }
+ },
+
+ pluginForMime: function(mimeType) {
+ if (!mimeType) return null;
+ try {
+ var w = DOM.mostRecentBrowserWindow;
+ if (!(w && w.navigator)) return null;
+ var mime = w.navigator.mimeTypes.namedItem(mimeType);
+ return mime && mime.enabledPlugin || null;
+ } catch(e) { return null; }
+ },
+
+ _mediaTypeRx: /^(?:vide|audi)o\/|\/ogg$/i,
+ isMediaType: function(mimeType) {
+ return this._mediaTypeRx.test(mimeType);
+ },
+
+ versionComparator: Cc["@mozilla.org/xpcom/version-comparator;1"].getService(Ci.nsIVersionComparator),
+ geckoVersion: ("@mozilla.org/xre/app-info;1" in Cc) ? Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).platformVersion : "0.0",
+ geckoVersionCheck: function(v) { return this.versionComparator.compare(this.geckoVersion, v) },
+
+ safeJSRx: false,
+ initSafeJSRx: function() {
+ try {
+ this.safeJSRx = new RegExp("^\\s*" + this.getPref("safeJSRx", "") + "\\s*;?\\s*$");
+ } catch(e) {
+ this.safeJSRx = false;
+ }
+ },
+ isSafeJSURL: function(url) {
+ var js = url.replace(/^javascript:/i, "");
+ return this.safeJSRx && js != url && this.safeJSRx.test(js);
+ },
+
+ isFirebugJSURL: function(url) {
+ return url == "javascript: eval(__firebugTemp__);"
+ },
+
+ isExternalScheme: function(scheme) {
+ try {
+ return IOS.getProtocolHandler(scheme).scheme != scheme;
+ } catch(e) {
+ return false;
+ }
+ },
+ normalizeExternalURI: function(uri) {
+ var uriSpec = uri.spec;
+ var uriValid = URIValidator.validate(uriSpec);
+ var fixURI = this.getPref("fixURI", true) &&
+ this.getPref("fixURI.exclude", "").split(/[^\w\-]+/)
+ .indexOf(uri.scheme) < 0;
+ var msg;
+ if (!uriValid) {
+ if (fixURI) {
+ uriSpec = uriSpec
+ .replace(/[\s\x01-\x1f\0]/g, " ") // whitespace + null + control chars all to space
+ .replace(/%[01][\da-f]/gi, "%20"); // ditto for already encoded items
+ if (uriSpec != uri.spec) {
+ if (this.consoleDump) this.dump("Fixing URI: " + uri.spec + " into " + uriSpec);
+ if (uriValid !== false || (uriValid = URIValidator.validate(uriSpec))) {
+ uri.spec = uriSpec;
+ }
+ }
+ }
+ if (uriValid === false) {
+ msg = "Rejected invalid URI: " + uriSpec;
+ if (this.consoleDump) this.dump(msg);
+ this.log("[NoScript URI Validator] " + msg);
+ return false;
+ }
+ }
+ // encode all you can (i.e. don't touch valid encoded and delims)
+ if (fixURI) {
+ try {
+ uriSpec = uriSpec.replace(/[^%]|%(?![\da-f]{2})/gi, encodeURI);
+ if (uriSpec != uri.spec) {
+ if (this.consoleDump) this.dump("Encoded URI: " + uri.spec + " to " + uriSpec);
+ uri.spec = uriSpec;
+ }
+ } catch(ex) {
+ msg = "Error assigning encoded URI: " + uriSpec + ", " + ex;
+ if (this.consoleDump) this.dump(msg);
+ this.log("[NoScript URI Validator] " + msg);
+ return false;
+ }
+ }
+ return true;
+ },
+
+ syncUI: function(aContext) {
+ let doc = aContext && (aContext instanceof Ci.nsIDOMDocument ? aContext : aContext.ownerDocument || aContext.document);
+ if (doc && doc.defaultView) {
+ let ev = doc.createEvent("Events");
+ ev.initEvent("NoScript:syncUI", true, false);
+ aContext.dispatchEvent(ev);
+ }
+ },
+
+ objectWhitelist: {},
+ ALL_TYPES: "*",
+ objectWhitelistLen: 0,
+ _objectKeyRx: /^((?:\w+:\/\/)?[^\.\/\d]+)\d+(\.[^\.\/]+\.)/,
+ objectKey: function(url, originSite) {
+ if (url.indexOf("id=") > 0) {
+ let [path, query] = url.split("?");
+ if (query) {
+ let id = query.match(/(?:^|&)(?:video_?)?id=([^&]+)/);
+ if (id) url = path + "?id=" + id[1];
+ }
+ }
+ return (originSite || '') + ">" + IOUtil.anonymizeURL(url.replace(this._objectKeyRx, '$1$2'));
+ },
+ anyAllowedObject: function(site, mime) {
+ let key = this.objectKey(site);
+ if (key in this.objectWhitelist) return true;
+ key += '/';
+ for (let s in this.objectWhitelist) {
+ if (s.indexOf(site) === 0) return true;
+ }
+ return false;
+ },
+ isAllowedObject: function(url, mime, site, originSite) {
+ let types = this.objectWhitelist[this.objectKey(url, originSite)] || this.objectWhitelist[this.objectKey(url)];
+ if (types && (types === this.ALL_TYPES || types.indexOf(mime) > -1))
+ return true;
+
+
+ if (typeof(site) === "undefined") site = this.getSite(url);
+
+ for (;site;) {
+ types = this.objectWhitelist[this.objectKey(site, originSite)] || this.objectWhitelist[this.objectKey(site)];
+ if (types && (types === this.ALL_TYPES || types.indexOf(mime) > -1))
+ return true;
+
+ if (!this._moreURLPartsRx.test(site)) break;
+ let s = site.replace(this._chopURLPartRx, '');
+ if (s === site) break;
+ site = s;
+ }
+
+ return false;
+ },
+ _moreURLPartsRx: /\..*\.|:\//,
+ _chopURLPartRx: /.*?(?::\/+|\.)/,
+
+ // Fire.fm compatibility shim :(
+ setAllowedObject: function(url, mime) {
+ this.allowObject(url, mime);
+ },
+
+ allowObject: function(url, mime, originSite) {
+ let key = this.objectKey(url, originSite);
+ if (key in this.objectWhitelist) {
+ let types = this.objectWhitelist[key];
+ if (types === this.ALL_TYPES) return;
+ if(mime === "*") {
+ types = this.ALL_TYPES;
+ } else {
+ if (types.indexOf(mime) > -1) return;
+ types.push(mime);
+ }
+ } else {
+ this.objectWhitelist[key] = mime === "*" ? this.ALL_TYPES : [mime];
+ }
+ this.objectWhitelistLen++;
+ },
+ isAllowedObjectByDOM: function(obj, objectURL, parentURL, mime, site, originSite) {
+ var url = this.getObjectURLWithDOM(obj, objectURL, parentURL);
+ return url && this.isAllowedObject(url, mime, site, originSite || this.getSite(parentURL));
+ },
+ allowObjectByDOM: function(obj, objectURL, parentURL, mime, originSite) {
+ var url = this.getObjectURLWithDOM(obj, objectURL, parentURL);
+ if (url) this.allowObject(url, mime, originSite || this.getSite(parentURL));
+ },
+ getObjectURLWithDOM: function(obj, objectURL, parentURL) {
+ let doc = obj.ownerDocument;
+ let suffix = encodeURIComponent(parentURL);
+ if (!doc) return objectURL + "#!#@" + suffix;
+
+ let id = obj.id || "";
+ let t = obj.tagName.toUpperCase();
+
+ const ytFrameURL = "https://www.youtube.com/embed/";
+
+ if ("IFRAME" === t && objectURL.substring(0, ytFrameURL.length) === ytFrameURL) {
+ objectURL = ytFrameURL;
+ id = "(ytFrame)";
+ } else {
+ objectURL = objectURL.replace(/[\?#].*/, '');
+ if (!id) {
+ let ee = doc.getElementsByTagName(t);
+
+ for (let j = ee.length; j-- > 0;) {
+ if (ee[j] === obj) {
+ id = t + "(" + j + ")";
+ break;
+ }
+ }
+ }
+ }
+ return objectURL + "#!#" + id + "@" + suffix;
+ },
+
+ resetAllowedObjects: function() {
+ this.objectWhitelist = {};
+ this.objectWhitelistLen = 0;
+ },
+
+ isAllowedMime: function(mime, site) {
+ return (this.allowedMimeRegExp && (
+ this.allowedMimeRegExp.test(mime) ||
+ this.allowedMimeRegExp.test(mime + "@" + site)));
+ },
+ countObject: function(embed, site) {
+ if(!site) return;
+ try {
+ var doc = embed.ownerDocument;
+
+ if (doc) {
+ var topDoc = doc.defaultView.top.document;
+ var os = this.getExpando(topDoc, "objectSites");
+ if(os) {
+ if(os.indexOf(site) < 0) os.push(site);
+ } else {
+ this.setExpando(topDoc, "objectSites", [site]);
+ }
+ }
+ } catch (ex) {}
+ },
+
+ getPluginExtras: function(obj) {
+ return this.getExpando(obj, "pluginExtras");
+ },
+ setPluginExtras: function(obj, extras) {
+ this.setExpando(obj, "pluginExtras", extras);
+ if (this.consoleDump & LOG_CONTENT_BLOCK) {
+ try {
+ this.dump("Setting plugin extras on " + obj + " -> " + (this.getPluginExtras(obj) == extras)
+ + ", " + (extras && extras.toSource()) );
+ } catch(e) {
+ this.dump("Setting plugin extras");
+ }
+ }
+
+ return extras;
+ },
+
+ getExpando: function(domObject, key, defValue) {
+ return domObject && domObject.__noscriptStorage && domObject.__noscriptStorage[key] ||
+ (defValue ? this.setExpando(domObject, key, defValue) || defValue : null);
+ },
+ setExpando: function(domObject, key, value) {
+ if (!domObject) return null;
+ if (!domObject.__noscriptStorage) domObject.__noscriptStorage = {};
+ if (domObject.__noscriptStorage) domObject.__noscriptStorage[key] = value;
+ else if(this.consoleDump) this.dump("Warning: cannot set expando " + key + " to value " + value);
+ return value;
+ },
+
+ hasVisibleLinks: function(document) {
+ const w = document.defaultView;
+ if (!w) return false;
+
+ const links = document.links;
+ let toBeChecked = null;
+ for (let j = 0, l; (l = links[j]); j++) {
+ if (l && l.href && l.href.indexOf("http") === 0) {
+ if (l.offsetWidth) return true;
+ if (!toBeChecked) toBeChecked = [];
+ toBeChecked.push(l);
+ }
+ }
+ if (!toBeChecked) return false;
+
+ let hiddenAncestors = [];
+ for (let j = toBeChecked.length; j-- > 0;) {
+ let n = toBeChecked[j];
+ if (n.firstChild) {
+ let ancestors = [];
+ for (;;) {
+ if (hiddenAncestors.indexOf(n) !== -1) break;
+ ancestors.push(n);
+ let s = w.getComputedStyle(n, '');
+ if (s.display === "none" || s.visibility === "hidden") {
+ hiddenAncestors.push.apply(hiddenAncestors, ancestors);
+ break;
+ }
+ if (!(n = n.parentNode)) return true;
+ }
+ }
+ }
+
+ if (document.embeds[0] || document.getElementsByTagName("object")[0]) return true;
+ let form = document.forms[0];
+ if (form && form.offsetHeight) return true;
+ return false;
+ },
+
+ processScriptElements: function(document, sites, docSite) {
+ const scripts = document.getElementsByTagName("script");
+ var scount = scripts.length;
+ var surrogates = this.getExpando(document, "surrogates", {});
+ if (scount) {
+ let win = document.defaultView;
+ const HTMLElement = win.HTMLElement;
+ sites.scriptCount += scount;
+ let nselForce = this.nselForce && this.isJSEnabled(docSite, win);
+ let isHTMLScript;
+ while (scount-- > 0) {
+ let script = scripts.item(scount);
+ isHTMLScript = script instanceof HTMLElement;
+ let scriptSrc;
+ if (isHTMLScript) {
+ scriptSrc = script.src;
+ } else if(script) {
+ scriptSrc = script.getAttribute("src");
+ if (!/^[a-z]+:\/\//i.test(scriptSrc)) continue;
+ } else continue;
+
+ let scriptSite = this.getSite(scriptSrc);
+ if (scriptSite) {
+ sites.all.push(scriptSite);
+
+ if (scriptSrc in surrogates) continue;
+
+ if (nselForce && isHTMLScript &&
+ !(script.__nselForce ||
+ this.isJSEnabled(scriptSite, win) ||
+ this.isUntrusted(scriptSite))) {
+
+ this.showNextNoscriptElement(script);
+ }
+ }
+ }
+ }
+ }
+,
+
+
+ showNextNoscriptElement: function(script) {
+ let doc = script.ownerDocument;
+ let checkRefresh = true;
+ let docShell;
+ const HTMLElement = doc.defaultView.HTMLElement;
+ try {
+ for (var node = script; (node = node.nextSibling);) {
+
+ if (node instanceof HTMLElement) {
+ script.__nselForce = true;
+
+ tag = node.tagName.toUpperCase();
+ if (tag == "SCRIPT") {
+ if (node.src) return;
+ script = node;
+ continue;
+ }
+ if (tag != "NOSCRIPT")
+ return;
+
+ let child = node.firstChild;
+ if (!(child && child.nodeType === 3)) break;
+
+ if (checkRefresh) {
+ this.setExpando(doc, "nselForce", true);
+ checkRefresh = false;
+ docShell = this.dom.getDocShellForWindow(doc.defaultView);
+ if (docShell.allowMetaRedirects) {
+ docShell.allowMetaRedirects = false;
+ } else {
+ docShell = null;
+ }
+ }
+
+ let el = doc.createElementNS(HTML_NS, "span");
+ el.__nselForce = true;
+
+ el.innerHTML = child.nodeValue;
+ node.replaceChild(el, child);
+ node.className = "noscript-show";
+ }
+ }
+ } catch(e) {
+ this.dump(e.message + " while showing NOSCRIPT element");
+ } finally {
+ if (docShell) docShell.allowMetaRedirects = true;
+ }
+ },
+
+
+ handleBookmark: function(url, openCallback) {
+ if (!url) return true;
+ try {
+ if (!this.getPref("forbidBookmarklets") && /^\s*(?:javascript|data):/i.test(url)) {
+ return this.executeJSURL(url, openCallback);
+ }
+ if (!this.jsEnabled && this.getPref("allowBookmarks")) {
+ let site = this.getSite(url);
+ if (!(this.isJSEnabled(site) || this.isUntrusted(site))) {
+ this.setJSEnabled(site, true);
+ this.savePrefs();
+ }
+ }
+ } catch(e) {
+ if (ns.consoleDump) ns.dump(e + " " + e.stack);
+ }
+ return false;
+ },
+
+ // applied to Places(UI)Utils
+ placesCheckURLSecurity: function(node) {
+ if(!this.__originalCheckURLSecurity(node)) return false;
+ var method = arguments.callee;
+ if(method._reentrant) return true;
+ try {
+ method._reentrant = true;
+ const url = node.uri;
+ node = null;
+ var self = this;
+ return !this.__ns.handleBookmark(url, function(url) {
+ if (method.caller) method.caller.apply(self, method.caller.arguments);
+ self = null;
+ });
+ } finally {
+ method._reentrant = false;
+ }
+ },
+
+
+ executeJSURL: function(url, openCallback, fromURLBar) {
+ var browserWindow = DOM.mostRecentBrowserWindow;
+ var browser = browserWindow.noscriptOverlay.currentBrowser;
+ if(!browser) return false;
+
+ var window = browser.contentWindow;
+ if(!window) {
+ let callbackId = IPC.parent.callback(openCallback);
+ browser.messageManager.sendAsyncMessage("NoScript:executeJSURL", {
+ url, callbackId, fromURLBar
+ });
+ return true;
+ }
+ return this.executeJSURLInContent(browser, window, url, openCallback, fromURLBar);
+ },
+
+ executeJSURLInContent(browser, window, url, openCallback, fromURLBar = false) {
+ var site = this.getDocSite(window.document) || this.getExpando(browser, "jsSite");
+
+ if (this.mozJSEnabled) {
+ if(this.consoleDump) this.dump("Executing JS URL " + url + " on site " + site);
+
+ let docShell = browser.docShell;
+
+ let snapshots = {
+ globalJS: this.globalJS,
+ docJS: docShell.allowJavascript,
+ siteJS: this.jsPolicySites.sitesString,
+ untrusted: this.untrustedSites.sitesString
+ };
+
+ let siteJSEnabled = this.isJSEnabled(site, window);
+
+ let doc = window.document;
+
+ let focusListener = null;
+
+ try {
+ WinScript.unblock(window);
+ docShell.allowJavascript = true;
+ if (!(this.jsEnabled = doc.documentURI === "about:blank" || ns.getPref(fromURLBar ? "allowURLBarImports" : "allowBookmarkletImports"))) {
+ if (site && !siteJSEnabled) {
+ this.jsPolicySites.add(site);
+ this.untrustedSites.remove(site, false, true);
+ }
+ } else {
+ focusListener = function(ev) {
+ ns.jsEnabled = docShell.isActive;
+ };
+ for (let et of ["focus", "blur"])
+ browser.addEventListener(et, focusListener, true);
+ }
+
+ try {
+ this.executingJSURL(doc, 1);
+ let noJS = !(siteJSEnabled && snapshots.docJS);
+ if (noJS) {
+ this._patchTimeouts(window, true);
+ }
+
+ if (noJS && /^javascript:/i.test(url)) {
+ JSURL.load(url, doc);
+ } else {
+ window.location.href = url;
+ }
+ Thread.yieldAll();
+ if (noJS) {
+ this._patchTimeouts(window, false);
+ }
+
+ } catch(e) {
+ this.logError(e, true, "Bookmarklet or location scriptlet");
+ }
+
+ return true;
+ } finally {
+ if (!siteJSEnabled) try {
+ WinScript.block(window);
+ } catch (e) {
+ ns.log(e);
+ }
+ this.setExpando(browser, "jsSite", site);
+ if (!docShell.isLoadingDocument && docShell.currentURI &&
+ this.getSite(docShell.currentURI.spec) == site)
+ docShell.allowJavascript = snapshots.docJS;
+
+ Thread.asap(function() {
+ try {
+ if (doc.defaultView && this.executingJSURL(doc) > 1) {
+ this.delayExec(arguments.callee, 100);
+ return;
+ }
+ this.executingJSURL(doc, 0);
+ } catch (e) {} // the document could be dead, e.g. after a javascript: non-void expression evaluation
+
+ if (focusListener)
+ for (let et of ["focus", "blur"])
+ browser.removeEventListener(et, focusListener, true);
+
+ if (this.jsEnabled != snapshots.globalJS)
+ this.jsEnabled = snapshots.globalJS;
+
+ this.jsPolicySites.sitesString = snapshots.siteJS;
+ this.untrustedSites.sitesString = snapshots.untrusted;
+
+ this.flushCAPS();
+
+ if (this.consoleDump & LOG_JS)
+ this.dump("Restored snapshot permissions on " + site + "/" + (docShell.isLoadingDocument ? "loading" : docShell.currentURI.spec));
+ }, this);
+ }
+ }
+ if (openCallback) openCallback();
+ return false;
+ },
+
+ _patchTimeouts: function(w, start) {
+ this._runJS(w, start
+ ? "if (!('__runTimeouts' in window)) " +
+ (function() {
+ var tt = [];
+ window.setTimeout = window.setInterval = function(f, d, a) {
+ if (typeof(f) != 'function') f = new Function(f || '');
+ tt.push({f: f, d: d, a: a});
+ return 0;
+ };
+ window.__runTimeouts = function() {
+ var t, count = 0;
+ while (tt.length && count++ < 200) { // let's prevent infinite pseudo-loops
+ tt.sort(function(a, b) { return a.d < b.d ? -1 : (a.d > b.d ? 1 : 0); });
+ t = tt.shift();
+ t.f.call(window, t.a);
+ }
+ delete window.__runTimeouts;
+ delete window.setTimeout;
+ };
+ }.toSource()) + "()"
+ : "if (('__runTimeouts' in window) && typeof(window.__runTimeouts) == 'function') window.__runTimeouts()"
+ );
+ },
+
+ _runJS: function(window, s) {
+ window.location.href = "javascript:" + encodeURIComponent(s + "; void(0);");
+ },
+
+ bookmarkletImport: function(scriptElem, src) {
+ var doc = scriptElem.ownerDocument;
+ ns.executingJSURL(doc, 1);
+ var w = doc.defaultView;
+
+
+ try {
+ ns._patchTimeouts(w, true);
+ var xhr = ns.createCheckedXHR("GET", src, function() {
+ if (xhr.readyState === 4) {
+ ns._runJS(doc.defaultView, xhr.responseText);
+ var ev = doc.createEvent("HTMLEvents");
+ ev.initEvent("load", false, true);
+ Thread.asap(function() {
+ scriptElem.dispatchEvent(ev);
+ dispose();
+ });
+ }
+ }, w);
+ xhr.send(null);
+ } catch(e) {
+ dispose();
+ ns.dump(e);
+ }
+
+ function dispose() {
+ Thread.asap(function() {
+ try {
+ ns._patchTimeouts(w, false);
+ } catch(e) {}
+ ns.executingJSURL(doc, -1);
+ });
+ };
+ },
+
+ executingJSURL: function(doc, n) {
+ const VAR = "JSURLExec";
+ var v = this.getExpando(doc, VAR) || 0;
+ if (typeof(n) === "number") {
+ this.setExpando(doc, VAR, n === 0 ? 0 : v += n);
+ }
+ return v;
+ },
+
+ isCheckedChannel: function(c) {
+ return ns.reqData(c).checked;
+ },
+ setCheckedChannel: function(c, v) {
+ ns.reqData(c).checked = v;
+ },
+
+ createCheckedXHR: function(method, url, async, window) {
+ if (typeof(async) == "undefined") async = true;
+ var xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
+ xhr.open(method, url, !!async);
+ this.setCheckedChannel(xhr.channel, true);
+
+ if (typeof(async) === "function")
+ xhr.addEventListener("readystatechange", async, false);
+
+ var privacyContext = window && window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation);
+ if ((privacyContext instanceof Ci.nsILoadContext) && ("usePrivateBrowsing" in privacyContext)
+ && privacyContext.usePrivateBrowsing) {
+ if (xhr.channel instanceof Ci.nsIPrivateBrowsingChannel) {
+ xhr.channel.setPrivate(true);
+ } else {
+ xhr.channel.loadFlags |= xhr.channel.INHIBIT_PERSISTENT_CACHING;
+ }
+ }
+
+ return xhr;
+ },
+
+ mimeEssentials: function(mime) {
+ return mime && mime.replace(/^application\/(?:x-)?/, "") || "";
+ },
+ urlEssentials: function(s) {
+ // remove query, hash and intermediate path
+ return s.replace(/[#\?].*/g, '').replace(/(.*?\w\/).+?(\/[^\/]+)$/, '$1...$2');
+ },
+ cssMimeIcon: function(mime, size) {
+ if (!mime) return;
+ [mime] = mime.split(/[;\s]/);
+ return mime == "application/x-shockwave-flash"
+ ? // work around for Windows not associating a sane icon to Flash
+ 'url("' + this.skinBase + "flash" + size + '.png")'
+ : /^application\/x-java\b/i.test(mime)
+ ? 'url("' + this.skinBase + "java" + size + '.png")'
+ : /^application\/x-silverlight\b/.test(mime)
+ ? 'url("' + this.skinBase + "somelight" + size + '.png")'
+ : /^font\b/i.test(mime)
+ ? 'url("' + this.skinBase + 'font.png")'
+ : mime === 'WebGL'
+ ? 'url("' + this.skinBase + "webgl" + size + '.png")'
+ : 'url("moz-icon://noscript?size=' + size + '&contentType=' + mime.replace(/[^\w-\/]/g, '') + '")';
+ },
+
+ _cachedObjectMimeRx: /^(?:text\/(?:javascript|css|x-c)|application\/(?:x-)?javascript)$/,
+ isCachedObjectMime: function(mime) { return this._cachedObjectMimeRx.test(mime); },
+
+ findPluginExtras: function(document) {
+ return this.getExpando(document, "pluginExtras", []);
+ },
+
+ appliesHere: function(pref, url) {
+ return pref && ((ANYWHERE & pref) == ANYWHERE ||
+ (this.isJSEnabled(this.getSite(url))
+ ? (WHERE_TRUSTED & pref) : (WHERE_UNTRUSTED & pref)
+ )
+ );
+ },
+
+ _preprocessObjectInfo: function(doc) {
+
+ const pe = this.getExpando(doc, "pe");
+ if (!pe) return null;
+ this.setExpando(doc, "pe", null);
+
+ var ret = [];
+ var embedRx = /^(?:object|embed)$/i;
+ for (var j = pe.length; j-- > 0;) {
+ let o = pe[j];
+ try {
+ if (this.getExpando(o.embed, "silverlight")) {
+ o.embed = this._attachSilverlightExtras(o.embed, o.pluginExtras);
+ if (!o.embed) continue; // skip unconditionally to prevent in-page Silverlight placeholders
+ }
+
+ let embed = o.embed;
+ if (this.getExpando(embed, "processed")) continue;
+ this.setExpando(embed, "processed", true);
+
+ if (embedRx.test(embed.tagName)) {
+ let node = embed;
+ while ((node = node.parentNode) && !node.__noscriptBlocked)
+ // if (node instanceof OBJECT) o.embed = embed = node
+ ;
+
+ if (node !== null) {
+ pe.splice(j, 1);
+ continue;
+ }
+ }
+
+ this.countObject(embed, o.pluginExtras.site);
+
+ this.setPluginExtras(embed, o.pluginExtras);
+ if (embed.ownerDocument) ret.push(o);
+ } catch(e1) {
+ if(this.consoleDump & LOG_CONTENT_BLOCK)
+ this.dump("Error setting plugin extras: " +
+ (o && o.pluginExtras && o.pluginExtras.url) + ", " + e1);
+ }
+ }
+ return ret;
+ },
+
+ processObjectElements: function(document, sites, loaded) {
+ const pluginExtras = this.findPluginExtras(document);
+ sites.pluginCount += pluginExtras.length;
+ sites.pluginExtras.push(pluginExtras);
+
+ const objInfo = this._preprocessObjectInfo(document);
+ if (!objInfo) return;
+
+ var count = objInfo.length;
+ if (count === 0) return;
+
+ sites.pluginCount += count;
+
+ const minSize = this.getPref("placeholderMinSize"),
+ longTip = this.getPref("placeholderLongTip");
+
+ const skipCSS = /^(?:position|top|left|right|bottom)$/;
+
+ var replacements = null,
+ collapse = this.collapseObject,
+ forcedCSS = ";",
+ pluginDocument = false;
+
+ try {
+ pluginDocument = count == 1 && (
+ objInfo[0].pluginExtras.url === document.URL && !objInfo[0].embed.nextSibling ||
+ document.body.lastChild === objInfo[0].embed && document.body.lastChild === document.body.firstChild
+ );
+ if (pluginDocument) {
+ collapse = false;
+ forcedCSS = ";outline-style: none !important;-moz-outline-style: none !important; width: 100%";
+
+ }
+ } catch(e) {}
+
+ var win = document.defaultView;
+
+ while (count--) {
+ let oi = objInfo[count];
+ let object = oi.embed;
+ let extras = oi.pluginExtras;
+
+ try {
+ extras.site = this.getSite(extras.url);
+
+ if(!this.showUntrustedPlaceholder && this.isUntrusted(extras.site))
+ continue;
+
+ let msg = "";
+
+ let objectTag = object.tagName.toUpperCase();
+ if (objectTag === "VIDEO") {
+ // Youtube HTML5 hack
+ let player = document.getElementById("movie_player-html5");
+ if (player) {
+ let rx = /\bhtml5-before-playback\b/;
+ if (rx.test(player.className)) player.className = player.className.replace(rx, '');
+ }
+ }
+
+ extras.tag = "<" + (this.isLegacyFrameReplacement(object) ? "FRAME" : objectTag) + ">";
+ extras.title = extras.tag + ", " +
+ this.mimeEssentials(extras.mime) + "@" +
+ (longTip ? SiteUtils.crop(extras.url) : extras.url.replace(/[#\?].*/, ''));
+
+ if ((extras.alt = object.getAttribute("alt")))
+ extras.title += ' "' + extras.alt + '"'
+
+
+ let anchor = document.createElementNS(HTML_NS, "a");
+ anchor.id = object.id;
+ anchor.href = /^(?:https?|ftp):/i.test(extras.url) ? extras.url : "#";
+ anchor.setAttribute("title", extras.title);
+
+ this.setPluginExtras(anchor, extras);
+ this.setExpando(anchor, "removedNode", object);
+
+ (replacements = replacements || []).push({object: object, placeholder: anchor, extras: extras });
+
+ if (this.showPlaceholder && (object.offsetWidth || object.offsetHeight || !this.isCachedObjectMime(extras.mime))) {
+ if (!pluginExtras.overlayListener) {
+ pluginExtras.overlayListener = true;
+ win.addEventListener("click", this.bind(this.onOverlayedPlaceholderClick), true);
+ }
+ anchor.addEventListener("click", this.bind(this.onPlaceholderClick), true);
+ anchor.className = "__noscriptPlaceholder__ __noscriptObjectPatchMe__";
+ } else {
+ anchor.className = "__noscriptHidden__";
+ if (collapse) anchor.style.display = "none";
+ continue;
+ }
+
+ object.className += " __noscriptObjectPatchMe__";
+
+ let innerDiv = document.createElementNS(HTML_NS, "div");
+ innerDiv.className = "__noscriptPlaceholder__1";
+
+ let cssDef = "",
+ restrictedSize,
+ style = win.getComputedStyle(oi.embed, null);
+
+ if (style) {
+ for (let cssCount = 0, cssLen = style.length; cssCount < cssLen; cssCount++) {
+ let cssProp = style.item(cssCount);
+ if (!skipCSS.test(cssProp))
+ cssDef += cssProp + ": " + style.getPropertyValue(cssProp) + ";";
+ }
+
+ innerDiv.setAttribute("style", cssDef + forcedCSS);
+
+ restrictedSize = (collapse || style.display === "none" || style.visibility === "hidden");
+
+ anchor.style.width = style.width;
+ anchor.style.height = style.height;
+ if (style.position !== "static") {
+ anchor.style.position = style.position;
+ anchor.style.top = style.top;
+ anchor.style.left = style.left;
+ anchor.style.bottom = style.bottom;
+ anchor.style.right = style.right;
+ }
+ } else restrictedSize = collapse;
+
+ if (restrictedSize) {
+ innerDiv.style.maxWidth = anchor.style.maxWidth = "32px";
+ innerDiv.style.maxHeight = anchor.style.maxHeight = "32px";
+ }
+
+ innerDiv.style.visibility = "visible";
+
+ let closeButton = innerDiv.appendChild(document.createElementNS(HTML_NS, "div"));
+ closeButton.className = "closeButton";
+
+ anchor.appendChild(innerDiv);
+
+ // icon div
+ innerDiv = innerDiv.appendChild(document.createElementNS(HTML_NS, "div"));
+ innerDiv.className = "__noscriptPlaceholder__2";
+
+ let iconSize;
+
+ if(restrictedSize || style && (64 > (parseInt(style.width) || 0) || 64 > (parseInt(style.height) || 0))) {
+ innerDiv.style.backgroundPosition = "bottom right";
+ iconSize = 16;
+ let w = parseInt(style.width) || 0,
+ h = parseInt(style.height) || 0;
+ if (minSize > w || minSize > h) {
+ var rect = object.getBoundingClientRect();
+ let aStyle = anchor.style, iStyle = innerDiv.parentNode.style;
+ aStyle.overflow = "visible";
+ aStyle.float = "left";
+
+ let isTop = !win.frameElement;
+ aStyle.minWidth = iStyle.minWidth = Math.max(w, isTop ? minSize : Math.min(document.documentElement.offsetWidth - rect.left, minSize)) + "px";
+ aStyle.minHeight = iStyle.minHeight = Math.max(h, isTop ? minSize : Math.min(document.documentElement.offsetHeight - rect.top, minSize)) + "px";
+
+ }
+ } else {
+ iconSize = 32;
+ innerDiv.style.backgroundPosition = "center";
+ if (msg) {
+ let msgDiv = document.createElement("div");
+ msgDiv.className = "msg";
+ msgDiv.textContent = msg;
+ anchor.firstChild.appendChild(msgDiv);
+ }
+ }
+ innerDiv.style.backgroundImage = this.cssMimeIcon(extras.mime, iconSize);
+
+ } catch(objectEx) {
+ ns.dump(objectEx + " processing plugin " + count + "@" + document.documentURI + "\n");
+ }
+
+ }
+
+ if (replacements) {
+ if (this.isJSEnabled(this.getSite(document.URL), win)) this.patchObjects(document);
+ this.delayExec(this.createPlaceholders, 0, replacements, pluginExtras, document);
+ }
+ },
+
+ get _objectPatch() {
+ delete this._objectPatch;
+ return this._objectPatch = function() {
+ const els = document.getElementsByClassName("__noscriptObjectPatchMe__");
+ const DUMMY_FUNC = () => DUMMY_FUNC;
+ var el;
+ for (var j = els.length; j-- > 0;) {
+ el = els[j];
+ el.setAttribute("class",
+ el.getAttribute("class").replace(/\b__noscriptObjectPatchMe__\b/, '').replace(/\s+/, ' ')
+ );
+ el.__noSuchMethod__ = DUMMY_FUNC;
+ }
+ }.toSource() + "()";
+ },
+
+ patchObjects: function(document) {
+ delete this.patchObjects;
+ return (this.patchObjects = ("getElementsByClassName" in document)
+ ? function(document) { ScriptSurrogate.executeDOM(document, this._objectPatch); }
+ : DUMMY_FUNC).call(this, document);
+ },
+
+ createPlaceholders: function(replacements, pluginExtras, document) {
+ for (let r of replacements) {
+ try {
+ if (r.extras.pluginDocument) {
+ this.setPluginExtras(r.object, null);
+ if (r.object.parentNode) r.object.parentNode.insertBefore(r.placeholder, r.object);
+ } else if (r.object.parentNode) {
+ let p = r.placeholder;
+ let o = r.object;
+ o.parentNode.insertBefore(p, o);
+ o._display = o.style.display;
+ o.style.display = "none";
+ if (p.style.position === "absolute") {
+ let b = p.getBoundingClientRect();
+ let el;
+ if (b.width && b.height &&
+ p !== (el = p.ownerDocument.defaultView
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils)
+ .elementFromPoint(
+ b.left + b.width / 2, b.top + b.height / 2, false, false)
+ ) && el && p.firstChild !== el && p.firstChild !== el.parentNode
+ ) {
+ let d = p.ownerDocument;
+ let w = d.defaultView;
+ p.style.top = (b.top + w.scrollY) + "px";
+ p.style.left = (b.left + w.scrollX) + "px";
+ p.style.zIndex = DOM.maxZIndex;
+ d.body.appendChild(p);
+ }
+ }
+ }
+ r.extras.placeholder = r.placeholder;
+ this._collectPluginExtras(pluginExtras, r.extras);
+
+ ns.patchObjects(document);
+ } catch(e) {
+ this.dump(e);
+ }
+ }
+ this.syncUI(document);
+ },
+
+ bind: function(f) {
+ return "_bound" in f ? f._bound : f._bound = (function() { return f.apply(ns, arguments); });
+ },
+
+ stackIsMine: function() {
+ var s = Components.stack.caller;
+ var f = s.filename.replace(/ line .*/, '');
+ while((s = s.caller)) {
+ if (s.filename && !(/^(?:resource|chrome):/.test(s.filename) || f === s.filename.replace(/ line .*/, ''))) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ onPlaceholderClick: function(ev, anchor) {
+ if (ev.button) return;
+ anchor = anchor || ev.currentTarget;
+ const object = this.getExpando(anchor, "removedNode");
+
+ if (object) try {
+ if("isTrusted" in ev && !ev.isTrusted || !this.stackIsMine()) {
+ return;
+ }
+ let shift = ev.shiftKey;
+ let closeButton = ev.target.className === "closeButton";
+ if (closeButton ? !shift : shift) {
+ if (this.collapseObject ||
+ this.getPref("placeholderCollapseOnClose", false)) {
+ anchor.style.display = "none";
+ } else {
+ anchor.style.visibility = "hidden";
+ anchor.style.width = anchor.offsetWidth + "px";
+ anchor.style.height = anchor.offsetHeight + "px";
+ anchor.removeChild(anchor.firstChild);
+ anchor.style.display = "block";
+ }
+ anchor.id = anchor.className = "";
+ return;
+ }
+ this.checkAndEnablePlaceholder(anchor, object);
+ } finally {
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ },
+
+ onOverlayedPlaceholderClick: function(ev) {
+ var el = ev.originalTarget;
+ var doc = el.ownerDocument;
+
+ // check for cloned nodes, like on http://www.vmware.com/products/workstation/new.html
+ for (let ph = el; ph.className && ph.className.indexOf("__noscriptPlaceholder__") !== -1; ph = ph.parentNode) {
+ if (ph.href && ph.title) {
+ if (this.getExpando(ph, "removedNode")) {
+ this.onPlaceholderClick(ev, ph);
+ return;
+ }
+
+ let pluginExtras = this.findPluginExtras(doc);
+ if (pluginExtras) {
+ for (let j = pluginExtras.length; j-- > 0;) {
+ if (pluginExtras[j].title === ph.title) {
+ let o = pluginExtras[j].placeholder;
+ let n = this.getExpando(o, "removedNode");
+ this.setExpando(ph, "removedNode", n);
+ this.setPluginExtras(ph, this.getPluginExtras(n));
+ this.onPlaceholderClick(ev, ph);
+ return;
+ }
+ }
+ }
+ break;
+ }
+ }
+ },
+
+ checkAndEnablePlaceholder: function(anchor, object) {
+ if (!(object || (object = this.getExpando(anchor, "removedNode")))) {
+ if (ns.consoleDump) ns.dump("Missing node on placeholder!");
+ return;
+ }
+
+ if (ns.consoleDump) ns.dump("Enabling node from placeholder...");
+
+ const extras = this.getPluginExtras(anchor);
+
+ if (!(extras && extras.url && extras.mime // && cache
+ )) return;
+
+ this.delayExec(this.checkAndEnableObject, 1,
+ {
+ window: anchor.ownerDocument.defaultView,
+ extras: extras,
+ anchor: anchor,
+ object: object
+ });
+ },
+
+ confirmEnableObject: function(win, extras) {
+ // work around for Linux tooltip obstructing the confirmation dialog
+ Thread.delay(function() {
+ win.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils)
+ .sendMouseEvent("mousemove", win.document.body, 0, 0, 0, 0, 0);
+ }, 100);
+ return extras.skipConfirmation || this.confirm(
+ this.getAllowObjectMessage(extras),
+ "confirmUnblock", undefined, win
+ );
+ },
+ get prompter() {
+ delete this.prompter;
+ return (this.prompter = Services.prompt);
+ },
+ confirm(msg, persistPref, title = "NoScript", window = DOM.mostRecentBrowserWindow) {
+ var alwaysAsk = { value: this.getPref(persistPref) };
+ if(!alwaysAsk.value && this.prefs.prefHasUserValue(persistPref) ||
+ this.prompter.confirmCheck(window, title, msg,
+ this.getString("alwaysAsk"), alwaysAsk)
+ ) {
+ this.setPref(persistPref, alwaysAsk.value);
+ return true;
+ }
+ return false;
+ },
+
+ isLegacyFrameDocument: function(doc) {
+ let w = doc.defaultView;
+ return (w.frameElement instanceof w.HTMLFrameElement) && this.isPluginDocumentURL(doc.URL, "iframe");
+ },
+ isLegacyFrameReplacement: function(obj) {
+ let g = Cu.getGlobalForObject(obj);
+ return (obj instanceof g.HTMLIFrameElement || obj instanceof g.HTMLAnchorElement) &&
+ (obj.ownerDocument.defaultView.frameElement instanceof g.HTMLFrameElement) &&
+ obj.ownerDocument.URL == this.createPluginDocumentURL(obj.src || obj.href, "iframe");
+ },
+ isClickToPlay: (obj) => obj instanceof Ci.nsIObjectLoadingContent && ("playPlugin" in obj) && ("activated" in obj) && !obj.activated,
+ handleClickToPlay: function(obj) {
+ if (this.isClickToPlay(obj) && this.getPref("smartClickToPlay")) {
+ Thread.asap(() => obj.playPlugin());
+ }
+ },
+
+ checkAndEnableObject: function(ctx) {
+ var extras = ctx.extras;
+
+ if (!this.confirmEnableObject(ctx.window, extras)) return;
+
+
+ var mime = extras.mime;
+ var url = extras.url;
+
+ this.allowObject(url, mime, extras.originSite);
+ let a = ctx.anchor;
+ var doc = a.ownerDocument;
+
+
+ var isLegacyFrame = this.isLegacyFrameReplacement(ctx.object);
+
+ let w = doc.defaultView;
+
+ if (isLegacyFrame || (mime == doc.contentType && doc.body &&
+ (a === doc.body.firstChild &&
+ a === doc.body.lastChild ||
+ ctx.object instanceof w.HTMLEmbedElement && ctx.object.src != url))
+ ) { // stand-alone plugin or frame
+ doc.body.removeChild(a); // TODO: add a throbber
+ if (isLegacyFrame) {
+ this.setExpando(doc.defaultView.frameElement, "allowed", true);
+ // doc.defaultView.frameElement.src = url;
+ doc.defaultView.location.replace(url);
+ } else this.quickReload(doc.defaultView, true);
+ return;
+ } else if (this.requireReloadRegExp && this.requireReloadRegExp.test(mime) ||
+ this.getExpando(ctx, "requiresReload") ||
+ /#!flashvars#.*\b_YUIvid_=/.test(url)) {
+ this.quickReload(doc.defaultView);
+ return;
+ } else if (mime === "WebGL" || mime && mime.endsWith(" (MSE)") || this.getExpando(ctx, "silverlight")) {
+ this.allowObject(doc.documentURI, mime);
+ if (mime === "WebGL") delete WebGLInterception.sites[this.getSite(doc.documentURI)];
+ if (mime && mime.endsWith(" (MSE)")) delete MSEInterception.sites[this.getSite(doc.documentURI)];
+ this.quickReload(doc.defaultView);
+ return;
+ }
+
+
+ if (url == doc.URL) { // full page content, just reload
+ this.quickReload(doc.defaultView);
+ return;
+ }
+
+ this.setExpando(a, "removedNode", null);
+ extras.allowed = true;
+ extras.placeholder = null;
+ this.delayExec(function() {
+ var jsEnabled = ns.isJSEnabled(ns.getSite(doc.documentURI), doc.defaultView);
+ if (ctx.object.parentNode) ctx.object.parentNode.removeChild(ctx.object);
+ if ("_display" in ctx.object) ctx.object.style.display = ctx.object._display;
+ var obj = ctx.object.cloneNode(true);
+
+
+ function reload(slow) {
+ ns.log(ns. getObjectURLWithDOM(obj, url, doc.documentURI));
+ ns.allowObjectByDOM(obj, url, doc.documentURI, mime);
+ if (slow) {
+ ns.log("RELOAD")
+ DOM.getDocShellForWindow(doc.defaultView).reload(0);
+ } else {
+ ns.quickReload(doc.defaultView);
+ }
+ }
+ let win = doc.defaultView;
+ let isMedia = win && ("HTMLMediaElement" in win) && (obj instanceof win.HTMLMediaElement);
+
+ if (isMedia) {
+
+ if (jsEnabled && !obj.controls
+ && !/(?:=[^&;]{10,}.*){2,}/.test(this.objectKey(url)) // try to avoid infinite loops when more than one long parameter is present in the object key
+ ) {
+ // we must reload, since the author-provided UI likely had no chance to wire events
+
+ let url = doc.URL;
+ if (doc.getElementById("movie_player-html5")) {
+ // Youtube HTML5 hack, autoclick thumbnail on page reload
+ DOM.getDocShellForWindow(doc.defaultView)
+ .chromeEventHandler.addEventListener("load", function(ev) {
+ try {
+ let w = ev.target.defaultView;
+ if (w == w.top) {
+ ev.currentTarget.removeEventListener(ev.type, arguments.callee, true);
+ }
+ if (ev.target.URL === url) {
+ let attempts = 10;
+ w.setTimeout(function() {
+ let node = w.document.getElementById("movie_player-html5");
+ if (node && (node = node.getElementsByClassName("video-thumbnail")[0])) {
+ node.click();
+ } else {
+ if (attempts-- > 0) w.setTimeout(arguments.callee, 500);
+ }
+ }, 500);
+ }
+ } catch(e) {}
+ }, true);
+ }
+
+ reload(true); // normal reload because of http://forums.informaction.com/viewtopic.php?f=10&t=7195
+ return;
+ }
+ obj.autoplay = true;
+ }
+
+ let parent = a.parentNode;
+
+ if (parent && parent.ownerDocument == doc) {
+
+ if (jsEnabled) {
+
+ if (/IFRAME/i.test(extras.tag) && /^https:\/\/www\.youtube\.com\/embed\//.test(url)) {
+ reload();
+ return;
+ }
+
+ ScriptSurrogate.executeSandbox(doc,
+ "env.a.__noSuchMethod__ = env.o.__noSuchMethod__ = function(m, a) { return env.n[m].apply(env.n, a) }",
+ { a: a, o: ctx.object, n: obj }
+ );
+ }
+
+ this.setExpando(obj, "allowed", true);
+ parent.replaceChild(obj, a);
+ var style = doc.defaultView.getComputedStyle(obj, '');
+
+ let body = doc.body;
+ if (body && body.clientWidth === obj.offsetWidth && body.clientHeight === obj.offsetHeight) {
+ // full size applet/movie
+ reload();
+ return;
+ }
+
+
+ if (jsEnabled && ((obj.offsetWidth || parseInt(style.width)) < 2 || (obj.offsetHeight || parseInt(style.height)) < 2)
+ && !/frame/i.test(extras.tag)) {
+ let ds = DOM.getDocShellForWindow(doc.defaultView);
+ let ch = ds.currentDocumentChannel;
+ if (!(ch instanceof Ci.nsIHttpChannel && ch.requestMethod === "POST"))
+ Thread.delay(function() {
+ if (obj.offsetWidth < 2 || obj.offsetHeight < 2) reload();
+ }, 500); // warning, asap() or timeout=0 won't always work!
+ }
+ ns.syncUI(doc);
+ } else {
+ reload();
+ }
+ }, 10);
+ return;
+
+ },
+
+ getSites: function(browser) {
+ var sites = {
+ scriptCount: 0,
+ pluginCount: 0,
+ pluginExtras: [],
+ pluginSites: [],
+ docSites: [],
+ recentlyBlocked: [],
+ all: [],
+ };
+ if (browser) {
+ if (browser.content) {
+ try {
+ sites = this._enumerateSites(browser, sites);
+ } catch(ex) {
+ if (this.consoleDump) this.dump("Error enumerating sites: " + ex + "," + ex.stack);
+ }
+ } else {
+ sites = JSON.parse(JSON.stringify(this.getExpando(browser, "sites", sites)));
+ }
+ }
+ return sites;
+ },
+
+
+ _collectPluginExtras: function(pluginExtras, extras) {
+ for (var e, j = pluginExtras.length; j-- > 0;) {
+ e = pluginExtras[j];
+ if (e == extras) return false;
+ if (e.mime == extras.mime && e.url == extras.url) {
+ if (!e.placeholder) {
+ pluginExtras.splice(j, 1, extras);
+ return true;
+ }
+ if (e.placeholder == extras.placeholder)
+ return false;
+ }
+ }
+ pluginExtras.push(extras);
+ return true;
+ },
+
+ _silverlightPatch: 'HTMLObjectElement.prototype.__defineGetter__("IsVersionSupported", function() { return ((/^application\\/x-silverlight\\b/.test(this.type)) ? (n) => true : undefined); });',
+
+ _protectNamePatch: "let x=__lookupSetter__(\"name\");__defineSetter__(\"name\",function(n){let s=document.currentScript;if(s&&/\\bname\\b/.test(s.textContent)){console.log(\"NoScript prevented \\\"\" + n + \"\\\" from being assigned to window.name\")}else{x.call(this,n);}})",
+ get _flashPatch() {
+ delete this._flashPatch;
+ return this._flashPatch = function() {
+ var type = "application/x-shockwave-flash";
+ var ver;
+ var setAttribute = HTMLObjectElement.prototype.setAttribute;
+ HTMLObjectElement.prototype.setAttribute = function(n, v) {
+ if (n == "type" && v == type && !this.data) {
+ this._pendingType = v;
+
+
+ this.SetVariable = (...args) => this.__proto__.SetVariable.apply(this, args);
+ this.GetVariable = function(n) {
+ if (n !== "$version") return this.__proto__.SetVariable.apply(this, arguments);
+
+ if (!ver) {
+ ver = navigator.plugins["Shockwave Flash"]
+ .description.match(/(\d+)\.(\d+)(?:\s*r(\d+))?/);
+ ver.shift();
+ ver.push('99');
+ ver = "WIN " + ver.join(",");
+ }
+
+ return ver;
+ }
+ }
+
+ setAttribute.call(this, n, v);
+ if (n === "data" && ("_pendingType" in this) && this._pendingType === type) {
+ setAttribute.call(this, "type", type);
+ this._pendingType = null;
+ }
+ };
+
+ }.toSource() + "()";
+ },
+
+ _attachSilverlightExtras: function(embed, extras) {
+ extras.silverlight = true;
+ var pluginExtras = this.findPluginExtras(embed.ownerDocument);
+ if (this._collectPluginExtras(pluginExtras, extras)) {
+ extras.site = this.getSite(extras.url);
+ try {
+ // try to work around the IsInstalled() Silverlight machinery
+ if (!embed.firstChild) { // dummy embed
+ exras.dummy = true;
+ return null;
+ }
+ extras.dummy = false;
+ } catch(e) {
+ if(this.consoleDump) this.dump(e);
+ }
+ }
+ return embed;
+ },
+
+
+ traverseObjects: function(callback, self, browser) {
+ return this.traverseDocShells(function(docShell) {
+ let document = docShell.document;
+ if (document) {
+ for (let t of ["object", "embed"]) {
+ for (let node of Array.slice(document.getElementsByTagName(t), 0)) {
+ if (callback.call(self, node, browser))
+ return true;
+ }
+ };
+ }
+ return false;
+ }, self, browser);
+ },
+
+ traverseDocShells: function(callback, self, browser) {
+ if (!browser) {
+ const bi = DOM.createBrowserIterator();
+ while((browser = bi.next()))
+ if (this.traverseDocShells(callback, self, browser))
+ return true;
+
+ return false;
+ }
+
+ const docShells = browser.docShell.getDocShellEnumerator(
+ Ci.nsIDocShellTreeItem.typeContent,
+ browser.docShell.ENUMERATE_FORWARDS
+ );
+
+ const nsIDocShell = Ci.nsIDocShell;
+ const nsIWebNavigation = Ci.nsIWebNavigation;
+
+ while (docShells.hasMoreElements()) {
+ let docShell = docShells.getNext();
+ if (docShell instanceof nsIDocShell && docShell instanceof nsIWebNavigation) {
+ try {
+ if (callback.call(self, docShell))
+ return true;
+ } catch (e) {
+ if (this.consoleDump) this.dump("Error while traversing docshells: " + e + ", " + e.stack);
+ }
+ }
+ }
+ return false;
+ },
+
+ _enumerateSites: function(browser, sites) {
+
+ const nsIDocShell = Ci.nsIDocShell;
+
+ let all = sites.all;
+ let docShell = browser.docShell;
+ var document, topWin;
+ sites.docJSBlocked = !docShell.allowJavascript;
+ try {
+ sites.cspBlocked = /\b(?:sandbox|script-src\s+'none')\s*(?:[,;]|$)/
+ .test(docShell.currentDocumentChannel.QueryInterface(Ci.nsIHttpChannel)
+ .getResponseHeader("Content-Security-Policy"));
+ } catch (e) {
+ sites.cspBlocked = false;
+ }
+
+ try {
+ this.traverseDocShells(function(docShell) {
+
+ let document = docShell.document;
+ if (!document) return;
+
+ // Truncate title as needed
+ if (this.truncateTitle && document.title.length > this.truncateTitleLen) {
+ document.title = document.title.substring(0, this.truncateTitleLen);
+ }
+
+ // Collect document / cached plugin URLs
+ let win = document.defaultView;
+ let docURI = document.documentURI;
+ let url = this.getSite(docURI);
+
+ if (url) {
+ try {
+ let domain = document.domain;
+ if (domain && domain != this.getDomain(url, true) && url != "chrome:" && url != "about:blank") {
+ // temporary allow changed document.domain on allow page
+ if (this.getExpando(browser, "allowPageURL") == browser.docShell.currentURI.spec &&
+ this.getBaseDomain(domain).length >= domain.length &&
+ !(this.isJSEnabled(domain) || this.isUntrusted(domain))) {
+ this.setTemp(domain, true);
+ this.setJSEnabled(domain, true);
+ this.quickReload(win);
+ }
+ all.unshift(domain);
+ }
+ } catch(e) {}
+
+ sites.docSites.push(url);
+ all.push(url);
+
+ for (let redir of this.getRedirCache(browser, docURI)) {
+ all.push(redir.site);
+ }
+ }
+
+ let domLoaded = !!this.getExpando(document, "domLoaded");
+ if (!topWin) {
+ topWin = win.top;
+ sites.topSite = url;
+ if (domLoaded) this.setExpando(browser, "allowPageURL", null);
+ }
+
+ let loaded = !((docShell instanceof nsIWebProgress) && docShell.isLoadingDocument);
+ if (!(domLoaded || loaded))
+ return;
+
+ this.processObjectElements(document, sites);
+ this.processScriptElements(document, sites, url);
+
+ }, this, browser);
+
+ document = topWin.document;
+ let cache = this.getExpando(document, "objectSites");
+ if(cache) {
+ if(this.consoleDump & LOG_CONTENT_INTERCEPT) {
+ try { // calling toSource() can throw unexpected exceptions
+ this.dump("Adding plugin sites: " + cache.toSource() + " to " + all.toSource());
+ } catch(e) {
+ this.dump("Adding " + cache.length + " cached plugin sites");
+ }
+ }
+ if (!this.contentBlocker || this.alwaysShowObjectSources)
+ all.push.apply(all, cache);
+
+ all.push.apply(sites.pluginSites, cache);
+ }
+
+ cache = this.getExpando(topWin, "codeSites");
+ if (cache) all.push.apply(all, [...cache]);
+
+ const removeBlank = !(this.showBlankSources || sites.topSite == "about:blank");
+
+ for (let j = all.length; j-- > 0;) {
+ let url = all[j];
+ if (/:/.test(url) &&
+ (removeBlank && url == "about:blank" ||
+ !(
+ /^(?:file:\/\/|[a-z]+:\/*[^\/\s]+)/.test(url) ||
+ // doesn't this URL type support host?
+ this.getSite(url + "x") == url
+ )
+ ) && url != "about:"
+ ) {
+ all.splice(j, 1); // reject scheme-only URLs
+ }
+ }
+ } catch (e) {
+ Cu.reportError(e);
+ }
+ sites.recentlyBlocked = this.recentlyBlocked;
+
+ if (!sites.topSite) sites.topSite = all[0] || '';
+ sites.all = this.sortedSiteSet(all);
+ return sites;
+ },
+
+ findOverlay: function(browser) {
+ return browser && browser.ownerDocument.defaultView.noscriptOverlay;
+ },
+
+
+ // nsIChannelEventSink implementation
+ asyncOnChannelRedirect: function(oldChan, newChan, flags, redirectCallback) {
+ this.onChannelRedirect(oldChan, newChan, flags);
+ redirectCallback.onRedirectVerifyCallback(0);
+ },
+ onChannelRedirect: function(oldChan, newChan, flags) {
+ const uri = newChan.URI;
+
+ if (flags === Ci.nsIChannelEventSink.REDIRECT_INTERNAL && oldChan.URI.spec === uri.spec)
+ return;
+
+ const rw = this.requestWatchdog;
+
+ ns.reqData(newChan).redirectFrom = oldChan.URI;
+ this.reqData(newChan).redirectFrom = oldChan.URI;
+ ABE.updateRedirectChain(oldChan, newChan);
+
+ const ph = PolicyState.detach(oldChan);
+
+ var browser;
+
+ if (ph) {
+ // 0: aContentType, 1: aContentLocation, 2: aRequestOrigin, 3: aContext, 4: aMimeTypeGuess, 5: aInternalCall
+
+ ph.contentLocation = uri;
+
+ var ctx = ph.context;
+ var type = ph.contentType;
+
+ if (type != 11 && !this.isJSEnabled(oldChan.URI.spec))
+ ph.requestOrigin = oldChan.URI;
+
+ try {
+ ph.mimeType = newChan.contentType || oldChan.contentType || ph.mimeType;
+ } catch(e) {}
+
+
+ let win;
+ try {
+ win = IOUtil.findWindow(newChan);
+ } catch (e) {}
+
+ switch(type) {
+ case 2: case 9: // script redirection? cache site for menu
+ try {
+ var site = this.getSite(uri.spec);
+ if (!win) win = ctx && ((ctx instanceof Ci.nsIDOMWindow) ? ctx : ctx.ownerDocument.defaultView);
+ browser = win && (DOM.findBrowserForNode(win) || DOM.getFrameMM(win));
+ if (browser) {
+ this.getRedirCache(browser, win.top.document.documentURI)
+ .push({ site: site, type: type });
+ } else {
+ if (this.consoleDump) this.dump("Cannot find window for " + uri.spec);
+ }
+ } catch(e) {
+ if (this.consoleDump) this.dump(e);
+ }
+ break;
+
+ case 7: // frame
+
+ ph.extra = CP_FRAMECHECK;
+ if (win && win.frameElement && ph.context != win.frameElement) {
+ // this shouldn't happen
+ if (this.consoleDump) this.dump("Redirected frame change for destination " + uri.spec);
+ ph.context = win.frameElement;
+ }
+ break;
+ }
+
+ if (this.shouldLoad.apply(this, ph.toArray()) != CP_OK) {
+ if (this.consoleDump) {
+ this.dump("Blocked " + oldChan.URI.spec + " -> " + uri.spec + " redirection of type " + type);
+ }
+ throw "NoScript aborted redirection to " + uri.spec;
+ }
+ }
+
+
+ // Document transitions
+
+ if ((oldChan.loadFlags & rw.DOCUMENT_LOAD_FLAGS) || (newChan.loadFlags & rw.DOCUMENT_LOAD_FLAGS) && oldChan.URI.prePath != uri.prePath) {
+ if (newChan instanceof Ci.nsIHttpChannel)
+ HTTPS.onCrossSiteRequest(newChan, oldChan.URI.spec,
+ browser || DOM.findBrowserForNode(IOUtil.findWindow(oldChan)), rw);
+
+ }
+
+ },
+
+ getRedirCache: function(browser, uri) {
+ var redirCache = this.getExpando(browser, "redirCache", {});
+ return redirCache[uri] || (redirCache[uri] = []);
+ },
+
+ _recentlyBlockedMax: 40,
+ recentlyBlocked: [],
+ recordBlocked: function(site, origin) {
+ if (!this.getPref("showRecentlyBlocked")) return;
+ let l = this.recentlyBlocked;
+ let pos = l.length;
+ while (pos-- > 0) if (l[pos].site === site) break;
+
+ let entry;
+ if (pos > -1) {
+ entry = l[pos];
+ let origins = entry.origins;
+ if (origins.indexOf(origin) == -1) origins.push(origin);
+ if (pos == l.length - 1) return;
+ l.splice(pos, 1);
+ } else entry = { site: site, origins: [origin] };
+
+ l.push(entry);
+ if (l.length > this._recentlyBlockedMax) {
+ this.recentlyBlocked = l.slice(- this._recentlyBlockedMax / 2);
+ }
+ },
+
+ cleanupRequest: DUMMY_FUNC,
+
+ get _inclusionTypeInternalExceptions() {
+ delete this._inclusionTypeInternalExceptions;
+ return this._inclusionTypeInternalExceptions = new AddressMatcher("https://*.ebaystatic.com/*");
+ },
+
+ hasNoSniffHeader: function(channel) {
+ for (let x = true, header = "X-Content-Type-Options";;) {
+ try {
+ return channel.getResponseHeader(header).toLowerCase() === "nosniff";
+ break;
+ } catch(e) {}
+ if (x) {
+ header = header.substring(2);
+ x = false;
+ } else {
+ return false;
+ }
+ }
+ },
+
+ checkInclusionType: function(channel) {
+ try {
+ if (channel instanceof Ci.nsIHttpChannel &&
+ Math.round(channel.responseStatus / 100) != 3) {
+ var ph = PolicyState.extract(channel);
+ if (ph) {
+ let ctype = ph.contentType;
+
+ // 2 JS, 4 CSS
+ if (!(ctype === 2 || ctype === 4)) return true;
+
+ let nosniff = ns.nosniff && ctype === 2;
+
+ if (nosniff) nosniff = this.hasNoSniffHeader(channel);
+
+ if (!(nosniff || ns.inclusionTypeChecking))
+ return true;
+
+ let origin = ABE.getOriginalOrigin(channel) || ph.requestOrigin;
+
+ if (nosniff || origin && this.getBaseDomain(this.getDomain(origin)) !== this.getBaseDomain(channel.URI.host)) {
+
+ var mime;
+ try {
+ mime = channel.contentType;
+ } catch (e) {
+ mime = "UNKNOWN";
+ }
+
+ let okMime =
+ ctype === 3
+ ? !nosniff || /\bimage\//i.test(mime)
+ : (ctype === 2
+ ? (nosniff
+ ? /(?:script|\bjs(?:on)?)\b/i // strictest
+ : /(?:script|\b(?:js(?:on)?)|css)\b/i) // allow css mime on js
+ : (PolicyUtil.isXSL(ph.context) || ph.mimeType.indexOf("/x") > 0) ? /\bx[ms]l/i : /\bcss\b/i
+ ).test(mime);
+
+ if (okMime) return true;
+
+ let uri = channel.URI;
+ let url = uri.spec;
+
+
+ let disposition;
+ try {
+ disposition = channel.getResponseHeader("Content-disposition");
+ } catch(e) {}
+
+
+ if (!disposition) {
+
+ let ext;
+ if (uri instanceof Ci.nsIURL) {
+ ext = uri.fileExtension;
+ if (!ext) {
+ var m = uri.directory.match(/\.([a-z]+)\/$/);
+ if (m) ext = m[1];
+ }
+ } else ext = '';
+
+ if (ext &&
+ (ctype === 2 && /^js(?:on)?$/i.test(ext) ||
+ ctype === 4 && (ext == "css" || ext == "xsl" && (PolicyUtil.isXSL(ph.context) || ph.mimeType.indexOf("/x") > 0)))
+ ) {
+ // extension matches and not an attachment, likely OK
+ return true;
+ }
+
+ // extension doesn't match, let's check the mime
+
+
+ if ((/^text\/.*ml$|unknown/i.test(mime) ||
+ mime === "text/plain" && !(ext && /^(?:asc|log|te?xt)$/.test(ext)) // see Apache's magic file, turning any unkown ext file containing JS style comments into text/plain
+ ) && !this.getPref("inclusionTypeChecking.checkDynamic", false)) {
+ // text/html or xml or text/plain with non-text ext, let's assume a misconfigured dynamically served script/css
+ if (this.consoleDump) this.dump(
+ "Warning: mime type " + mime + " for " +
+ (ctype == 2 ? "Javascript" : "CSS") + " served from " +
+ uri.spec);
+ return true;
+ }
+ } else mime = mime + ", " + disposition;
+
+ if (this._inclusionTypeInternalExceptions.test(url) ||
+ new AddressMatcher(this.getPref("inclusionTypeChecking.exceptions", "")).test(url))
+ return true;
+
+ // every check failed, this is a fishy cross-site mistyped inclusion
+
+ this.log("[NoScript] Blocking " + (nosniff ? "nosniff " : "cross-site ") +
+ (ctype === 2 ? "Javascript" : ctype === 3 ? "image" : "CSS") +
+ " served from " +
+ url +
+ " with wrong type info " + mime + " and included by " + (origin && origin.spec));
+ IOUtil.abort(channel);
+ return false;
+ }
+ }
+ }
+ } catch(e) {
+ if (this.consoleDump) this.dump("Error checking inclusion type for " + channel.name + ": " + e);
+ }
+ return true;
+ },
+
+ onContentSniffed: function(req) {
+ try {
+ let contentType;
+ let nosniff = this.nosniff && this.hasNoSniffHeader(req);
+ try {
+ contentType = req.contentType;
+ if (!contentType || contentType === "application/x-unknown-content-type") {
+ contentType = req.getResponseHeader("Content-type");
+ if (nosniff) {
+ nosniff = !contentType;
+ }
+ } else {
+ nosniff = false;
+ }
+ if (this.consoleDump & LOG_SNIFF) {
+ this.dump("OCS: " + req.name + ", " + contentType);
+ }
+ } catch(e) {
+ this.dump("OCS: " + req.name + ", CONTENT TYPE UNAVAILABLE YET");
+ if (!nosniff) return; // we'll check later in http-on-examine-merged-response
+ }
+ if (nosniff) {
+ try {
+ contentType = req.contentType = "text/plain";
+ ns.log("[NoScript] Force text/plain for missing content-type on " + req.name);
+ } catch(e) {
+ ns.dump(e);
+ }
+ }
+ if (IOUtil.isMediaDocOrFrame(req, contentType)) {
+ IOUtil.suspendChannel(req);
+ Thread.delay(() => IOUtil.resumeParentChannel(req), 100);
+ }
+ this.processXSSInfo(req);
+ } catch(e) {
+ if (this.consoleDump) this.dump(e);
+ }
+ },
+
+ onBeforeLoad: function(win) {
+ let docShell = DOM.getDocShellForWindow(win);
+ if (!docShell) return;
+ let channel = docShell.currentDocumentChannel;
+ if (!channel) return;
+ this.unserializeReqData(channel);
+
+ const uri = channel.URI;
+ const originURI = ABE.getOriginalOrigin(channel);
+
+ let contentType;
+ try {
+ contentType = channel.contentType;
+ } catch(e) {
+ contentType = "";
+ }
+
+ const topWin = win == win.top;
+
+ if (ns.reqData(channel).checkWindowName) {
+ InjectionChecker.checkWindowName(win, channel.URI.spec);
+ }
+
+ if (!IOUtil.isMediaDocOrFrame(channel, contentType)) {
+ return;
+ }
+
+ try {
+ let body = win.document.body;
+ let media = body && body.children.length === 1 && body.firstChild;
+ if (!(media instanceof win.HTMLMediaElement)) media = null;
+ if (this.shouldLoad(media ? 15 : 7, uri, topWin ? uri : originURI || uri, media || win.frameElement || win, contentType,
+ win.frameElement ? CP_FRAMECHECK : CP_SHOULDPROCESS) !== CP_OK) {
+
+ channel.loadFlags |= channel.INHIBIT_CACHING;
+
+ if (this.consoleDump & LOG_CONTENT_INTERCEPT)
+ this.dump("Media document content type detected");
+
+ if (media) {
+ if (this.consoleDump & LOG_CONTENT_BLOCK)
+ this.dump("Aborting media " + contentType);
+ IOUtil.abort(channel);
+ return;
+ }
+
+
+ if(!topWin) {
+ // check if this is an iframe
+
+ if (win.frameElement && !(win.frameElement instanceof win.HTMLFrameElement) &&
+ this.shouldLoad(5, uri, originURI || IOS.newURI(win.parent.location.href, null, null),
+ win.frameElement, contentType, CP_SHOULDPROCESS) === CP_OK) {
+ IOUtil.resumeParentChannel(channel);
+ return;
+ }
+
+ if (this.consoleDump & LOG_CONTENT_BLOCK)
+ this.dump("Deferring framed media document");
+
+ var url = uri.spec;
+
+ let browser = DOM.findBrowserForNode(win) || DOM.getFrameMM(win);
+ this.getRedirCache(browser, win.top.document.documentURI).push({site: this.getSite(url), type: 7});
+
+
+ Thread.asap(function() {
+ IOUtil.abort(channel);
+ if (docShell) {
+ var doc = docShell.document;
+ let tag = doc.body && doc.body.firstChild && doc.body.firstChild.tagName;
+ if (tag) {
+ docShell.loadURI(ns.createPluginDocumentURL(url,
+ tag ),
+ Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY,
+ null, null, null);
+ }
+ }
+ });
+
+ return;
+ }
+
+ this.dump("Blocking top-level plugin document");
+ Thread.asap(() => {
+ IOUtil.abort(channel);
+ for (let tag of ["embed", "video", "audio"]) {
+ let embeds = win.document.getElementsByTagName(tag);
+ if (embeds.length > 0 && (tag !== "embed" || this._abortPluginDocLoads)) {
+ let eType = "application/x-noscript-blocked";
+ let eURL = "data:" + eType + ",";
+ for (let j = embeds.length; j-- > 0;) {
+ let e = embeds.item(j);
+ if (this.shouldLoad(5, uri, null, e, contentType, CP_SHOULDPROCESS) !== CP_OK) {
+ e.src = eURL;
+ e.type = eType;
+ }
+ }
+ }
+ }
+ }, true);
+
+ return;
+ }
+ } catch (e) {
+ Cu.reportError(e);
+ IOUtil.abort(channel);
+ }
+ IOUtil.resumeParentChannel(channel);
+ },
+
+ get _abortPluginDocLoads() {
+ delete this._abortPluginDocLoads;
+ return (this._abortPluginDocLoads = this.geckoVersionCheck("18.0.1") < 0);
+ },
+
+ processXSSInfo(req) {
+ let browser = IOUtil.findBrowser(req);
+ if (browser) {
+ let overlay = this.findOverlay(browser);
+ if (overlay) {
+ overlay.setMetaRefreshInfo(null, browser);
+ let xssInfo = ns.reqData(req).XSS;
+ if (xssInfo) xssInfo.browser = browser;
+ this.requestWatchdog.unsafeReload(browser, false);
+ if (xssInfo) {
+ this.delayExec(() => overlay.notifyXSS(xssInfo), 500);
+ }
+ }
+ }
+ },
+
+ hasClearClickHandler: false,
+ get clearClickHandler() {
+ delete this.clearClickHandler;
+ this.hasClearClickHandler = true;
+ return this.clearClickHandler = new ClearClickHandler(this);
+ },
+
+ _pageModMaskRx: /^(?:chrome|resource|view-source):/,
+ onWindowSwitch: function(url, win, docShell) {
+ let channel = docShell.currentDocumentChannel;
+
+ if (ns.reqData(channel).xssChecked &&
+ this.filterBadCharsets(docShell)) return;
+
+ const doc = docShell.document;
+ const flag = "__noScriptEarlyScripts__";
+ if (flag in doc && doc[flag] === url) return;
+ doc[flag] = url;
+
+ const site = this.getSite(url);
+ var jsBlocked = !(docShell.allowJavascript && (this.jsEnabled || this.isJSEnabled(site, doc.defaultView)));
+
+
+
+ if (!((docShell instanceof nsIWebProgress) && docShell.isLoadingDocument)) {
+ // likely a document.open() page
+ url = "wyciwyg:"; // don't execute on document.open() pages with a misleading URL
+ jsBlocked = false;
+ }
+
+ if (channel) {
+ this.setExpando(win, "docJSBlocked", ns.reqData(channel).docJBlocked);
+ }
+
+ if (this._pageModMaskRx.test(url)) return;
+
+ var scripts;
+
+ if (jsBlocked) {
+ this.blockEvents(doc.defaultView);
+ } else {
+
+ if (this.implementToStaticHTML && !("toStaticHTML" in doc.defaultView)) {
+ scripts = [this._toStaticHTMLDef];
+ }
+
+ let dntPatch = DoNotTrack.getDOMPatch(docShell);
+ if (dntPatch) {
+ (scripts || (scripts = [])).push(dntPatch);
+ }
+
+ if (this.forbidWebGL) {
+ let script = WebGLInterception.hook(doc, site);
+ if (script) (scripts || (scripts = [])).push(script);
+ }
+
+ if (this.contentBlocker) {
+ if (this.liveConnectInterception && this.forbidJava &&
+ !this.isAllowedObject(site, "application/x-java-vm", site, site)) {
+ (doc.defaultView.wrappedJSObject || doc.defaultView).disablePlugins = this._disablePlugins;
+ (scripts || (scripts = [])).push(this._liveConnectInterceptionDef);
+ }
+ if (this.audioApiInterception && this.forbidMedia &&
+ !this.isAllowedObject(site, "audio/ogg", site, site))
+ (scripts || (scripts = [])).push(this._audioApiInterceptionDef);
+
+ if (this.forbidMedia && this.contentBlocker) {
+ let script = MSEInterception.hook(doc, site);
+ if (script) (scripts || (scripts = [])).push(script);
+ }
+ }
+
+ if (this.forbidFlash && this.flashPatch)
+ (scripts || (scripts = [])).push(this._flashPatch);
+
+ if (this.forbidSilverlight && this.silverlightPatch)
+ (scripts || (scripts = [])).push(this._silverlightPatch);
+
+ if( this.jsHackRegExp && this.jsHack && this.jsHackRegExp.test(url))
+ (scripts || (scripts = [])).push(this.jsHack);
+
+ if (ns.reqData(channel).protectName && this.getPref("protectWindowNameXAssignment")) {
+ (scripts || (scripts = [])).push(this._protectNamePatch);
+ }
+ }
+
+ ScriptSurrogate.apply(doc, url, url, jsBlocked, scripts);
+ },
+
+ onWindowCreated: function(window, site) {
+ if (this.consoleDump) this.dump(`1st onWindowCreated ${site}`);
+ try {
+ this.beforeScripting(window, site);
+ } catch(e) {
+ Cu.reportError(e);
+ }
+ (this.onWindowCreated = this._onWindowCreatedReal).apply(this, arguments);
+ },
+
+ isBrowserOrigin: (origin) => /^(?:\[System Principal\]$|moz-safe-about:)/.test(origin),
+
+ mustBlockJS: function(window, site, blocker) {
+ let document = window.document;
+ let origin = this.getPrincipalOrigin(this.getPrincipal(document));
+ if (this.isBrowserOrigin(origin)) return false;
+ let blockIt;
+ if (this.consoleDump) this.dump("Window created, origin: " + origin + ", site: " + site + ", URL: " + document.URL + ", location: " + window.location.href);
+
+ site = this.getSite(origin || site);
+ if (site === 'moz-nullprincipal:') {
+ site = this.getSite(document.URL);
+
+ if (!site) {
+ // "special" URI (e.g. data:), let's use opener
+ let docShell = DOM.getDocShellForWindow(window);
+ let channel = docShell.currentDocumentChannel;
+ if (channel) {
+ let loadInfo = channel.loadInfo;
+ if (loadInfo) {
+ let principal = loadInfo.triggeringPrincipal || loadInfo.loadingPrincipal;
+ if (principal) site = this.getSite(principal.origin);
+ }
+ }
+ }
+ }
+
+ window._NoScriptSite = site;
+
+ if (this.globalHttpsWhitelist && this.isGlobalHttps(window)) {
+ blockIt = false;
+ } else {
+ if ((this.cascadePermissions || this.restrictSubdocScripting) && window.top !== window) {
+ if (this.cascadePermissions) {
+ blockIt = blocker.isBlocked(window.top) || this.isUntrusted(site);
+ if (!blockIt) {
+ let topSite = window.top._NoScriptSite || this.getDocSite(window.top.document);
+ blockIt = !this.isJSEnabled(topSite);
+ }
+ } else if (this.restrictSubdocScripting && blocker.isBlocked(window.parent)) {
+ blockIt = true;
+ }
+ }
+ }
+
+ if (typeof blockIt === "undefined")
+ blockIt = !this.isJSEnabled(site);
+
+ if (blockIt) try {
+ // If the original content-type was */json but we morphed to text/html, JSON viewer kicked in
+ let docShell = DOM.getDocShellForWindow(window);
+ let channel = docShell.currentDocumentChannel;
+ if (channel instanceof Ci.nsIHttpChannel) {
+ let originalContentType = channel.getResponseHeader("Content-Type");
+ if (/\/json(?:;|$)/i.test(originalContentType) && channel.contentType === "text/html") blockIt = false;
+ }
+ } catch (e) {
+ this.log(e)
+ }
+
+ if (!blockIt && site.substring(0, 3) === "ftp") {
+ blockIt = InjectionChecker.checkURL(document.URL);
+ }
+
+ return blockIt;
+ },
+
+ _onWindowCreatedReal: function(window, site) {
+ this.onBeforeLoad(window);
+ try {
+ let mustBlock = this.mustBlockJS(window, site, WinScript);
+ if (this.consoleDump) this.dump(`${mustBlock ? "Forbidding" : "Allowing"} ${site}`);
+ if (mustBlock) {
+ WinScript.block(window);
+ } else {
+ WinScript.unblock(window);
+ }
+ } catch(e) {
+ Cu.reportError(e);
+ }
+ },
+
+ beforeScripting: function(subj, url) { // early stub
+ try {
+ INCLUDE("ScriptlessBGThumbs");
+ } catch(e) {
+ Cu.reportError(e);
+ }
+ if (!this.httpStarted) {
+
+ let url = subj.location || subj.documentURI;
+
+ if (/^(?:about|resource|chrome|file|moz-nullprincipal):/.test(url)) {
+ if (/^file|moz-/.test(url))
+ this.initContentPolicy(true);
+ return;
+ }
+ if (this.consoleDump) ns.dump(url);
+
+ }
+ this.executeEarlyScripts = this.onWindowSwitch;
+ // replace legacy code paths
+ if (subj.documentElement) { // we got document element inserted
+ this.onWindowSwitch = null;
+ }
+ this.beforeScripting = this._beforeScriptingReal;
+ this.beforeScripting(subj, url);
+ },
+ _beforeScriptingReal: function(subj, url) { // the real thing
+ const win = subj.defaultView || subj;
+ if (win instanceof Ci.nsIDOMChromeWindow) return;
+ const docShell = this.dom.getDocShellForWindow(win);
+ if (docShell) {
+ this.executeEarlyScripts(docShell.document.documentURI, win, docShell);
+ }
+ },
+
+ blockEvents: function(window) {
+ let et = ["start", "finish", "bounce"],
+ eh = function(e) { e.preventDefault(); e.stopPropagation(); };
+
+ return (this.blockEvents = function(window) {
+ for (let t of et) window.addEventListener(t, eh, true);
+ })(window);
+ },
+
+ get sanitizeHTML() {
+ delete this.sanitizeHTML;
+ return this.sanitizeHTML = ("nsIParserUtils" in Ci)
+ ? function(s, t) {
+ t.innerHTML = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils).sanitize(s, 0)
+ }
+ : function(s, t) {
+ t.appendChild(Cc["@mozilla.org/feed-unescapehtml;1"].getService(Ci.nsIScriptableUnescapeHTML)
+ .parseFragment(s, false, null, t));
+ };
+ },
+ get implementToStaticHTML() {
+ delete this.implementToStaticHTML;
+ return this.implementToStaticHTML = this.getPref("toStaticHTML");
+ },
+ sanitizeStaticDOM: function(el) {
+ // remove attributes from forms
+ for (let f of Array.slice(el.getElementsByTagName("form"))) {
+ for (let a of Array.slice(f.attributes)) {
+ f.removeAttribute(a.name);
+ }
+ }
+ let doc = el.ownerDocument;
+ // remove dangerous URLs (e.g. javascript: or data: or reflected XSS URLs)
+ for (let a of ['href', 'to', 'from', 'by', 'values']) {
+ let res = doc.evaluate('//@' + a, el, null, Ci.nsIDOMXPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (let j = res.snapshotLength; j-- > 0;) {
+ let attr = res.snapshotItem(j);
+ if (InjectionChecker.checkURL(attr.nodeValue))
+ attr.nodeValue = "";
+ }
+ }
+ },
+ toStaticHTMLHandler: function(ev) {
+ try {
+ var t = ev.target;
+ var doc = t.ownerDocument;
+ t.parentNode.removeChild(t);
+ var s = t.getAttribute("data-source");
+ ns.sanitizeHTML(s, t);
+ ns.sanitizeStaticDOM(t);
+ } catch(e){ if (ns.consoleDump) ns.dump(e) }
+ },
+ get _toStaticHTMLDef() {
+ delete this._toStaticHTMLDef;
+ return this._toStaticHTMLDef =
+ "window.toStaticHTML = " +
+ (
+ function toStaticHTML(s) {
+ var t = document.createElement("toStaticHTML");
+ t.setAttribute("data-source", s);
+ document.documentElement.appendChild(t);
+ var ev = document.createEvent("Events");
+ ev.initEvent("NoScript:toStaticHTML", true, false);
+ t.dispatchEvent(ev);
+ return t.innerHTML;
+ }
+ ).toString();
+ },
+
+ liveConnectInterception: true,
+ get _liveConnectInterceptionDef() {
+ delete this._liveConnectInterceptionDef;
+ return this._liveConnectInterceptionDef = function() {
+ const w = window;
+ var dp = w.disablePlugins;
+ delete w.disablePlugins;
+ const g = function() {
+ const d = document;
+ const o = d.createElement("object");
+ o.type = "application/x-java-vm";
+ o.data = "data:" + o.type + ",";
+ d.documentElement.appendChild(o);
+ d.documentElement.removeChild(o);
+ const k = function() {};
+ w.__defineGetter__("java", k);
+ w.__defineGetter__("Packages", k);
+ }
+
+ try {
+ dp(true);
+ w.__defineGetter__("java", g);
+ w.__defineGetter__("Packages", g);
+ } finally {
+ dp(false);
+ }
+ }.toSource() + "()";
+ },
+
+ audioApiInterception: true,
+ _audioApiInterceptionDef:
+ ("defineProperty" in Object)
+ ? 'Object.defineProperty(HTMLAudioElement.prototype, "mozWriteAudio", {value: function() {new Audio("data:,")}});'
+ : "",
+ _disablePlugins: function(b) {
+ ns.plugins.disabled = b;
+ },
+
+ get plugins() {
+ delete this.plugins;
+ INCLUDE("Plugins");
+ return this.plugins = Plugins;
+ },
+
+ beforeManualAllow: function(win) {
+ // reset prevBlock info, to forcibly allow docShell JS
+ this.setExpando(win.document, "prevBlocked", { value: "m" });
+ },
+
+ handleErrorPage: function(win, uri) {
+ win = win && win.contentWindow || win;
+ if (!win) return;
+ var docShell = DOM.getDocShellForWindow(win);
+ if (!docShell) return;
+
+ docShell.allowJavascript = true;
+
+ },
+
+
+ // start nsIWebProgressListener
+
+
+ onLinkIconAvailable: DUMMY_FUNC,
+ onStateChange: function(wp, req, stateFlags, status) {
+ var ph;
+
+ if (stateFlags & WP_STATE_START) {
+ if (req instanceof Ci.nsIChannel) {
+ // handle docshell JS switching and other early duties
+
+ if (PolicyState.isChecking(req.URI)) {
+ // ContentPolicy couldn't complete! DOS attack?
+ PolicyState.removeCheck(req.URI);
+ IOUtil.abort(req);
+ this.log("Aborted " + req.URI.spec + " on start, possible DOS attack against content policy.");
+ return;
+ }
+
+ PolicyState.attach(req); // this is needed after bug 797684 fix, because http observers are notified later
+
+ if ((stateFlags & WP_STATE_START_DOC) == WP_STATE_START_DOC) {
+ if (!(req instanceof Ci.nsIHttpChannel) && (
+ // prevent about:newTab breakage
+ req.URI.spec == "about:blank" && !IOUtil.extractInternalReferrer(req) && Bug.$771655 ||
+ req.URI.schemeIs("data") && Bug.$789773 ||
+ DOM.browserWinURI && req.URI.equals(DOM.browserWinURI)
+ )
+ ) return;
+
+ let w = wp.DOMWindow;
+ if (w) {
+
+ if (w != w.top && w.frameElement) {
+ ph = ph || PolicyState.extract(req);
+ if (ph && this.shouldLoad(7, req.URI, ph.requestOrigin, w.frameElement, ph.mimeType, CP_FRAMECHECK) != CP_OK) { // late frame/iframe check
+ IOUtil.abort(req);
+ return;
+ }
+ }
+ }
+ }
+ }
+ } else if ((stateFlags & WP_STATE_STOP)) {
+ // STOP REQUEST
+ if (req instanceof Ci.nsIHttpChannel) {
+ this.cleanupRequest(req);
+
+ if (status === NS_ERROR_CONNECTION_REFUSED || status === NS_ERROR_NOT_AVAILABLE ||
+ status === NS_ERROR_UNKNOWN_HOST) { // evict host from DNS cache to prevent DNS rebinding
+ try {
+ var host = req.URI.host;
+ if (host) {
+ if (status === NS_ERROR_UNKNOWN_HOST) {
+ DNS.invalidate(host);
+ } else {
+ DNS.evict(host);
+ }
+ }
+ } catch(e) {}
+ }
+ }
+ }
+ },
+
+ onLocationChange(wp, req, location) {},
+ onLocationChange2(wp, req, location, flags) {},
+
+ onStatusChange: function(wp, req, status, msg) {
+ if (status == 0x804b0003 && (req instanceof Ci.nsIChannel) && typeof ns === "object" && !ABE.isDeferred(req)) { // DNS resolving, check if we need to clear the cache
+ try {
+ var host = req.URI.host;
+ if (host) {
+ var loadFlags = req.loadFlags;
+ var cached = DNS.getCached(host);
+ if (cached.expired ||
+ loadFlags & LF_VALIDATE_ALWAYS ||
+ loadFlags & LF_LOAD_BYPASS_ALL_CACHES) {
+ DNS.evict(host);
+ }
+ }
+ } catch (e) {}
+ }
+ },
+ onSecurityChange: DUMMY_FUNC,
+ onProgressChange: DUMMY_FUNC,
+ onRefreshAttempted: function(wp, uri, delay, sameURI) {
+ if (delay == 0 && !sameURI)
+ return true; // poor man's redirection
+
+ var pref = this.getPref("forbidBGRefresh");
+ try {
+ if (!pref || this.prefService.getBoolPref("accessibility.blockautorefresh"))
+ return true; // let the browser do its thing
+ } catch(e) {}
+
+ var win = wp.DOMWindow;
+ var currentURL = win.location.href;
+ if (!this.appliesHere(pref, currentURL))
+ return true;
+
+ var browserWin = DOM.mostRecentBrowserWindow;
+ if (!(browserWin && "noscriptOverlay" in browserWin))
+ return true; // not a regular browser window
+
+ var exceptions = new AddressMatcher(this.getPref("forbidBGRefresh.exceptions"));
+ if (exceptions && exceptions.test(currentURL))
+ return true;
+
+ var browser = DOM.findBrowserForNode(win);
+ var currentBrowser = browserWin.noscriptOverlay.currentBrowser;
+ var docShell = DOM.getDocShellForWindow(win);
+
+ var uiArgs = Array.slice(arguments);
+
+ var ts = Date.now();
+
+ if (browser == currentBrowser) {
+ win.addEventListener("blur", function(ev) {
+ ev.currentTarget.removeEventListener(ev.type, arguments.callee, false);
+ docShell.suspendRefreshURIs();
+ hookFocus(false);
+ }, false);
+ return true; // OK, this is the foreground tab
+ }
+
+
+ function hookFocus(bg) {
+ ns.log("[NoScript] Blocking refresh on unfocused tab, " + currentURL + "->" + uri.spec, false);
+ win.addEventListener("focus", function(ev) {
+ ev.currentTarget.removeEventListener(ev.type, arguments.callee, false);
+ if ((docShell instanceof Ci.nsIRefreshURI) &&
+ (bg || docShell.refreshPending)) {
+ var toGo = Math.round((delay - (Date.now() - ts)) / 1000);
+ if (toGo < 1) toGo = 1;
+ ns.setupRefresh(docShell, docShell.currentURI, toGo + ";" + uri.spec);
+ docShell.resumeRefreshURIs();
+ }
+ }, false);
+ }
+ hookFocus(true);
+ return false;
+ },
+ // end nsIWebProgressListener
+
+ _badCharsetRx: /\bUTF-?7\$|^armscii-8$/i,
+ _goodCharsetRx: /^UTF-?8$/i,
+ filterBadCharsets: function(docShell) {
+ try {
+ let charsetInfo = docShell.documentCharsetInfo || docShell;
+ let cs;
+ try {
+ cs = charsetInfo.charset;
+ } catch (e) {
+ cs = docShell.document.characterSet;
+ }
+
+ if (this._goodCharsetRx.test(cs)) return false;
+
+ if(this._badCharsetRx.test(cs)) {
+ this.log("[NoScript XSS] Neutralizing bad charset " + cs);
+ } else {
+ let uri = docShell.currentURI;
+ if (!(uri instanceof Ci.nsIURL)) return false;
+ let url = unescape(uri.spec);
+ try {
+ let exceptions = this.getPref("xss.checkCharset.exceptions");
+ if (exceptions && AddressMatcher.create(exceptions).test(url)) return false;
+ } catch (e) {}
+
+ let ic = this.injectionChecker;
+ let unicode = /^UTF-?16/i.test(cs) && url.indexOf("\0") !== -1;
+ let le = unicode && /LE$/i.test(cs);
+
+ function decode(u) {
+ if (unicode) {
+ let pos = u.indexOf("\0");
+ if (pos > -1) {
+ if (le) pos--;
+ return u.substring(0, pos) + ic.toUnicode(u.substring(pos), cs);
+ }
+ }
+ return ic.toUnicode(u, cs);
+ }
+
+ let check = (original, decoded) => original === decoded || !ic.checkRecursive(decoded, 1);
+
+ let [filePath, query, ref] = ["filePath", "query", "ref"].map((p) => unescape(uri[p]));
+
+ if ( // check...
+ // ...whole URL
+ check(url, decode(url)) &&
+ // ...whole path
+ check(filePath, decode(filePath)) &&
+ // ...path parts
+ check(filePath, uri.filePath.split("/").map((p) => decode(unescape(p))).join("/")) &&
+ // ... whole query
+ check(query, decode(query)) &&
+ // ... query parts
+ check(query, uri.query.split("&").map((p) => p.split("=").map((p) => decode(unescape(p))).join("=")).join("&")) &&
+ // ... fragment
+ check(ref, decode(ref))
+ ) return false;
+
+ this.log("[NoScript XSS] Potential XSS with charset " + cs + ", aborting request");
+ }
+
+ this.requestWatchdog.abortChannel(docShell.currentDocumentChannel);
+ return true;
+ } catch(e) {
+ ns.log(e)
+ if (this.consoleDump) this.dump("Error filtering charset " + e);
+ }
+ return false;
+ },
+
+ _attemptNavigationInternal: function(doc, destURL, callback) {
+ var cs = doc.characterSet;
+ var uri = IOS.newURI(destURL, cs, IOS.newURI(doc.documentURI, cs, null));
+
+ if (/^https?:\/\//i.test(destURL)) callback(doc, uri);
+ else {
+ var done = false;
+ var req = ns.createCheckedXHR("HEAD", uri.spec, function() {
+ if (req.readyState < 2) return;
+ try {
+ if (!done && req.status) {
+ done = true;
+ if (req.status == 200) callback(doc, uri);
+ req.abort();
+ }
+ } catch(e) {}
+ }, doc.defaultView);
+ req.send(null);
+ }
+ },
+ attemptNavigation: function(doc, destURL, callback) {
+ // delay is needed on Gecko < 1.9 to detach browser context
+ this.delayExec(this._attemptNavigationInternal, 0, doc, destURL, callback);
+ },
+
+ // simulate onchange on selects if options look like URLs
+ onContentChange: function(ev) {
+ var s = ev.originalTarget;
+ if (!(s instanceof s.ownerDocument.defaultView.HTMLSelectElement) ||
+ s.hasAttribute("multiple") ||
+ !/open|nav|location|\bgo|load/i.test(s.getAttribute("onchange"))) return;
+
+ var opt = s.options[s.selectedIndex];
+ if (!opt) return;
+
+ if (/[\/\.]/.test(opt.value) && opt.value.indexOf("@") < 0) {
+ this.attemptNavigation(s.ownerDocument, opt.value, function(doc, uri) {
+ doc.defaultView.location.href = uri.spec;
+ });
+ ev.preventDefault();
+ }
+ },
+
+ onContentClick: function(ev) {
+
+ if (ev.button == 2) return;
+
+ var a = ev.originalTarget;
+
+ if (a.__noscriptFixed) return;
+
+ var doc = a.ownerDocument;
+ let w = doc.defaultView;
+
+ let onclick;
+
+ while (!(a instanceof w.HTMLAnchorElement || a instanceof w.HTMLAreaElement)) {
+ if (typeof(a.getAttribute) == "function" && (onclick = a.getAttribute("onclick"))) break;
+ if (!(a = a.parentNode)) return;
+ }
+
+ const href = a.getAttribute("href");
+ // fix JavaScript links
+ var jsURL;
+ if (href) {
+ jsURL = /^javascript:/i.test(href);
+ if (!(jsURL || href == "#")) return;
+ } else {
+ jsURL = "";
+ }
+
+ onclick = onclick || a.getAttribute("onclick");
+ var fixedHref = (onclick && this.extractJSLink(onclick)) ||
+ (jsURL && this.extractJSLink(href)) || "";
+
+ onclick = onclick || href;
+
+ if (/\bsubmit\s*\(\s*\)/.test(onclick)) {
+ var form;
+ if (fixedHref) {
+ form = doc.getElementById(fixedHref); // youtube
+ if (!(form instanceof w.HTMLFormElement)) {
+ form = doc.forms.namedItem(fixedHref);
+ }
+ }
+ if (!form) {
+ var m = onclick.match(/(?:(?:\$|document\.getElementById)\s*\(\s*["']#?([\w\-]+)[^;]+|\bdocument\s*\.\s*(?:forms)?\s*(?:\[\s*["']|\.)?([^\.\;\s"'\]]+).*)\.submit\s*\(\)/);
+ form = m && (/\D/.test(m[1]) ? (doc.forms.namedItem(m[1]) || doc.getElementById(m[1])) : doc.forms.item(parseInt(m[1])));
+ if (!(form && (form instanceof w.HTMLFormElement))) {
+ while ((form = a.parentNode) && form != doc && !form instanceof w.HTMLFormElement);
+ }
+ }
+ if (form && (form instanceof w.HTMLFormElement)) {
+ form.submit();
+ ev.preventDefault();
+ }
+ return;
+ }
+
+ if (fixedHref) {
+ var callback;
+ if (/^(?:button|input)$/i.test(a.tagName)) { // JS button
+ if (a.type == "button" || (a.type == "submit" && !a.form)) {
+ callback = function(doc, uri) { doc.defaultView.location.href = uri.spec; };
+ } else return;
+ } else {
+ var evClone = doc.createEvent("MouseEvents");
+ evClone.initMouseEvent("click",ev.canBubble, ev.cancelable,
+ ev.view, ev.detail, ev.screenX, ev.screenY,
+ ev.clientX, ev.clientY,
+ ev.ctrlKey, ev.altKey, ev.shiftKey, ev.metaKey,
+ ev.button, ev.relatedTarget);
+ callback =
+ function(doc, uri) {
+ a.setAttribute("href", fixedHref);
+ var title = a.getAttribute("title");
+ a.setAttribute("title", title ? "[js] " + title :
+ (onclick || "") + " " + href
+ );
+ a.dispatchEvent(ev = evClone); // do not remove "ev = " -- for some reason, it works this way only :/
+ };
+ a.__noscriptFixed = true;
+ }
+ if (callback) {
+ this.attemptNavigation(doc, fixedHref, callback);
+ ev.preventDefault();
+ }
+ } else { // try processing history.go(n) //
+ if(!onclick) return;
+
+ jsURL = onclick.match(/history\s*\.\s*(?:go\s*\(\s*(-?\d+)\s*\)|(back|forward)\s*\(\s*)/);
+ jsURL = jsURL && (jsURL = jsURL[1] || jsURL[2]) && (jsURL == "back" ? -1 : jsURL == "forward" ? 1 : jsURL);
+
+ if (!jsURL) return;
+ // jsURL now has our relative history index, let's navigate
+
+ var docShell = DOM.getDocShellForWindow(doc.defaultView);
+ if (!docShell) return;
+ var sh = docShell.sessionHistory;
+ if (!sh) return;
+
+ var idx = sh.index + jsURL;
+ if (idx < 0 || idx >= sh.count) return; // out of history bounds
+ docShell.gotoIndex(idx);
+ ev.preventDefault(); // probably not needed
+ }
+ },
+
+ extractJSLink: function(js) {
+ const findLink = /(['"])(.*?)\1/g;
+ const badURIChar = /[^\/\w-\?\.#%=&:@]/;
+ findLink.lastIndex = 0;
+ var maxScore = 0;
+ var m, href;
+ while ((m = findLink.exec(js))) {
+ let s = m[2];
+ if (/^https?:\/\//.test(s)) return s;
+ let score = (badURIChar.test(s) ? 0 : 3) +
+ (s.split("/").length - 1) * 2 +
+ s.split("."). length - 1;
+ if (score > maxScore) {
+ maxScore = score;
+ href = s;
+ }
+ }
+ return href || "";
+ },
+
+
+ checkLocalLink: function(url, principal, fromPolicy) {
+
+ if (!this.allowLocalLinks)
+ return fromPolicy;
+
+ if (!principal) return true;
+
+ if (url instanceof Ci.nsIURI) {
+ if (!url.schemeIs("file")) return fromPolicy;
+ url = url.spec;
+ } else if (typeof url !== "string" || url.indexOf("file:///") !== 0) return fromPolicy;
+ let site = principal.URI ? principal.URI.spec : this.getPrincipalOrigin(principal);
+
+ if (!/^(ht|f)tps?:/.test(site)) return fromPolicy;
+
+ let [to, from] = ["to", "from"].map(function(n) { return AddressMatcher.create(ns.getPref("allowLocalLinks." + n, "")) });
+
+ return ((from
+ ? from.test(site)
+ : this.isJSEnabled(this.getSite(site)))
+ && (!to || to.test(url))
+ );
+ },
+
+ createXSanitizer: function() {
+ return new XSanitizer(this.filterXGetRx, this.filterXGetUserRx);
+ },
+
+ get externalFilters() {
+ delete this.externalFilters;
+ if (("nsIProcess2" in Ci || // Fx 3.5
+ "runAsync" in Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess) // Fx >= 3.6
+ )) {
+ INCLUDE("ExternalFilters");
+ this.externalFilters = ExternalFilters;
+ this.externalFilters.initFromPrefs("noscript.ef.");
+ } else this.externalFilters = { enabled: false, supported: false };
+ return this.externalFilters;
+ },
+
+ callExternalFilters: function(ch, cached) {
+ var ph = PolicyState.extract(ch);
+ if (ph) {
+ switch (ph.contentType) {
+ case 5: case 12:
+ this.externalFilters.handle(ch, ph.mimeType, ph.context, cached);
+ }
+ }
+ },
+
+ switchExternalFilter: function(filterName, domain, enabled) {
+ var f = this.externalFilters.byName(filterName);
+ if (!f) return;
+
+ var done;
+ if (enabled) {
+ done = f.removeDomainException(domain);
+ } else {
+ done = f.addDomainException(domain);
+ }
+ if (!done) return;
+
+ this.delayExec(this.traverseObjects, 0,
+ function(p) {
+ const info = this.externalFilters.getObjFilterInfo(p);
+ if (!info) return;
+
+ if (this.getBaseDomain(this.getDomain(info.url)) == domain) {
+ this.externalFilters.log("Reloading object " + info.url);
+ var anchor = p.nextSibling;
+ p.parentNode.removeChild(p);
+ anchor.parentNode.insertBefore(p, anchor);
+ }
+ }, this);
+ },
+
+ get compatEvernote() {
+ delete this.compatEvernote;
+ return this.compatEvernote = ("IWebClipper3" in Ci) && this.getPref("compat.evernote") && {
+ onload: function(ev) {
+ var f = ev.currentTarget;
+ if ((f.__evernoteLoadCount = (f.__evernoteLoadCount || 0) + 1) >= 7) {
+ f.removeEventListener(ev.type, arguments.callee, false);
+ var id = f.id.replace(/iframe/g, "clipper");
+ for (var box = f.parentNode; box && box.id != id; box = box.parentNode);
+ if (box) box.parentNode.removeChild(box);
+ }
+ }
+ }
+ },
+
+ get compatGNotes() {
+ delete this.compatGNotes;
+ return this.compatGNotes = ("@google.com/gnotes/app-context;1" in Cc) && this.getPref("compat.gnotes") &&
+ "http://www.google.com/notebook/static_files/blank.html";
+ },
+
+ consoleService: Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService),
+
+ log: function(msg, dump) {
+ if (msg.stack) msg += msg.stack;
+ this.consoleService.logStringMessage(msg);
+ if (dump) this.dump(msg, true);
+ },
+
+ logError: function(e, dump, cat) {
+ var se = Cc["@mozilla.org/scripterror;1"].createInstance(Ci.nsIScriptError);
+ se.init(e.message, e.fileName, /^javascript:/i.test(e.fileName) ? e.fileName : null,
+ e.lineNumber, 0, 0, cat || "Component JS");
+ if (dump && this.consoleDump) this.dump(e.message, true);
+ this.consoleService.logMessage(se);
+ },
+
+ dump: function(msg, noConsole) {
+ if (!this.consoleDump) return;
+ if (msg.stack) msg += msg.stack;
+ msg = `[NoScript ${this.childProcess ? "C" : "P"}] ${msg}`;
+ try {
+ dump(`${msg}\n`);
+ if(this.consoleLog && !noConsole) this.log(msg);
+ } catch (e) {
+ this.log(`Error ${e} while logging "${msg}"`);
+ }
+ },
+
+
+
+}
+
+ns.wrappedJSObject = ns;
+ns.__global__ = this; // debugging helper necessary on Gecko >= 13
+ns._e = function(f) {
+ return eval("(" + f + ")()");
+}
+var Main = ns;
+
+
diff --git a/extensions/noscript/chrome/content/noscript/MainChild.js b/extensions/noscript/chrome/content/noscript/MainChild.js
new file mode 100644
index 0000000..4611d52
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/MainChild.js
@@ -0,0 +1,870 @@
+var MainChild = {
+ beforeInit: function() {
+ // can't use big preference values in the child process
+ INCLUDE("Membrane");
+ let proto = PolicySites.prototype;
+ proto.toPref = () => {};
+ let fromPref = proto.fromPref;
+ let wrap = (target, propKey) => propKey === "getCharPref" ?
+ name => Services.cpmm.sendSyncMessage(IPC_P_MSG.GET_PREF, {method: propKey, name: target.root + name})[0]
+ : target[propKey];
+ proto.fromPref = function(pref, ...args) {
+ return fromPref.call(this, Membrane.create(pref, wrap), ...args);
+ };
+ },
+ afterInit: function() {
+ let snapshot = Services.cpmm.sendSyncMessage(IPC_P_MSG.GET_SNAPSHOT)[0];
+ this.setSnapshot(snapshot);
+ this.initContentPolicy(true);
+ },
+
+ "http-on-opening-request": {
+ observe: function(channel, topic, data) {
+ INCLUDE("Policy");
+ delete this.observe;
+ (this.observe = this._observe)(channel, topic, data);
+ },
+ _observe: function(channel, topic, data) {
+ if (channel instanceof Ci.nsIHttpChannel) PolicyState.attach(channel);
+ }
+ },
+
+ blockWhereNeeded(browser) {
+ this.traverseDocShells(function(docShell) {
+ let site = this.getDocSite(docShell.document);
+ if (!(this.isJSEnabled(site) || this.checkShorthands(site))) {
+ try {
+ WinScript.block(docShell.document.defaultView);
+ } catch(e) {
+ ns.log("Failed blocking " + site + ": " + e);
+ }
+ }
+ return false;
+ }, this, browser);
+ },
+
+ _lastSnapshot: {
+ timestamp: 0,
+ lastUntrustedSites: null,
+ lastTrustedSites: null,
+ },
+ reload(browser, snapshots, mustReload, reloadPolicy, innerWindowID = 0) {
+ let isCurrentFrame = innerWindowID && innerWindowID == browser.content.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
+ if (!isCurrentFrame && innerWindowID && reloadPolicy === this.RELOAD_ALL) {
+ Thread.delay(() => this.reload(browser, snapshots, mustReload, reloadPolicy), 50);
+ return;
+ }
+
+ this.blockWhereNeeded(browser);
+
+ let { previous, current, timestamp } = snapshots;
+ let { lastTrusted, lastUntrusted, lastGlobal, lastObjects } = previous;
+ if (timestamp !== this._lastSnapshot.timestamp) {
+ this.jsPolicySites.sitesString = current.lastTrusted;
+ this.untrustedSites.sitesString = current.lastUntrusted;
+ this.objectWhitelist = JSON.parse(current.lastObjects);
+ this.jsEnabled = current.lastGlobal;
+ this._lastSnapshot = {
+ timestamp,
+ lastTrustedSites: new PolicySites(lastTrusted),
+ lastUntrustedSites: new PolicySites(lastUntrusted)
+ };
+ this.initContentPolicy();
+ }
+
+ if (!mustReload ||
+ !isCurrentFrame && reloadPolicy === this.RELOAD_CURRENT
+ ) {
+ return;
+ }
+
+ let { lastTrustedSites, lastUntrustedSites } = this._lastSnapshot;
+
+ let webNav = browser.webNavigation || browser.docShell.QueryInterface(Ci.nsIWebNavigation);
+ let sites = this.getSites(browser);
+ let allSites = sites.all;
+ let noFrames = sites.docSites.length === 1;
+
+ for (let j = 0, len = allSites.length; j < allSites.length; j++) {
+ let site = allSites[j];
+
+ let checkTop;
+
+ if (j === 0 && noFrames) // top level, if unchanged and forbidden we won't reload
+ {
+ checkTop = sites.topSite === site;
+ if (!checkTop) {
+ checkTop = true;
+ site = sites.topSite;
+ j = allSites.indexOf(site);
+ if (j > -1) {
+ allSites.splice(j, 1, sites[0]);
+ allSites[j = 0] = site;
+ } else {
+ len++;
+ allSites.unshift(site);
+ }
+ }
+ } else checkTop = false;
+
+ let prevStatus =
+ !(lastGlobal ? this.alwaysBlockUntrustedContent && lastUntrustedSites.matches(site)
+ : !(lastTrustedSites.matches(site) || this.checkShorthands(site, lastTrustedSites)) || lastUntrustedSites.matches(site)
+ );
+ let currStatus = this.isJSEnabled(site) || !!this.checkShorthands(site);
+
+ if (currStatus != prevStatus) {
+ this.quickReload(webNav);
+ return;
+ }
+
+ if (checkTop && !currStatus) {
+ // top level, unchanged and forbidden: don't reload
+ j = len;
+ break;
+ }
+ }
+
+ // check plugin objects
+ if (this.consoleDump & LOG_CONTENT_BLOCK) {
+ this.dump("Checking object permission changes...");
+ try {
+ this.dump(sites.toSource() + ", " + lastObjects);
+ } catch(e) {}
+ }
+ if (this.checkObjectPermissionsChange(sites, JSON.parse(lastObjects))) {
+ this.quickReload(webNav);
+ }
+
+ },
+
+
+ reloadAllowedObjectsChild: function(browser, mime) {
+ let docShell = browser.docShell.QueryInterface(Ci.nsIWebNavigation);
+
+ if (mime === "WebGL" && WebGLInterception.reloadAllowed(docShell))
+ return;
+
+ if (this.getPref("autoReload.onMultiContent", false)) {
+ this.quickReload(docShell);
+ return;
+ }
+ var reloadEmbedders = this.getPref("autoReload.embedders");
+ var canReloadPage = reloadEmbedders == 1 ? this.getPref("autoReload") : !!(reloadEmbedders);
+
+ var sites = this.getSites(browser);
+ var egroup, j, e;
+ for (egroup of sites.pluginExtras) {
+ for (j = egroup.length; j-- > 0;) {
+ e = egroup[j];
+ if (this.isAllowedObject(e.url, e.mime, e.site, e.originSite)) {
+ if (e.placeholder && e.placeholder.parentNode) {
+ e.skipConfirmation = true;
+ this.checkAndEnablePlaceholder(e.placeholder);
+ } else if (!(e.allowed || e.embed) && canReloadPage) {
+ if (e.document) {
+ this.quickReload(DOM.getDocShellForWindow(e.document.defaultView));
+ break;
+ } else {
+ this.quickReload(docShell);
+ return;
+ }
+ }
+ }
+ }
+ }
+ },
+
+ checkObjectPermissionsChange: function(sites, snapshot) {
+ if(this.objectWhitelist == snapshot) return false;
+ for (let url in snapshot) {
+ let s = this.getSite(url);
+ if (!(s in snapshot)) snapshot[s] = snapshot[url];
+ }
+ for (let s of sites.pluginSites) {
+ s = this.objectKey(s);
+ if ((s in snapshot) && !(s in this.objectWhitelist)) {
+ return true;
+ }
+ }
+
+ for (let egroup of sites.pluginExtras) {
+ for (let j = 0, len = egroup.length; j < len; j++) {
+ let e = egroup[j];
+ let url;
+ if (!e.placeholder && e.url && ((url = this.objectKey(e.url)) in snapshot) && !(url in this.objectWhitelist)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+
+ quickReload: function(webNav, checkNullCache) {
+ if (!(webNav instanceof Ci.nsIWebNavigation)) {
+ webNav = DOM.getDocShellForWindow(webNav);
+ }
+
+ var uri = webNav.currentURI;
+
+ if (checkNullCache && (webNav instanceof Ci.nsIWebPageDescriptor)) {
+ try {
+ var ch = IOUtil.newChannel(uri.spec, null, null);
+ if (ch instanceof Ci.nsICachingChannel) {
+ ch.loadFlags |= ch.LOAD_ONLY_FROM_CACHE;
+ ch.cacheKey = webNav.currentDescriptor.QueryInterface(Ci.nsISHEntry).cacheKey;
+ if (ch.open().available() == 0) {
+ webNav.reload(webNav.LOAD_FLAGS_BYPASS_CACHE);
+ return;
+ }
+ }
+ } catch(e) {
+ if (this.consoleDump) this.dump(e);
+ } finally {
+ try {
+ ch.close();
+ } catch(e1) {}
+ }
+ }
+
+ webNav.reload(webNav.LOAD_FLAGS_CHARSET_CHANGE);
+ },
+
+ // These catch both Paypal's variant,
+ // if (parent.frames.length > 0){ top.location.replace(document.location); }
+ // and the general concise idiom with its common reasonable permutations,
+ // if (self != top) top.location = location
+ _frameBreakNoCapture: /\bif\s*\(\s*(?:(?:(?:window|self|top)\s*\.\s*)*(?:window|self|top)\s*!==?\s*(?:(?:window|self|top)\s*\.\s*)*(?:window|self|top)|(?:(?:window|self|parent|top)\s*\.\s*)*(?:parent|top)\.frames\.length\s*(?:!==?|>)\s*0)\s*\)\s*\{?\s*(?:window\s*\.\s*)?top\s*\.\s*location\s*(?:\.\s*(?:replace|assign)\s*\(|(?:\s*\.\s*href\s*)?=)\s*(?:(?:document|window|self)\s*\.\s*)?location(?:\s*.\s*href)?\s*\)?\s*;?\s*\}?/,
+ _frameBreakCapture: /^\(function\s[^\{]+\{\s*if\s*\(\s*(?:(?:(?:window|self|top)\s*\.\s*)*(window|self|top)\s*!==?\s*(?:(?:window|self|top)\s*\.\s*)*(window|self|top)|(?:(?:window|self|parent|top)\s*\.\s*)*(?:parent|top)\.frames\.length\s*(?:!==?|>)\s*0)\s*\)\s*\{?\s*(?:window\s*\.\s*)?top\s*\.\s*location\s*(?:\.\s*(?:replace|assign)\s*\(|(?:\s*\.\s*href\s*)?=)\s*(?:(?:document|window|self)\s*\.\s*)?location(?:\s*.\s*href)?\s*\)?\s*;?\s*\}?/,
+ doEmulateFrameBreak: function(w) {
+ // If JS is disabled we check the top 5 script elements of the page searching for the first inline one:
+ // if it starts with a frame breaker, we honor it.
+ var d = w.document;
+ var url = d.URL;
+ if (url.indexOf("http") !== 0 || this.isJSEnabled(this.getSite(url), w)) return false;
+ var ss = d.getElementsByTagName("script");
+ var sc, m, code;
+ try {
+ for (var j = 0, len = 5, s; j < len && (s = ss[j]); j++) {
+ code = s.textContent;
+ if (code && /\S/.test(code)) {
+ if (this._frameBreakNoCapture.test(code)) {
+ try {
+ sc = sc || new SyntaxChecker();
+ var m;
+ if (sc.check(code) &&
+ (m = sc.lastFunction.toSource().match(this._frameBreakCapture)) &&
+ (!m[1] || (m[1] == "top" || m[2] == "top") && m[1] != m[2])) {
+ var top = w.top;
+
+ var docShell = DOM.getDocShellForWindow(top);
+ var allowJavascript = docShell.allowJavascript;
+ var allowPlugins = docShell.allowPlugins;
+ if (allowJavascript) { // temporarily disable JS & plugins on the top frame to prevent counter-busting
+ docShell.allowJavascript = docShell.allowPlugins = false;
+ top.addEventListener("pagehide", function(ev) {
+ ev.currentTarget.removeEventListener(ev.type, arguments.calle, false);
+ docShell.allowJavascript = allowJavascript;
+ docShell.allowPlugins = allowPlugins;
+ }, false);
+ }
+ top.location.href = url;
+ var body = d.body;
+ if (body) while(body.firstChild) body.removeChild(body.firstChild);
+ return true;
+ }
+ } catch(e) {
+ this.dump("Error checking " + code + ": " + e.message);
+ }
+ }
+ break; // we want to check the first inline script only
+ }
+ }
+ } finally {
+ if (sc) Cu.nukeSandbox(sc.sandbox);
+ }
+ return false;
+ },
+
+ knownFrames: {
+ _history: {},
+ add: function(url, parentSite) {
+ var f = this._history[url] || (this._history[url] = []);
+ if (f.indexOf(parentSite) > -1) return;
+ f.push(parentSite);
+ },
+ isKnown: function(url, parentSite) {
+ var f = this._history[url];
+ return f && f.indexOf(parentSite) > -1;
+ },
+ reset: function() {
+ this._history = {};
+ }
+ },
+
+ frameContentLoaded: function(w) {
+ if (this.emulateFrameBreak && this.doEmulateFrameBreak(w)) return; // we're no more framed
+ },
+
+ metaRefreshWhitelist: {},
+ processMetaRefresh(document, notifyCallback) {
+ let win = document.defaultView;
+ var docShell = DOM.getDocShellForWindow(win);
+ if (!this.forbidMetaRefresh ||
+ this.metaRefreshWhitelist[document.documentURI] ||
+ this.isJSEnabled(this.getSite(document.documentURI), win) ||
+ !document.getElementsByTagName("noscript")[0]
+ ) {
+ if (!docShell.allowMetaRedirects) this.disableMetaRefresh(docShell); // refresh blocker courtesy
+ return;
+ }
+ try {
+ let rr = document.getElementsByTagName("meta");
+ if (!rr[0]) return;
+ const refreshRx = /refresh/i;
+ for (let refresh of rr) {
+ if (!refreshRx.test(refresh.httpEquiv)) continue;
+ let node = refresh;
+ while (node = node.parentNode) {
+ if (node.localName == "noscript")
+ break;
+ }
+ if (!node) continue;
+ let content = refresh.content.split(/[,;]/, 2);
+ let uri = content[1];
+ if (uri && !new AddressMatcher(this.getPref("forbidMetaRefresh.exceptions")).test(document.documentURI)) {
+ if (notifyCallback && !(document.documentURI in this.metaRefreshWhitelist)) {
+ let timeout = parseInt(content[0]) || 0;
+ uri = uri.replace (/^\s*URL\s*=\s*/i, "");
+ var isQuoted = /^['"]/.test(uri);
+ uri = isQuoted ? uri.match(/['"]([^'"]*)/)[1] : uri.replace(/\s[\s\S]*/, '');
+ try {
+ notifyCallback({
+ baseURI: docShell.currentURI,
+ uri: uri,
+ timeout: timeout
+ });
+ } catch(e) {
+ dump("[NoScript]: " + e + " notifying meta refresh at " + document.documentURI + "\n");
+ }
+ }
+ document.defaultView.addEventListener("pagehide", function(ev) {
+ ev.currentTarget.removeEventListener(ev.type, arguments.callee, false);
+ docShell.allowMetaRedirects = true;
+ document = docShell = null;
+ }, false);
+ this.disableMetaRefresh(docShell);
+ return;
+ }
+ }
+ } catch(e) {
+ dump("[NoScript]: " + e + " processing meta refresh at " + document.documentURI + "\n");
+ }
+ },
+ doFollowMetaRefresh: function(metaRefreshInfo, forceRemember) {
+ var document = metaRefreshInfo.document;
+ if (forceRemember || this.getPref("forbidMetaRefresh.remember", false)) {
+ this.metaRefreshWhitelist[document.documentURI] = metaRefreshInfo.uri;
+ }
+ var docShell = metaRefreshInfo.docShell || DOM.getDocShellForWindow(document.defaultView);
+ this.enableMetaRefresh(docShell);
+ if (docShell instanceof Ci.nsIRefreshURI) {
+ this.setupRefresh(docShell,
+ metaRefreshInfo.baseURI || IOS.newURI(document.documentURI, null, null),
+ "0;" + metaRefreshInfo.uri);
+ }
+ },
+ doBlockMetaRefresh: function(metaRefreshInfo) {
+ if (this.getPref("forbidMetaRefresh.remember", true)) {
+ var document = metaRefreshInfo.document;
+ this.metaRefreshWhitelist[document.documentURI] = null;
+ }
+ },
+
+ enableMetaRefresh: function(docShell) {
+ if (docShell) {
+ docShell.allowMetaRedirects = true;
+ docShell.resumeRefreshURIs();
+ // if(this.consoleDump) dump("Enabled META refresh on " + (docShell.currentURI && docShell.currentURI.spec) + "\n");
+ }
+ },
+ disableMetaRefresh: function(docShell) {
+ if (docShell) {
+ docShell.suspendRefreshURIs();
+ docShell.allowMetaRedirects = false;
+ if (docShell instanceof Ci.nsIRefreshURI) {
+ docShell.cancelRefreshURITimers();
+ }
+ // if(this.consoleDump) dump("Disabled META refresh on " + (docShell.currentURI && docShell.currentURI.spec) + "\n");
+ }
+ },
+
+ setupRefresh: function(docShell, baseURI, header) {
+ if (docShell instanceof Ci.nsIRefreshURI)
+ try {
+ // Gecko <= 16
+ docShell.setupRefreshURIFromHeader(baseURI, header);
+ } catch (e) {
+ docShell.setupRefreshURIFromHeader(baseURI, docShell.document.nodePrincipal, header);
+ }
+ },
+
+ detectJSRedirects: function(document) {
+ if (this.jsredirectIgnore) return 0;
+
+ try {
+ if (document.documentURI.indexOf("http") !== 0) return 0;
+
+ let window = document.defaultView;
+ if (!window) return 0;
+
+ let hasVisibleLinks = this.hasVisibleLinks(document);
+ if (!this.jsredirectForceShow && hasVisibleLinks)
+ return 0;
+
+ let body = document.body;
+ if (!body) return 0;
+
+ let seen = [];
+ let cstyle = document.defaultView.getComputedStyle(body, "");
+ if (cstyle) {
+ if (cstyle.visibility != "visible") {
+ body.style.visibility = "visible";
+ }
+ if (cstyle.display == "none") {
+ body.style.display = "block";
+ }
+ }
+ if (!hasVisibleLinks && (document.links[0] || document.forms[0])) {
+ let links = document.links;
+ for (let j = 0, len = links.length; j < len; j++) {
+ let l = links[j];
+ if (!(l.href && l.href.indexOf("http") === 0)) continue;
+ l = body.appendChild(l.cloneNode(true));
+ l.style.visibility = "visible";
+ l.style.display = "block";
+ seen.push(l.href);
+ }
+
+
+ for (let forms = document.forms, j = 0, f; f = forms[j]; j++) {
+ if (f.action) {
+ let e;
+ for (let els = f.elements, k = 0; e = els[k]; k++) {
+ if (e.type === "submit") break;
+ }
+ if (!e) {
+ e = document.createElement("input");
+ e.type = "submit";
+ e.value = f.action.substring(0, 47);
+ if (f.action.length > 48) e.value += "...";
+ f.appendChild(e);
+ }
+ }
+ }
+ }
+
+ var code;
+ var container = null;
+
+ code = body && body.getAttribute("onload");
+ const sources = code ? [code] : [];
+ var scripts = document.getElementsByTagName("script");
+ for (let j = 0, len = scripts.length; j < len; j++)
+ sources.push(scripts[j].textContent);
+
+ scripts = null;
+
+ if (sources.length === 0) return 0;
+
+ var follow = false;
+ const findURL = /(?:(?:\b(?:open|replace)\s*\(|(?:\b(?:href|location|src|path|pathname|search)|(?:[Pp]ath|UR[IL]|[uU]r[il]))\s*=)\s*['"]|['"](?=https?:\/\/\w|\w*[\.\/\?]))([\?\/\.\w\-%\&][^\s'"]*)/g;
+ const MAX_TIME = 1000;
+ const MAX_LINKS = 30;
+ const ts = Date.now();
+ outerLoop:
+ for (let j = 0, len = sources.length; j < len; j++) {
+ findURL.lastIndex = 0;
+ code = sources[j];
+ for (let m; m = findURL.exec(code);) {
+
+ if (!container) {
+ container = document.createElementNS(HTML_NS, "div");
+ with (container.style) {
+ backgroundImage = 'url("' + this.pluginPlaceholder + '")';
+ backgroundRepeat = "no-repeat";
+ backgroundPosition = "2px 2px";
+ padding = "4px 4px 4px 40px";
+ display = "block";
+ minHeight = "32px";
+ textAlign = "left";
+ }
+ follow = this.jsredirectFollow && window == window.top &&
+ !window.frames[0] &&
+ !document.evaluate('//body[normalize-space()!=""]', document, null,
+ Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
+ document.body.appendChild(container);
+ }
+ let url = m[1];
+ if (url.indexOf("\\") !== -1 &&
+ url.indexOf('"') === -1 // notice that m[1] is guaranteed not to contain quotes nor whitespace, but we double check anyway :)
+ ) {
+ // resolve JS escapes, see http://forums.informaction.com/viewtopic.php?f=10&t=8792
+ let sandbox = new Cu.Sandbox("about:blank");
+ try {
+ url = Cu.evalInSandbox('"' + url + '"', sandbox); // this is safe, since we've got no quotes...
+ } catch(e) {
+ // ...but a trailing backslash could cause a (harmless) syntax error anyway
+ } finally {
+ Cu.nukeSandbox(sandbox);
+ }
+ }
+ let a = document.createElementNS(HTML_NS, "a");
+ a.href = url;
+ container.appendChild(a);
+ if (a.href.toLowerCase().indexOf("http") != 0 || seen.indexOf(a.href) > -1) {
+ container.removeChild(a);
+ continue;
+ }
+ seen.push(a.href);
+ a.appendChild(document.createTextNode(a.href));
+ container.appendChild(document.createElementNS(HTML_NS, "br"));
+
+ if (seen.length >= MAX_LINKS || Date.now() - ts > MAX_TIME) break outerLoop;
+ }
+
+ if (follow && seen.length == 1) {
+ this.log("[NoScript Following JS Redirection]: " + seen[0] + " FROM " + document.location.href);
+
+ this.doFollowMetaRefresh({
+ uri: seen[0],
+ document: document
+ });
+ }
+
+ if (Date.now() - ts > MAX_TIME) break;
+ }
+ return seen.length;
+ } catch(e) {
+ this.dump(e.message + " while processing JS redirects");
+ return 0;
+ }
+ },
+
+ cpConsoleFilter: [2, 5, 6, 7, 15],
+ cpDump: function(msg, aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aInternalCall, aPrincipal) {
+ this.dump("Content " + msg + " -- type: " + aContentType + ", location: " + (aContentLocation && aContentLocation.spec) +
+ ", requestOrigin: " + (aRequestOrigin && aRequestOrigin.spec) + ", ctx: " +
+ (aContext !== null && aContext.tagName ? "<HTML " + aContext.tagName + ">" // try not to cause side effects of toString() during load
+ : aContext) +
+ ", mime: " + aMimeTypeGuess + ", Internal: " + aInternalCall +
+ ", principal.origin: " + (aPrincipal && aPrincipal.origin));
+ },
+ reject: function(what, args /* [aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aInternalCall, [aPrincipal] ] */) {
+
+ if (this.consoleDump) {
+ if(this.consoleDump & LOG_CONTENT_BLOCK && args.length >= 6) {
+ this.cpDump("BLOCKED " + what, args[0], args[1], args[2], args[3], args[4], args[5], args[6] && args[6]);
+ }
+ if(this.consoleDump & LOG_CONTENT_CALL) {
+ this.dump(new Error().stack);
+ }
+ }
+ switch(args[0]) {
+ case 9:
+ // our take on https://bugzilla.mozilla.org/show_bug.cgi?id=387971
+ args[1].spec = this.nopXBL;
+ return CP_OK;
+ case 5:
+ if (args[3]) args[3].__noscriptBlocked = true;
+ }
+
+ PolicyState.cancel(args);
+
+
+ if (args[1]) {
+ let win = DOM.findWindow(args[3]);
+ this.recordBlocked(this.getSite(args[1].spec) || "", this.getSite(win && win.location.href || args[2] && args[2].spec));
+ }
+
+ return CP_REJECT;
+ },
+
+ nopXBL: "chrome://global/content/bindings/general.xml#basecontrol",
+
+ forbiddenXMLRequest: function(aRequestOrigin, aContentLocation, aContext, forbidDelegate) {
+ let originURL, locationURL;
+ if (aContentLocation.schemeIs("chrome") || aContentLocation.schemeIs("moz-extension") || !aRequestOrigin ||
+ // GreaseMonkey Ajax comes from resource: hidden window
+ // Google Toolbar Ajax from about:blank
+ aRequestOrigin.schemeIs("chrome") || aRequestOrigin.schemeIs("resource") ||
+ aRequestOrigin.schemeIs("about") || aRequestOrigin.schemeIs("moz-extension") ||
+ // Web Developer extension "appears" to XHR towards about:blank
+ (locationURL = aContentLocation.spec) == "about:blank"
+ ) return false;
+
+ let locationSite = this.getSite(locationURL);
+ if (!this.isJSEnabled(locationSite) && this.checkShorthands(locationSite))
+ this.autoTemp(locationSite);
+
+ var win = aContext && aContext.defaultView;
+ if(win) {
+ this.cacheCodeSite(win, locationSite);
+ }
+ return forbidDelegate.call(this, originURL, locationURL, win);
+ },
+
+ cacheCodeSite(win, site) {
+ win = win.top;
+ let cache = this.getExpando(win, "codeSites");
+ if (!cache) {
+ cache = this.setExpando(win, "codeSites", new Set());
+ }
+ cache.add(site);
+ },
+
+
+ addFlashVars: function(url, embed) {
+ // add flashvars to have a better URL ID
+ if (embed instanceof Ci.nsIDOMElement) try {
+ var flashvars = embed.getAttribute("flashvars");
+ if (!flashvars) {
+ let params = embed.getElementsByTagName("param");
+ for (let j = 0, p; (p = params[j]); j++)
+ if (p.name && p.name.toLowerCase() === "flashvars")
+ flashvars = p.value;
+ }
+ if (flashvars) {
+ let yahooRx = /\bYUIBridgeCallback=[^&]+/;
+ if (yahooRx.test(flashvars)) {
+ let d = embed.ownerDocument;
+ let m = d && d.URL.match(/(\d+)\.html\b/);
+ flashvars = flashvars.replace(yahooRx, m ? "_YUIvid_=" + m[1] : "");
+ }
+ let videoId = flashvars.match(/video_?id=[^&]+/);
+ url += "#!flashvars#" + encodeURI(videoId && videoId[0] || flashvars);
+ }
+ } catch(e) {
+ if (this.consoleDump) this.dump("Couldn't add flashvars to " + url + ":" + e);
+ }
+ return url;
+ },
+
+ addObjectParams: function(url, embed) {
+ if (embed instanceof Ci.nsIDOMElement) try {
+ var params = embed.getElementsByTagName("param");
+ if (!params.length) return url;
+
+ var pp = [];
+ for(let j = params.length; j-- > 0;) {
+ pp.push(encodeURIComponent(params[j].name) + "=" + encodeURIComponent(params[j].value));
+ }
+ url += "#!objparams#" + pp.join("&");
+ } catch (e) {
+ if (this.consoleDump) this.dump("Couldn't add object params to " + url + ":" + e);
+ }
+ return url;
+ },
+
+ tagWindowlessObject: function(o) {
+ const rx = /^(?:opaque|transparent)$/i;
+ var b;
+ try {
+ let tag = o.tagName && o.tagName.toLowerCase();
+ if (tag === "embed") {
+ b = rx.test(o.getAttribute("wmode"));
+ } else if (tag === "object") {
+ var params = o.getElementsByTagName("param");
+ const wmodeRx = /^wmode$/i;
+ for(var j = params.length; j-- > 0 &&
+ !(b = wmodeRx.test(params[j].name && rx.test(params[j].value)));
+ );
+ }
+ if (b) this.setExpando(o, "windowless", true);
+ } catch (e) {
+ if (this.consoleDump) this.dump("Couldn't tag object for window mode.");
+ }
+ },
+
+ isWindowlessObject: function(o) {
+ return this.getExpando(o, "windowless") || o.settings && o.settings.windowless;
+ },
+
+ resolveSilverlightURL: function(uri, embed) {
+ if(!uri) return "";
+
+
+ if (embed instanceof Ci.nsIDOMElement) try {
+
+ var url = "";
+ var params = embed.getElementsByTagName("param");
+ if (!params.length) return uri.spec;
+
+ var name, value, pp = [];
+ for (var j = params.length; j-- > 0;) { // iteration inverse order is important for "source"!
+ name = params[j].name;
+ value = params[j].value;
+ if(!(name && value)) continue;
+
+ if (!url && name.toLowerCase() == "source") {
+ try {
+ url = uri.resolve(value);
+ continue;
+ } catch(e) {
+ if (this.consoleDump)
+ this.dump("Couldn't resolve Silverlight URL " + uri.spec + " + " + value + ":" + e);
+ url = uri.spec;
+ }
+ }
+ pp.push(encodeURIComponent(name) + "=" + encodeURIComponent(value));
+ }
+ return (url || uri.spec) + "#!objparams#" + pp.join("&");
+ } catch(e1) {
+ if (this.consoleDump) this.dump("Couldn't resolve Silverlight URL " + uri.spec + ":" + e1);
+ }
+ return uri.spec;
+ },
+
+ tagForReplacement: function(embed, pluginExtras) {
+ try {
+ var doc = embed.ownerDocument;
+ if(!doc) {
+ if (embed instanceof Ci.nsIDOMDocument) {
+ pluginExtras.document = (doc = embed);
+ pluginExtras.url = this.getSite(pluginExtras.url);
+ this._collectPluginExtras(this.findPluginExtras(doc), pluginExtras);
+ }
+ } else {
+ var node = embed;
+ while((node = node.parentNode))
+ if (node.__noScriptBlocked)
+ return;
+ if (!pluginExtras.document) {
+ pluginExtras.document = doc;
+ }
+ var pe = this.getExpando(doc, "pe");
+ if (pe === null) this.setExpando(doc, "pe", pe = []);
+ pe.push({embed: embed, pluginExtras: pluginExtras});
+ }
+ try {
+ this.syncUI(doc);
+ } catch(noUIex) {
+ if(this.consoleDump) this.dump(noUIex);
+ }
+ } catch(ex) {
+ if(this.consoleDump) this.dump(
+ "Error tagging object [" + pluginExtras.mime + " from " + pluginExtras.url +
+ " - embed " + embed +
+ "] for replacement: " + ex);
+ }
+ },
+
+ blockLegacyFrame: function(frame, uri, sync) {
+
+ var verbose = this.consoleDump & LOG_CONTENT_BLOCK;
+ if(verbose) {
+ this.dump("Redirecting blocked legacy frame " + uri.spec + ", sync=" + sync);
+ }
+
+
+ var url = this.createPluginDocumentURL(uri.spec, "iframe");
+
+ if(sync) {
+ if (verbose) dump("Legacy frame SYNC, setting to " + url + "\n");
+ frame.contentWindow.location = url;
+ } else {
+ frame.ownerDocument.defaultView.addEventListener("load", function(ev) {
+ if(verbose) dump("Legacy frame ON PARENT LOAD, setting to " + url + "\n");
+ ev.currentTarget.removeEventListener("load", arguments.callee, false);
+ frame.contentWindow.location = url;
+ }, false);
+ }
+ return true;
+
+ },
+
+
+ isPluginDocumentURL: function(url, tag) {
+ try {
+ return url.replace(/(src%3D%22).*?%22/i, '$1%22') == this.createPluginDocumentURL('', tag)
+ } catch(e) {}
+ return false;
+ },
+
+ createPluginDocumentURL: function(url, tag) {
+ tag = tag ? tag.toLowerCase() : "embed";
+ return 'data:text/html;charset=utf-8,' +
+ encodeURIComponent('<html><head></head><body style="padding: 0px; margin: 0px"><' +
+ tag + ' src="' + url + '" width="100%" height="100%"></' +
+ tag + '></body></html>');
+ },
+
+ forbiddenIFrameContext: function(originURL, locationURL) {
+ if (this.isForbiddenByHttpsStatus(originURL)) return false;
+ var domain = this.getDomain(locationURL, true);
+ if (!domain) return false;
+ switch (this.forbidIFramesContext) {
+ case 0: // all IFRAMES
+ return true;
+ case 3: // different 2nd level domain or either untrusted parent or origin
+ if (!(this.untrustedSites.matches(this.getSite(locationURL)) ||
+ this.untrustedSites.matches(this.getSite(originURL))))
+ return this.getBaseDomain(this.getDomain(originURL, true)) !=
+ this.getBaseDomain(domain);
+ case 2: // different domain (unless forbidden by HTTPS status)
+ if (this.getDomain(originURL, true) != domain) return true;
+ // if we trust only HTTPS both sites must have the same scheme
+ if (!this.isForbiddenByHttpsStatus(locationURL.replace(/^https:/, 'http:'))) return false;
+ case 1: // different site
+ return this.getSite(originURL) != this.getSite(locationURL);
+ }
+ return false;
+ },
+
+ forbiddenXBLContext: function(originURL, locationURL, window) {
+ if (locationURL == this.nopXBL) return false; // always allow our nop binding
+
+ var locationSite = this.getSite(locationURL);
+ var originSite = this.getSite(originURL);
+
+ switch (this.forbidXBL) {
+ case 4: // allow only XBL from the same trusted site or chrome (default)
+ if (locationSite != originSite) return true; // chrome is checked by the caller checkXML
+ case 3: // allow only trusted XBL on trusted sites
+ if (!locationSite) return true;
+ case 2: // allow trusted and data: (Fx 3) XBL on trusted sites
+ if (!(this.isJSEnabled(originSite, window) ||
+ locationSite.indexOf("file:") === 0 // we trust local files to allow Linux theming
+ )) return true;
+ case 1: // allow trusted and data: (Fx 3) XBL on any site
+ if (!(this.isJSEnabled(locationSite, window) || /^(?:data|file|resource):/.test(locationURL))) return true;
+ case 0: // allow all XBL
+ return false;
+ }
+ return true;
+ },
+
+ forbiddenXHRContext: function(originURL, locationURL, window) {
+ if (!window) {
+ // live bookmarks
+ return false;
+ }
+
+ var locationSite = this.getSite(locationURL);
+ // var originSite = this.getSite(originURL);
+ switch (this.forbidXHR) {
+ case 3: // forbid all XHR
+ return true;
+ case 2: // allow same-site XHR only
+ if (locationSite && locationSite != originSite) return true;
+ case 1: // allow trusted XHR targets only
+ if (locationSite && locationSite !== "moz-nullprincipal:" && !this.isJSEnabled(locationSite, window))
+ return true;
+ case 0: // allow all XBL
+ return false;
+ }
+ return true;
+ },
+};
+
diff --git a/extensions/noscript/chrome/content/noscript/MainParent.js b/extensions/noscript/chrome/content/noscript/MainParent.js
new file mode 100644
index 0000000..65a6e70
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/MainParent.js
@@ -0,0 +1,611 @@
+Main.OBSERVED_TOPICS.push("http-on-opening-request", "http-on-modify-request");
+LAZY_INCLUDE("IO");
+
+var MainParent = {
+ beforeInit: function() {
+ this._initE10s();
+ },
+ afterInit: function() {
+
+ if ((this.locked = this.prefs.prefIsLocked("default"))) {
+ try {
+ const psKey = this.POLICY_NAME + ".sites";
+ const dc = this.defaultCaps;
+ dc.lockPref("policynames");
+ dc.unlockPref(psKey);
+ this.resetDefaultSitePrefs();
+ dc.setCharPref(psKey, this.policyPB.getCharPref("sites"));
+ dc.lockPref(psKey);
+ if (dc instanceof PBI) dc.addObserver("default.javascript.", this, true);
+ dc.setCharPref("default.javascript.enabled", "noAccess");
+ dc.lockPref("default.javascript.enabled");
+ this.prefs.lockPref("global");
+ } catch(e) {
+ this.dump(e);
+ }
+ }
+
+ Thread.delay(this.checkSubscriptions, 10000, this);
+
+ this._updateSync();
+
+ try {
+ let dp = this.prefService.getDefaultBranch("noscript.");
+ let snapshot = dp.getCharPref("snapshot");
+ this._afterInitSnapshot = snapshot;
+ this.setSnapshot(JSON.parse(snapshot));
+ this._afterInitTemp = this.tempSites.sitesString;
+ this._afterInitTrusted = this.jsPolicySites.sitesString;
+ dp.setCharPref("snapshot", "");
+ } catch (e) {
+ this._afterInitSnapshot = e;
+ }
+
+ this.reloadWhereNeeded(this.RELOAD_NO); // init snapshots
+
+
+
+ if (this.getPref("webext.enabled")) {
+ INCLUDE("WebExt");
+ this.webExt = WebExt;
+ }
+ this._afterInited = true;
+ },
+
+ _initE10s: function() {
+ INCLUDE("e10sParent");
+ this.onDisposal(() => { if (IPC.parent) IPC.parent.dispose(); });
+ },
+
+ "http-on-modify-request": {
+ observe: function(channel, topic, data) {
+ try {
+ if (channel instanceof Ci.nsIHttpChannel) {
+
+ if (channel.status) {
+ if (ns.consoleDump)
+ ns.dump("Unexpected! HTTP observer called on aborted channel " +
+ channel.name + " (0x" + channel.status.toString(16) + ") - " +
+ new Error().stack);
+ return;
+ }
+
+ let ncb = channel.notificationCallbacks;
+ let loadFlags = channel.loadFlags;
+ if (!(loadFlags || ncb || channel.owner)) {
+ try {
+ if (channel.getRequestHeader("Content-type") == "application/ocsp-request") {
+ if (ns.consoleDump) ns.dump("Skipping cross-site checks for OCSP request " + channel.name);
+ return;
+ }
+ } catch(e) {}
+ }
+
+ if (ncb) {
+ const IBCL = Ci.nsIBadCertListener2;
+ let bgReq = ncb instanceof Ci.nsIXMLHttpRequest || ncb instanceof IBCL
+ || ("responseXML" in ncb); // for some reason, since Gecko 15 (new XMLHttpRequest() instanceof Ci.nsIXMLHttpRequest) === false
+ if (!bgReq) try { bgReq = ncb.getInterface(IBCL); } catch (e) {}
+ if (bgReq && !ns.isCheckedChannel(channel)) {
+ if (ns.consoleDump) {
+ ns.dump("Skipping cross-site checks for chrome background request " + channel.name + ", " + loadFlags + ", " + channel.owner);
+ }
+ return;
+ }
+ }
+
+ let abeReq = ns.requestWatchdog.onHttpStart(channel);
+ }
+
+ } catch (e) {
+ ns.dump(e + "\n" + e.stack);
+ }
+ }
+ },
+
+ onVersionChanged: function(prev) {
+ let removalsOnly = !this.getPref("allowWhitelistUpdates");
+
+ // update hacks
+ var versions = {
+ "2.1.1.2rc6": {
+ "hotmail.com": "wlxrs.com", // required by Hotmail/Live webmail
+ "google.com": "googleapis.com gstatic.com", // required by most Google services and also by external resources
+ "addons.mozilla.org": "paypal.com paypalobjects.com" // required for the "Contribute" AMO feature not to break badly with no warning
+ },
+
+ "2.2.9rc2": {
+ "addons.mozilla.org": "persona.org"
+ },
+
+ "2.4.9rc2": {
+ "!browserid.org": "persona.org"
+ },
+ "2.5.9rc3": {
+ "live.com": "gfx.ms afx.ms" // fully Microsoft-controlled (no user content), now required by MS mail services
+ },
+ "2.6.5.9rc2": {
+ "live.com": "sfx.ms" // fully Microsoft-controlled (no user content), now required by MS mail services
+ },
+ "2.6.6rc5": {
+ "live.com": "outlook.com live.net" // fully Microsoft-controlled (no user content), now required by MS mail services
+ },
+ "2.6.9.4rc1": {
+ "vimeo.com": "vimeocdn.com" // no movie will play anymore without this
+ },
+ "2.6.9.19rc1": {
+ "youtube.com": "googlevideo.com" // Youtube's HTML5 video player now requires this
+ },
+ "2.6.9.22rc1": {
+ "prototypejs.org": "bootstrapcdn.com" // Used by many sites, mostly for styles and fonts
+ },
+ "2.6.9.27": {
+ "!vjs.zendcdn.net": "" // removal
+ },
+ "2.6.9.28rc2": {
+ "!googleapis.com": "ajax.googleapis.com" // storage.googleapis.com allows HTML files!
+ },
+ "2.6.9.30rc1": {
+ "!mootools.net": ""
+ },
+ "2.6.9.30rc2": {
+ "!cdnjs.cloudflare.com": "",
+ "!prototypejs.org": "",
+ "ajax.googleapis.com": "maps.googleapis.com"
+ },
+ "2.6.9.30rc4": {
+ "about:blank": "about:pocket-signup about:pocket-save"
+ },
+ "2.6.9.30rc5": {
+ "!about:packet-save": "about:pocket-saved",
+ "!about:pocket-signup": "about:pocket-signup",
+ "google.com": "ajax.googleapis.com maps.googleapis.com"
+ },
+ "2.6.9.35rc1": {
+ "!about:pocket-save": "about:pocket-saved",
+ "!about:pocket-signup": "about:pocket-signup",
+ "google.com": "ajax.googleapis.com maps.googleapis.com"
+ },
+ "2.6.9.36rc1": {
+ "netflix.com": "https://*.nflxvideo.net"
+ },
+ "5.0.10rc3": {
+ "!persona.org": ""
+ },
+ };
+
+ for (let v in versions) {
+ if (this.versionComparator.compare(prev, v) < 0) {
+ let cascading = versions[v];
+ for (let site in cascading) {
+ let newSites = !removalsOnly && cascading[site].split(/\s+/).filter(function(s) {
+ // check whether browser internal URIs are supported
+ if (/^(?:about|chrome|resource):\w/.test(s))
+ try {
+ IOUtil.newChannel(s, null, null);
+ } catch(e) {
+ return false;
+ }
+ return true;
+ });
+ let replace = site[0] === "!";
+ if (replace) site = site.substring(1);
+ if (this.isJSEnabled(site)) {
+ if (replace) this.jsPolicySites.remove(site, true, false);
+ if (!removalsOnly && newSites[0]) {
+ this.jsPolicySites.remove(newSites, true, false);
+ this.setJSEnabled(newSites, true);
+ }
+ }
+ }
+ }
+ }
+ },
+
+ firstRun: false,
+ versionChecked: false,
+ checkVersion: function(browserStartup = false) {
+ if (this.versionChecked) return;
+ this.versionChecked = browserStartup;
+
+ if (!this.getPref("visibleUIChecked", false) && this.ensureUIVisibility())
+ this.setPref("visibleUIChecked", true);
+
+ let ver = this.VERSION;
+ let prevVer = this.getPref("version", "");
+ this.firstRun = prevVer !== ver;
+ if (!this.firstRun) {
+ prevVer = this.getPref("firstRunRedirection.pending", ver);
+ }
+ ns.dump(`Checking version - browserStartup=${browserStartup}, ${prevVer} -> ${ver}`);
+ if (this.firstRun || prevVer !== ver) {
+ if (this.firstRun && prevVer) try {
+ this.onVersionChanged(prevVer);
+ } catch (ex) {
+ Cu.reportError(ex);
+ }
+ this.setPref("version", ver);
+ this.setPref("firstRunRedirection.pending", ver);
+ const betaRx = /(?:a|alpha|b|beta|pre|rc)\d*$/; // see http://viewvc.svn.mozilla.org/vc/addons/trunk/site/app/config/constants.php?view=markup#l431
+ if (prevVer.replace(betaRx, "") != ver.replace(betaRx, "")) {
+ if (!browserStartup) {
+ this.setPref("firstRunRedirection.pending", prevVer);
+ } else if (this.getPref("firstRunRedirection", true)) {
+ const name = "noscript";
+ const domain = name.toLowerCase() + ".net";
+
+ IOUtil.newChannel("https://" + domain + "/-", null, null).asyncOpen({ // DNS prefetch
+ onStartRequest: function() {},
+ onStopRequest: function(req, ctx) {
+ if (req.status && req.status !== NS_BINDING_REDIRECTED) {
+ ns.setPref("version", '');
+ ns.savePrefs();
+ return;
+ }
+
+ var browser = DOM.mostRecentBrowserWindow.getBrowser();
+ if (typeof(browser.addTab) != "function") return;
+
+
+ var url = "https://" + domain + "/?ver=" + ver;
+ var hh = "X-IA-Post-Install: " + name + " " + ver;
+ if (prevVer) {
+ url += "&prev=" + prevVer;
+ hh += "; updatedFrom=" + prevVer;
+ }
+ hh += "\r\n";
+
+ var hs = Cc["@mozilla.org/io/string-input-stream;1"] .createInstance(Ci.nsIStringInputStream);
+ hs.setData(hh, hh.length);
+ hs.seek(0, 0);
+
+ var b = (browser.selectedTab = browser.addTab()).linkedBrowser;
+ b.stop();
+ b.webNavigation.loadURI(url, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, hs);
+
+ },
+ onDataAvailable: function() {}
+ }, {});
+ }
+ }
+ this.savePrefs();
+ }
+ },
+
+ ensureUIVisibility: function() {
+
+ try {
+ let window = DOM.mostRecentBrowserWindow;
+ let document = window.document;
+ const tbbId = "noscript-tbb";
+ let tbb = document.getElementById(tbbId);
+ if (tbb) return false;
+
+ try {
+ let cui = window.CustomizableUI;
+ let widget = cui.getWidget(tbbId);
+ if (!(widget && widget.areaType)) {
+ cui.addWidgetToArea(tbbId, cui.AREA_NAVBAR);
+ }
+ } catch (e) { // super-legacy
+ let addonBar = document.getElementById("addon-bar");
+ if (!addonBar) return false;
+
+ let navBar = document.getElementById("nav-bar");
+
+ let [bar, refId] =
+ addonBar.collapsed && navBar && !navBar.collapsed || !this.getPref("statusIcon", true)
+ ? [navBar, "urlbar-container"]
+ : [addonBar, "status-bar"];
+
+ let set = bar.currentSet.split(/\s*,\s*/);
+ if (set.indexOf(tbbId) > -1) return false;
+
+ set.splice(set.indexOf(refId), 0, tbbId);
+
+ bar.setAttribute("currentset", bar.currentSet = set.join(","));
+ document.persist(bar.id, "currentset");
+ try {
+ window.BrowserToolboxCustomizeDone(true);
+ } catch (e) {}
+ }
+
+ try {
+ window.noscriptOverlay.initPopups();
+ } catch(e) {}
+ return true;
+ } catch(e) {
+ this.dump(e);
+ return false;
+ }
+ },
+
+ checkSubscriptions: function() {
+ var lastCheck = this.getPref("subscription.last_check");
+ var checkInterval = this.getPref("subscription.checkInterval", 24) * 60000;
+ var now = Date.now();
+ if (lastCheck + checkInterval > now) {
+ this.delayExec(this.checkSubscriptions, lastCheck + checkInterval - now + 1000);
+ return;
+ }
+
+ function load(list, process, goOn) {
+ var url = ns.getPref("subscription." + list + "URL");
+ if (!url) {
+ goOn();
+ return;
+ }
+ var xhr = ns.createCheckedXHR("GET", url, function() {
+ if (xhr.readyState === 4) {
+ if (xhr.status === 0 || xhr.status === 200) {
+ var lists = xhr.responseText.split("[UNTRUSTED]");
+ try {
+ process(lists[0], lists[1]);
+ ns.dump(list + " list at " + url + " loaded.");
+ } catch(e) {
+ ns.dump(e);
+ }
+ }
+ goOn();
+ }
+ });
+ xhr.send(null);
+ }
+
+ load("untrusted",
+ function(trusted, untrusted) {
+ ns.untrustedSites.sitesString += " " + untrusted;
+ ns.persistUntrusted();
+ },
+ function() {
+ load("trusted", function(trusted, untrusted) {
+ var trustedSites = new PolicySites(trusted);
+ trustedSites.remove(ns.untrustedSites.sitesList, true, false);
+ ns.flushCAPS(ns.jsPolicySites.sitesString + " " + trustedSites.sitesString);
+ }, function() {
+ ns.setPref("subscription.lastCheck", Date.now());
+ ns.savePrefs(true);
+ ns.delayExec(ns.checkSubscriptions, checkInterval);
+ });
+ }
+ );
+ },
+
+ get builtInSync() {
+ var ret = false;
+ try {
+ ret = this.prefService.getDefaultBranch("services.sync.prefs.sync.javascript.").getBoolPref("enabled");
+ } catch (e) {}
+ delete this.builtInSync;
+ return (this.builtInSync = ret);
+ },
+
+ _updateSync: function() {
+ let t = Date.now();
+ this._clearSync();
+ if (this.builtInSync && this.getPref("sync.enabled")) this._initSync();
+ if (this.consoleDump) this.dump("Sync prefs inited in " + (Date.now() - t));
+ },
+ _initSync: function() {
+
+ try {
+ let branch = this.prefService.getDefaultBranch("services.sync.prefs.sync.noscript.");
+ for (let key of this.prefs.getChildList("", {})) {
+ switch (key) {
+ case "version":
+ case "preset":
+ case "placesPrefs.ts":
+ case "mandatory":
+ case "default":
+ case "ABE.wanIpAsLocal":
+ case "ABE.migration":
+ case "sync.enabled":
+ break;
+ default:
+ branch.setBoolPref(key, true);
+ }
+ }
+ this.prefService.getDefaultBranch("services.sync.prefs.sync.")
+ .setBoolPref(this.policyPB.root + "sites", true);
+ } catch(e) {
+ this.dump(e);
+ }
+
+ },
+ _clearSync: function() {
+ try {
+ this.prefService.getBranch("services.sync.prefs.sync.noscript.").deleteBranch("");
+ } catch(e) {
+ this.dump(e);
+ }
+ try{
+ this.prefService.getBranch("services.sync.prefs.sync." + this.policyPB.root).deleteBranch("");
+ } catch(e) {
+ this.dump(e);
+ }
+ },
+
+ _dontSerialize: ["version", "temp", "preset", "placesPrefs.ts", "mandatory", "default"],
+
+ conf2JSON(excludeDefault = false) {
+ const excluded = this._dontSerialize;
+ const prefs = {};
+ for (let key of this.prefs.getChildList("", {})) {
+ if (!(excluded.includes(key) || excludeDefault && !this.prefs.prefHasUserValue(key))) {
+ prefs[key] = this.getPref(key);
+ }
+ }
+ return {
+ prefs: prefs,
+ whitelist: this.getPermanentSites().sitesString,
+ V: this.VERSION
+ };
+ },
+
+ serializeConf: function(beauty) {
+ const conf = JSON.stringify(this.conf2JSON());
+ return beauty ? conf.replace(/([^\\]"[^"]*[,\{])"/g, "$1\r\n\"").replace(/},?(?:\n|$)/g, "\r\n$&") : conf;
+ },
+
+ restoreConf: function(s) {
+ try {
+ const json = JSON.parse(s.replace(/[\n\r]/g, ''));
+ if (json.ABE) ABE.restoreJSONRules(json.ABE);
+
+ const prefs = json.prefs;
+ const exclude = this._dontSerialize;
+ for (let key in prefs) {
+ if (exclude.indexOf(key) === -1) {
+ this.setPref(key, prefs[key]);
+ }
+ }
+
+ if (prefs.global != ns.jsEnabled) ns.jsEnabled = prefs.global;
+
+ this.flushCAPS(json.whitelist);
+ this.setPref("temp", "");
+ this.setPref("gtemp", "");
+
+ return true;
+ } catch(e) {
+ this.dump("Cannot restore configuration: " + e);
+ return false;
+ }
+ },
+
+ applyPreset: function(preset) {
+
+ this.resetDefaultPrefs(this.prefs, ['version', 'temp', 'untrusted', 'preset']);
+
+ switch(preset) {
+ case "off":
+ this.setPref("ABE.enabled", false);
+ this.setPref("filterXGet", false);
+ this.setPref("filterXPost", false);
+ this.setPref("clearClick", 0);
+ case "low":
+ this.jsEnabled = true;
+ break;
+ case "high":
+ this.setPref("contentBlocker", true);
+ case "medium":
+ this.jsEnabled = false;
+ break;
+ default:
+ return;
+ }
+
+ this.setPref("preset", preset);
+ this.savePrefs();
+ },
+
+ _sound: null,
+ playSound: function(url, force) {
+ if (force || this.getPref("sound", false)) {
+ var sound = this._sound;
+ if (sound === null) {
+ sound = Cc["@mozilla.org/sound;1"].createInstance(Ci.nsISound);
+ sound.init();
+ this._sound = sound;
+ }
+ try {
+ sound.play(IOS.newURI(url, null, null));
+ } catch(ex) {
+ //dump(ex);
+ }
+ }
+ },
+
+ _soundNotified: {},
+ soundNotify: function(url) {
+ if (this.getPref("sound.oncePerSite", true)) {
+ const site = this.getSite(url);
+ if (this._soundNotified[site]) return;
+ this._soundNotified[site] = true;
+ }
+ this.playSound(this.getPref("sound.block"));
+ },
+
+ readFile: function(file) {
+ return IO.readFile(file);
+ },
+ writeFile: function(file, content) {
+ IO.writeFile(file, content);
+ },
+
+ cleanupBrowser: function(browser) {
+ delete browser.__noscriptStorage;
+ },
+
+ _snapshot: {
+ lastTrusted: "",
+ lastUntrusted: "",
+ lastGlobal: false,
+ lastObjects: "{}",
+ },
+
+ updateSnapshot() {
+ const trusted = this.jsPolicySites.sitesString;
+ const untrusted = this.untrustedSites.sitesString;
+ const global = this.jsEnabled;
+ const objects = JSON.stringify(this.objectWhitelist);
+ let snapshot = this._snapshot;
+ this._snapshot = {
+ lastGlobal: global,
+ lastTrusted: trusted,
+ lastUntrusted: untrusted,
+ lastObjects: objects,
+ };
+
+ snapshot.changed = !(!snapshot.lastTrusted ||
+ global === snapshot.lastGlobal &&
+ snapshot.lastObjects === objects &&
+ trusted === snapshot.lastTrusted &&
+ untrusted === snapshot.lastUntrusted
+ );
+
+ return snapshot;
+ },
+
+ reloadAllowedObjects: function(browser, mime) {
+ browser.messageManager.sendAsyncMessage("NoScript:reloadAllowedObjects", {mime});
+ },
+
+ reloadWhereNeeded: function(reloadPolicy = this.RELOAD_ALL, snapshot = this.updateSnapshot()) {
+ if (!snapshot.changed) {
+ return;
+ }
+
+ const currentTabOnly = !this.getPref("autoReload.allTabs") ||
+ this.jsEnabled != snapshot.lastGlobal && !this.getPref("autoReload.allTabsOnGlobal");
+ if (currentTabOnly && reloadPolicy === this.RELOAD_ALL) {
+ reloadPolicy = this.RELOAD_CURRENT;
+ }
+ let payload = {
+ snapshots: {
+ previous: snapshot,
+ current: this._snapshot,
+ timestamp: Date.now(),
+ },
+ reloadPolicy,
+ mustReload: !(
+ reloadPolicy === this.RELOAD_NO ||
+ !this.getPref("autoReload") ||
+ snapshot.lastGlobal !== this._snapshot.lastGlobal && !this.getPref("autoReload.global")
+ ),
+ };
+ try {
+ let browser = DOM.mostRecentBrowserWindow.noscriptOverlay.currentBrowser;
+ payload.innerWindowID = browser.innerWindowID;
+ } catch (e) {}
+
+ Services.mm.broadcastAsyncMessage("NoScript:reload", payload);
+
+ },
+
+ purgeRecent() {
+ this.recentlyBlocked = [];
+ Services.mm.broadcastAsyncMessage("NoScript:purgeRecent", null);
+ },
+};
+
diff --git a/extensions/noscript/chrome/content/noscript/Membrane.js b/extensions/noscript/chrome/content/noscript/Membrane.js
new file mode 100644
index 0000000..6dbafdb
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Membrane.js
@@ -0,0 +1,20 @@
+var Membrane = {
+ create(real, wrap) {
+ let shadow = {};
+ return new Proxy(shadow, {
+ get: function(target, propKey, receiver) {
+ var pd = Object.getOwnPropertyDescriptor(real, propKey);
+ if (pd !== undefined && !pd.configurable && !pd.writable) {
+ Object.defineProperty(target, propKey, {
+ value: wrap(real, propKey, receiver),
+ writable: false,
+ configurable: false,
+ enumerable: pd.enumerable
+ });
+ return target[propKey];
+ }
+ return wrap(real, propKey, receiver);
+ }
+ });
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/MimeService.js b/extensions/noscript/chrome/content/noscript/MimeService.js
new file mode 100644
index 0000000..dc9d8eb
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/MimeService.js
@@ -0,0 +1,18 @@
+var MimeService = {
+ _cache: new Map(),
+ getTypeFromExtension(ext) {
+ if (ext) {
+ if (typeof ext !== "string") {
+ Cu.reportError(`getTypeFromExtension ${ext}`);
+ }
+ let cache = this._cache;
+ if (cache.has(ext)) {
+ return cache.get(ext);
+ }
+ let res = Services.cpmm.sendSyncMessage("NoScript:getMime", {ext})[0];
+ cache.set(ext, res);
+ return res;
+ }
+ }
+};
+
diff --git a/extensions/noscript/chrome/content/noscript/MimeServiceParent.js b/extensions/noscript/chrome/content/noscript/MimeServiceParent.js
new file mode 100644
index 0000000..8fa874a
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/MimeServiceParent.js
@@ -0,0 +1,19 @@
+var MimeService = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener, Ci.nsISupportsWeakReference]),
+ service: Cc['@mozilla.org/uriloader/external-helper-app-service;1']
+ .getService(Ci.nsIMIMEService),
+ getTypeFromExtension(ext) {
+ return this.service.getTypeFromExtension(ext);
+ },
+ receiveMessage(m) {
+ if (m.name === "NoScript:getMime") {
+ try {
+ return this.getTypeFromExtension(m.data.ext);
+ } catch (e) {
+ ns.dump(`Could not guess mime type for ${m.data.ext}`);
+ }
+ }
+ return '';
+ }
+};
+Services.ppmm.addWeakMessageListener("NoScript:getMime", MimeService);
diff --git a/extensions/noscript/chrome/content/noscript/NoScript_License.txt b/extensions/noscript/chrome/content/noscript/NoScript_License.txt
new file mode 100644
index 0000000..00a3b0e
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/NoScript_License.txt
@@ -0,0 +1,17 @@
+NoScript - a Firefox extension for whitelist driven safe JavaScript execution
+Copyright (C) 2004-2014 Giorgio Maone - g.maone@informaction.com
+
+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 2 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, write to the
+Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA \ No newline at end of file
diff --git a/extensions/noscript/chrome/content/noscript/PasteHandler.jsm b/extensions/noscript/chrome/content/noscript/PasteHandler.jsm
new file mode 100644
index 0000000..72151f1
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/PasteHandler.jsm
@@ -0,0 +1,83 @@
+var EXPORTED_SYMBOLS = ["PasteHandler"];
+
+const Cu = Components.utils;
+
+Cu.import("chrome://noscript/content/importer.jsm");
+let IMPORT = IMPORT_FOR(this);
+
+function PasteHandler(ctx) {
+ this.ctx = ctx;
+ ctx.addEventListener("paste", pasteEventHandler, true);
+}
+
+PasteHandler.prototype = {
+ dispose() {
+ this.ctx.removeEventListener("paste", pasteEventHandler, true);
+ }
+}
+
+
+
+function pasteEventHandler(e) {
+ if (typeof Cu === "undefined") { // uninstalled
+ e.currentTarget.removeEventListener(e.type, arguments.callee, true);
+ return;
+ }
+ Cu.import("resource://gre/modules/Services.jsm");
+ if (!Services.prefs.getBoolPref("noscript.sanitizePaste")) {
+ return;
+ }
+ let data = e.clipboardData;
+ let html = data.getData("text/html");
+ let t = e.target;
+ if (t.nodeType !== 1) t = t.parentElement;
+
+ let console = t.ownerDocument.defaultView.console;
+
+ try {
+ let node = t.cloneNode();
+
+ node.innerHTML = html;
+
+ if (sanitizeExtras(node)) {
+ let sanitized = node.innerHTML;
+ IMPORT("defer");
+ defer(function() { try {
+ sanitizeExtras(t);
+ console.log("[NoScript] Sanitized\n<PASTE>\n" + html + "\n</PASTE>to\n<PASTE>\n" + sanitized + "</PASTE>");
+ } catch(ex) {
+ console.log(ex);
+ }}, 0);
+ }
+ } catch(ex) {
+ console.log(ex);
+ }
+}
+
+function sanitizeExtras(el) {
+ let ret = false;
+
+ // remove attributes from forms
+ for (let f of el.getElementsByTagName("form")) {
+ for (let a of f.attributes) {
+ f.removeAttribute(a.name);
+ ret = true;
+ }
+ }
+
+ let doc = el.ownerDocument;
+
+ // remove dangerous URLs (e.g. javascript: or data: URLs)
+ for (let a of ['href', 'to', 'from', 'by', 'values']) {
+ let res = doc.evaluate('//@' + a, el, null, /* DOMXPathResult.UNORDERED_NODE_SNAPSHOT_TYPE */ 6, null);
+ for (let j = res.snapshotLength; j-- > 0;) {
+ let attr = res.snapshotItem(j);
+ if (/^\W*(?:(?:javascript|data):|https?:[\s\S]+[[(<])/i.test(unescape(attr.value))) {
+ attr.value = "javascript:void(0)";
+ ret = true;
+ }
+ }
+ }
+ return ret;
+}
+
diff --git a/extensions/noscript/chrome/content/noscript/Plugins.js b/extensions/noscript/chrome/content/noscript/Plugins.js
new file mode 100644
index 0000000..d19511f
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Plugins.js
@@ -0,0 +1,30 @@
+var Plugins = {
+ _disabled: false,
+ get disabled() { return this._disabled; },
+
+ _registrar: Components.manager.nsIComponentRegistrar,
+ _CTRID: "@mozilla.org/plugin/host;1",
+ get _CID() {
+ delete this._CID;
+ return this._CID = this._registrar.contractIDToCID(this._CTRID);
+ },
+ get _factory() {
+ delete this._factory;
+
+ return this._factory = Components.manager.getClassObject(Cc[this._CTRID], Ci.nsIFactory);
+ },
+
+ set disabled(b) {
+ if (b == this._disabled) return b;
+ if (b) {
+ this._registrar.unregisterFactory(this._CID, this._factory);
+ } else {
+ this._registrar.registerFactory(this._CID, "PluginHost", this._CTRID, this._factory);
+ }
+ return this._disabled = !!b;
+ }
+
+};
+// Gecko >= 2.0 seems to need the following to gets things rolling reliably
+Plugins.disabled = true;
+Plugins.disabled = false;
diff --git a/extensions/noscript/chrome/content/noscript/Policy.js b/extensions/noscript/chrome/content/noscript/Policy.js
new file mode 100644
index 0000000..668d0a3
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Policy.js
@@ -0,0 +1,927 @@
+Cc['@mozilla.org/docloaderservice;1'].getService(nsIWebProgress).addProgressListener(ns,
+ nsIWebProgress.NOTIFY_LOCATION | nsIWebProgress.NOTIFY_STATE_REQUEST | nsIWebProgress.NOTIFY_STATUS |
+ ("NOTIFY_REFRESH" in nsIWebProgress ? nsIWebProgress.NOTIFY_REFRESH : 0));
+
+var PolicyState = {
+ hintsList: [],
+ checking: [],
+ addCheck: function(url) {
+ if (typeof Map === "function") {
+ this.checking = new Map();
+ this.addCheck = function(url) { this.checking.set(url, true); };
+ this.removeCheck = function(url) { this.checking.delete(url); };
+ PolicyState.isChecking = (url) => this.checking.has(url);
+ } else {
+ this.addCheck = function(url) {
+ if (this.checking.indexOf(url) === -1) {
+ this.checking.push(url);
+ }
+ };
+ }
+ this.addCheck(url);
+ },
+
+ removeCheck: function(url) {
+ let idx = this.checking.indexOf(url);
+ if (idx !== -1) this.checking.splice(idx, 1);
+ },
+ isChecking: function(url) {
+ return this.checking.indexOf(url) !== -1;
+ },
+
+ hintsForURI: function(uri, clear) {
+ let hl = this.hintsList;
+ let spec = uri.spec;
+
+ for (let j = hl.length; j--;) {
+ let h = hl[j];
+ if (h.URISpec !== spec) continue;
+ try {
+ if (h.URIRef.get() === uri) {
+ if (clear) hl.splice(j, 1);
+ return h;
+ }
+ } catch(e) {
+ }
+ }
+ return null;
+ },
+
+ attach: function(channel) {
+ let uri = channel.URI;
+ if (this.extract(channel) ||
+ !(uri.schemeIs("http") || uri.schemeIs("https")))
+ return;
+
+ let hints = this.hintsForURI(uri, true) || uri !== channel.originalURI && this.hintsForURI(channel.originalURI, true);
+ if (hints) {
+ hints._attached = true;
+ if (hints.contentType === 6) {
+ let origin = hints.requestOrigin;
+ if (origin && origin.schemeIs("moz-nullprincipal")) {
+ if (/\n(?:handleCommand@chrome:\/\/[\w/-]+\/urlbarBindings\.xml|.*?@chrome:\/\/noscript\/content\/noscriptBM\.js)(?::\d+)+\n/
+ .test(new Error().stack)) {
+ hints.requestOrigin = ABE.BROWSER_URI;
+ } else if (hints.context.docShell) {
+ hints.requestOrigin = IOUtil.unwrapURL(hints.context.docShell.currentURI);
+ }
+ }
+ }
+ ns.reqData(channel).policyHints = hints;
+ } else {
+ // if (!this.extract(channel)) ns.log("Missing hints for " + channel.name + ", " + channel.status + ", " + channel.loadFlags);
+ }
+ }
+,
+ extract(channel, detach) {
+ let data = ns.reqData(channel);
+ let ph = data.policyHints;
+ if (detach) delete data.policyHints;
+ return ph;
+ },
+ detach(channel) {
+ let uri = channel.URI;
+ if (!(uri.schemeIs("http") || uri.schemeIs("https"))) return null;
+ let hints = this.extract(channel, true);
+ if (!hints) this.reset(uri);
+ return hints;
+ }
+,
+ reset: function(uri) {
+ if (uri) this.hintsForURI(uri, true);
+ else this.sweep();
+ },
+ cancel: function(hints) {
+ hints._psCancelled = true;
+ },
+
+ SWEEP_COUNTDOWN: 1000,
+ _sweepCount: 1000,
+ save: function(uri, hints) {
+
+ if ("_psCancelled" in hints) return false;
+
+ this.hintsList.push(new PolicyHints(uri, hints));
+
+ if (this._sweepCount-- < 0) this.sweep();
+ return true;
+ },
+
+ sweep: function() {
+ this._sweepCount = this.SWEEP_COUNTDOWN;
+ let hl = this.hintsList;
+ for (let j = hl.length; j--;) {
+ let u;
+ try {
+ u = hl[j].URIRef.get();
+ } catch(e) {
+ u = null;
+ }
+ if (!u) hl.splice(j, 1);
+ }
+ },
+
+ toString: function() {
+ return "PolicyState: " + this.hintsList.map((h) => h.URISpec + " - " + h.URIRef.get()).toSource()
+ }
+}
+
+function PolicyHints(uri, hints) {
+ this.args = hints;
+ if (hints[1] === uri) {
+ hints[1] = uri.clone(); // avoid cyclic references
+ if (hints[2] === uri) {
+ hints[2] = hints[1];
+ }
+ }
+ this.context = hints[3]; // turns it into a weak reference
+ this.URIRef = Cu.getWeakReference(uri);
+ this.URISpec = uri.spec; // for fast lookups
+}
+
+PolicyHints.prototype = (function() {
+ const props = ["contentType", "contentLocation", "requestOrigin", "context", "mimeType", "extra", "owner"];
+ const proto = {
+ get wrappedJSObject() { return this; },
+ toArray: function() { return props.map(p => this[p]); },
+ toSource: Object.prototype.toSource,
+ toString: Object.prototype.toSource,
+ };
+
+ props.forEach(function(p, i) {
+ let setter = p === "context" ?
+ function(v) {
+ try {
+ v = v ? Cu.getWeakReference(v) : null;
+ } catch (e) {
+ v = null;
+ }
+ if (v) {
+ this.__defineGetter__(i, function() { try { return v.get(); } catch (e) {} return null; } );
+ } else {
+ this.args[i] = v;
+ }
+ return this[p];
+ }
+ : function(v) { return (this.args[i] = v); };
+
+ proto.__defineGetter__(p, function() { return this.args[i]; });
+ proto.__defineSetter__(p, setter);
+ });
+
+ return proto;
+})();
+
+var NOPContentPolicy = {
+ shouldLoad: CP_NOP,
+ shouldProcess: CP_NOP
+};
+
+
+// nsIContentPolicy interface
+// we use numeric constants for performance sake:
+// TYPE_OTHER = 1
+// TYPE_SCRIPT = 2
+// TYPE_IMAGE = 3
+// TYPE_STYLESHEET = 4
+// TYPE_OBJECT = 5
+// TYPE_DOCUMENT = 6
+// TYPE_SUBDOCUMENT = 7
+// TYPE_REFRESH = 8
+// TYPE_XBL = 9
+// TYPE_PING = 10
+// TYPE_XMLHTTPREQUEST = 11
+// TYPE_OBJECT_SUBREQUEST = 12
+// TYPE_DTD = 13
+// TYPE_FONT = 14
+// TYPE_MEDIA = 15
+// TYPE_WEBSOCKET = 16
+// TYPE_CSP_REPORT = 17
+// TYPE_XSLT = 18
+// TYPE_BEACON = 19
+// ACCEPT = 1
+
+
+var MainContentPolicy = {
+ shouldLoad: function(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aInternalCall, principal) {
+ if (!aContentLocation) {
+ if (aContentType === 5 && aInternalCall === CP_SHOULDPROCESS && aMimeTypeGuess === "application/x-shockwave-flash")
+ return this.reject("Empty Flash object", arguments);
+ aContentLocation = aRequestOrigin;
+ }
+
+ var locationURL =aContentLocation.spec;
+ if (locationURL === "about:blank") return CP_OK;
+
+ if (aContentType === 5 && /^application\/x-java\b/i.test(aMimeTypeGuess) &&
+ aInternalCall !== CP_OBJECTARC) {
+ try {
+ let cs = aContext.ownerDocument.characterSet;
+ let code, codeBase, archive;
+
+ let pp = aContext.getElementsByTagName("param");
+ for (let j = 0, len = pp.length; j < len; j++) {
+ let p = pp[j];
+ if (p.parentNode == aContext) {
+ switch(p.name.toLowerCase()) {
+ case "code": code = p.value; break;
+ case "codebase": codeBase = p.value; break;
+ case "archive": archive = p.value; break;
+ }
+ }
+ }
+
+ if (!code)
+ code = aContext.getAttribute("code");
+
+ if (!codeBase)
+ codeBase = aContext.getAttribute("codebase") ||
+ (aContext instanceof win.HTMLAppletElement ? "/" : ".");
+
+ if (!archive)
+ archive = aContext.getAttribute("archive");
+
+ try {
+ aContentLocation = IOS.newURI(codeBase, cs, aRequestOrigin);
+ } catch (e) {}
+
+ if (aContext instanceof win.HTMLEmbedElement) {
+ code = aContext.getAttribute("code");
+ if (code && /\bjava\b/.test(aMimeTypeGuess)) {
+ archive = archive ? code + " " + archive : code;
+ } else code = '';
+ }
+ if (archive) {
+ let prePaths;
+ let base = aContentLocation;
+ let jars = archive.split(/[\s,]+/);
+ for (let j = jars.length; j-- > 0;) {
+ try {
+ let jar = jars[j];
+ let u = IOS.newURI(jar, cs, base);
+ let prePath = u.prePath;
+ if (prePath !== base.prePath) {
+ if (prePaths) {
+ if (prePaths.indexOf(prePath) !== -1) continue;
+ prePaths.push(prePath);
+ } else prePaths = [prePath];
+ } else {
+ if (j === 0 && code === jar) aContentLocation = u;
+ continue;
+ }
+ this.setExpando(aContext, "allowed", null);
+ let res = this.shouldLoad(aContentType, u, aRequestOrigin, aContext, aMimeTypeGuess, CP_OBJECTARC);
+ if (res !== CP_OK) return res;
+ } catch (e) {
+ this.dump(e)
+ }
+ }
+ this.setExpando(aContext, "allowed", null);
+ }
+
+ if (code) {
+ try {
+ if (!/\.class\s*$/i.test(code)) code += ".class";
+ aContentLocation = IOS.newURI(code, cs, aContentLocation);
+ } catch (e) {}
+ }
+ } catch (e) {}
+ }
+
+ var logIntercept = this.consoleDump, logBlock;
+
+ if(logIntercept) {
+ logBlock = logIntercept & LOG_CONTENT_BLOCK;
+ logIntercept = logIntercept & LOG_CONTENT_INTERCEPT;
+ } else logBlock = false;
+
+ if (!aInternalCall) {
+ PolicyState.addCheck(aContentLocation);
+ }
+
+ var originURL, originSite, locationSite, scheme,
+ forbid, isScript, isJava, isFlash, isSilverlight,
+ isLegacyFrame, blockThisFrame, contentDocument,
+ unwrappedLocation, mimeKey,
+ isHTTP,
+ mustCountObject = false;
+
+
+ try {
+
+ let win = aContext && (
+ aContext.ownerDocument
+ ? aContext.ownerDocument.defaultView
+ : aContext.document ? aContext : (aContext.defaultView || Cu.getGlobalForObject(aContext))
+ );
+
+ unwrappedLocation = IOUtil.unwrapURL(aContentLocation);
+ scheme = unwrappedLocation.scheme;
+
+ if (scheme === "file") {
+ if (!ns.checkLocalLink(unwrappedLocation, ns.getPrincipal(aContext), true)) {
+ return this.reject("Local File Link", arguments);
+ }
+ }
+
+ isHTTP = scheme === "http" || scheme === "https";
+
+ if (isHTTP) {
+
+ // reject any cross-site google-analytics subrequest unless explicitly whitelisted
+ if (aContentType !== 2 && aContentType !== 6 &&
+ unwrappedLocation.host.indexOf("google-analytics") !== -1 &&
+ unwrappedLocation.prePath !== (aRequestOrigin && aRequestOrigin.prePath) &&
+ !this.isJSEnabled(this.getSite(unwrappedLocation.spec))
+ ) {
+ return this.reject("Google Analytics web bug", arguments);
+ }
+
+ if (aRequestOrigin &&
+ !(aContentType === 4 && Bug.$677643)
+ ) {
+
+ HTTPS.forceURI(unwrappedLocation, null, aContext);
+
+ switch(aContentType) {
+
+ case 5:
+
+
+ // early ABE check for any plugin content except Flash, Silverlight and PDF
+ // (Java, for instance, is known to bypass HTTP observers!)
+ if (/^application\/(?:x-(?:shockwave-flash|silverlight)$|futuresplash|pdf$)/i.test(aMimeTypeGuess))
+ break;
+
+ case 7:
+ if (aContext instanceof win.HTMLObjectElement) {
+ if (this.isCachedObjectMime(aMimeTypeGuess) &&
+ !(aContext.offsetWidth && aContext.offsetHeight) &&
+ this.getPref("allowCachingObjects") &&
+
+ aRequestOrigin && this.isJSEnabled(this.getSite(aRequestOrigin.spec), win) &&
+ !this.pluginForMime(aMimeTypeGuess) &&
+ (aMimeTypeGuess.indexOf("css") > 0 || this.isJSEnabled(this.getSite(aContentLocation.spec), win))
+ ) {
+ return CP_OK;
+ }
+ }
+ if (aContentType === 7 || aInternalCall) break;
+
+ case 1: case 12: // we may have no chance to check later for unknown and sub-plugin requests
+
+ let res = ABE.checkPolicy(aRequestOrigin, unwrappedLocation, aContentType);
+ if (res && res.fatal) {
+ this.requestWatchdog.notifyABE(res, true);
+ return this.reject("ABE-denied inclusion", arguments);
+ }
+ }
+ }
+
+ if (logIntercept && this.cpConsoleFilter.indexOf(aContentType) > -1) {
+ this.cpDump("processing", aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aInternalCall);
+ if (this.consoleDump & LOG_CONTENT_CALL)
+ this.dump(new Error().stack);
+ }
+
+ }
+
+ switch (aContentType) {
+ case 9: // XBL - warning, in 1.8.x could also be XMLHttpRequest...
+ return this.forbidXBL &&
+ this.forbiddenXMLRequest(aRequestOrigin, aContentLocation, aContext, this.forbiddenXBLContext)
+ ? this.reject("XBL", arguments) : CP_OK;
+
+ case 11: // in Firefox 3 we check for cross-site XHR
+ return this.forbidXHR &&
+ this.forbiddenXMLRequest(aRequestOrigin, aContentLocation, aContext, this.forbiddenXHRContext)
+ ? this.reject("XHR", arguments) : CP_OK;
+
+ case 10: // TYPE_PING
+ if (this.jsEnabled || !this.getPref("noping", true) ||
+ aRequestOrigin && this.isJSEnabled(this.getSite(aRequestOrigin.spec))
+ )
+ return CP_OK;
+
+ return this.reject("Ping", arguments);
+
+ case 17: // CSP report, avoid exfiltration on untrusted resources
+ if (this.jsEnabled ||
+ this.isJSEnabled(this.getSite(aContentLocation.spec)) &&
+ aRequestOrigin && this.isJSEnabled(this.getSite(aRequestOrigin.spec))
+ )
+ return CP_OK;
+
+ return this.reject("CSP report", arguments);
+
+ case 2:
+ if (/^(?:chrome|resource|moz-extension)$/.test(aContentLocation.scheme)) {
+ return CP_OK;
+ }
+ forbid = isScript = true;
+ break;
+
+ case 4: // STYLESHEETS
+ if (PolicyUtil.supportsXSL ||
+ !(PolicyUtil.isXSL(aContext) && /\/x[ms]l/.test(aMimeTypeGuess))
+ ) return CP_OK;
+ case 18: // XSL
+ if (!/^(?:chrome|resource|moz-extension)$/.test(aContentLocation.scheme) &&
+ this.getPref("forbidXSLT", true)) {
+ forbid = isScript = true; // we treat XSLT like scripts
+ break;
+ }
+ return CP_OK;
+
+ case 14: // fonts
+ forbid = this.forbidFonts && !/^(?:chrome|moz-extension)$/.test(aContentLocation.scheme);
+ if (!forbid) return CP_OK;
+ mimeKey = "FONT";
+ if (aContentLocation && aRequestOrigin && aContentLocation.schemeIs("data"))
+ locationURL = this.getSite(aRequestOrigin.spec);
+
+ break;
+
+ case 5: // embeds
+
+ if (aContentLocation && aRequestOrigin &&
+ (locationURL = aContentLocation.spec) == (originURL = aRequestOrigin.spec) &&
+ aMimeTypeGuess) {
+
+ if (aContext instanceof win.HTMLEmbedElement &&
+ this.isAllowedObject(locationURL, aMimeTypeGuess)
+ ) {
+ if (logIntercept) this.dump("Plugin document " + locationURL);
+ return CP_OK; // plugin document, we'll handle it in our webprogress listener
+ }
+
+ if (!(aContext.getAttribute("data") || aContext.getAttribute("codebase") || aContext.getAttribute("archive") || aContext.getAttribute("src")
+ || aContext.firstChild) && aMimeTypeGuess == "application/x-shockwave-flash") {
+ if (logIntercept) this.dump("Early Flash object manipulation with no source set yet.");
+ if (this.anyAllowedObject(this.getSite(locationURL), aMimeTypeGuess))
+ return CP_OK;
+
+ this.setExpando(aContext, "requiresReload", true);
+ }
+ }
+
+ case 15: // media
+ if (aContentType === 15) {
+ if (aRequestOrigin && !this.isJSEnabled(this.getSite(aRequestOrigin.spec), aContext.ownerDocument.defaultView)) {
+ // let's wire poor man's video/audio toggles if JS is disabled and therefore controls are not available
+ this.delayExec(function() {
+ aContext.addEventListener("click", function(ev) {
+ var media = ev.currentTarget;
+ if (media.paused) media.play();
+ else media.pause();
+ }, true);
+ }, 0);
+ }
+
+ forbid = this.forbidMedia;
+ if (!forbid && aMimeTypeGuess) return CP_OK;
+ }
+
+ if (aMimeTypeGuess) // otherwise let's treat it as an iframe
+ break;
+
+ case 7:
+
+ locationURL = aContentLocation.spec;
+ originURL = aRequestOrigin && aRequestOrigin.spec || "";
+ let vsPos = locationURL.indexOf("view-source:");
+ if (vsPos !== -1 && vsPos < 7 // includes feed: and pcast: prefixed URLs
+ && /^(?:https?|ftp):/.test(originURL))
+ return this.reject("Embedded view-source:", arguments);
+
+ if (locationURL === "about:blank" || /^chrome:/.test(locationURL)
+ || !originURL && (aContext instanceof Ci.nsIDOMXULElement) // custom browser like in Stumbleupon discovery window
+ ) return CP_OK;
+
+ if (!aMimeTypeGuess) {
+ aMimeTypeGuess = this.guessMime(aContentLocation);
+ if (logIntercept)
+ this.dump("Guessed MIME '" + aMimeTypeGuess + "' for location " + locationURL);
+ }
+
+ if (aContentType === 15) {
+ if (!aMimeTypeGuess) try {
+ aMimeTypeGuess = aContext.tagName.toLowerCase() + "/ogg";
+ } catch (e) {}
+
+ if (!forbid) return CP_OK;
+
+ break; // we just need to guess the Mime for video/audio
+ }
+
+ if (!(aContext instanceof Ci.nsIDOMXULElement)) {
+
+ isLegacyFrame = aContext instanceof win.HTMLFrameElement;
+
+ if (isLegacyFrame
+ ? this.forbidFrames || // we shouldn't allow framesets nested inside iframes, because they're just as bad
+ this.forbidIFrames &&
+ (win.frameElement instanceof win.HTMLIFrameElement) &&
+ this.getPref("forbidMixedFrames", true)
+ : this.forbidIFrames || // we use iframes to make placeholders for blocked legacy frames...
+ this.forbidFrames &&
+ this.isLegacyFrameReplacement(aContext)
+ ) {
+ try {
+ contentDocument = aContext.contentDocument;
+ } catch(e) {}
+
+ blockThisFrame = (aInternalCall === CP_FRAMECHECK) && !(
+ this.knownFrames.isKnown(locationURL, originSite = this.getSite(originURL)) ||
+ /^(?:chrome|resource|wyciwyg|moz-extension):/.test(locationURL) ||
+ locationURL === this._silverlightInstalledHack ||
+ locationURL === this.compatGNotes ||
+ (
+ originURL
+ ? ( /^(?:chrome|about|resource|moz-extension):/.test(originURL) && originURL !== "about:blank" ||
+ /^(?:data|javascript):/.test(locationURL) &&
+ (contentDocument && (originURL == contentDocument.URL
+ || /^(?:data:|javascript:|about:blank$)/.test(contentDocument.URL)
+ ) || this.isFirebugJSURL(locationURL)
+ )
+ )
+ : contentDocument &&
+ this.getSite(contentDocument.URL) == (locationSite = this.getSite(locationURL))
+ )
+ ) && this.forbiddenIFrameContext(originURL || (originURL = aContext.ownerDocument.URL), locationURL);
+ }
+ }
+ case 6:
+
+ if (aRequestOrigin && aRequestOrigin != aContentLocation) {
+
+ if (isHTTP) {
+
+ // external?
+ if (aRequestOrigin.schemeIs("chrome") && aContext && aContext.ownerDocument &&
+ aContext.ownerDocument.defaultView.isNewToplevel){
+ this.requestWatchdog.externalLoad = aContentLocation.spec;
+ }
+
+ } else if(scheme === "data" || scheme === "javascript") {
+
+ if (aContext instanceof Ci.nsIDOMXULElement) {
+ originURL = originURL || aRequestOrigin.spec;
+ if (originURL === "chrome://browser/content/browser.xul") {
+ //code
+ if (this.dropXssProtection) {
+ let stack = new Error().stack.split("\n");
+ for (let j = stack.length; j-- > 0;)
+ if (stack[j].indexOf("onxbldrop([object DragEvent])@chrome://global/content/bindings/browser.xml") === 0) {
+ ns.log('NoScript prevented "' + aContentLocation.spec + '" from being loaded on drop.');
+ return this.reject("Drop XSS", arguments);
+ }
+ }
+ } else if (
+ !(aContext.ownerDocument.URL === originURL // Addon-SDK panels
+ || this.isJSEnabled(originSite = this.getSite(originURL), aContext.ownerDocument.defaultView))
+ ) {
+ return this.reject("top level data: URI from forbidden origin", arguments);
+ }
+ }
+ return CP_OK; // JavaScript execution policies will take care of this
+ } else if(scheme !== aRequestOrigin.scheme &&
+ scheme !== "chrome" && // faster path for common case
+ this.isExternalScheme(scheme)) {
+ // work-around for bugs 389106 & 389580, escape external protocols
+ if (aContentType !== 6 && !aInternalCall &&
+ this.getPref("forbidExtProtSubdocs", true) &&
+ !this.isJSEnabled(originSite = this.getSite(originURL = originURL || aRequestOrigin.spec)) &&
+ (!aContext.contentDocument || aContext.contentDocument.URL != originURL)
+ ) {
+ return this.reject("External Protocol Subdocument", arguments);
+ }
+ if (!this.normalizeExternalURI(aContentLocation)) {
+ return this.reject("Invalid External URL", arguments);
+ }
+ } else if(aContentType === 6 && scheme === "chrome" &&
+ this.getPref("lockPrivilegedUI", false) && // block DOMI && Error Console
+ /^(?:javascript:|chrome:\/\/(?:global\/content\/console|inspector\/content\/inspector|venkman\/content\/venkman)\.xul)$/
+ .test(locationURL)) {
+ return this.reject("Locked Privileged UI", arguments);
+ }
+ }
+
+ if (!(this.forbidSomeContent || this.alwaysBlockUntrustedContent) ||
+ !blockThisFrame && (
+ aContext instanceof Ci.nsIDOMXULElement ||
+ !aMimeTypeGuess ||
+ aMimeTypeGuess.substring(0, 5) === "text/" ||
+ aMimeTypeGuess === "application/xml" ||
+ aMimeTypeGuess === "application/xhtml+xml" ||
+ aMimeTypeGuess.substring(0, 6) === "image/" ||
+ !(this.isMediaType(aMimeTypeGuess) || this.pluginForMime(aMimeTypeGuess))
+ )
+ ) {
+
+ if (logBlock)
+ this.dump("Document OK: " + aMimeTypeGuess + "@" + (locationURL || aContentLocation.spec) +
+ " --- PGFM: " + this.pluginForMime(aMimeTypeGuess));
+
+ if (aContentLocation.schemeIs("about") && /^about:(?:net|cert)error\?/.test(aContentLocation.spec)) {
+ this.handleErrorPage(aContext, aContentLocation);
+ }
+
+ return CP_OK;
+ }
+ break;
+
+ case 12:
+ // Silverlight mindless activation scheme :(
+ if (!this.forbidSilverlight
+ || !this.getExpando(aContext, "silverlight") || this.getExpando(aContext, "allowed"))
+ return CP_OK;
+
+ aMimeTypeGuess = "application/x-silverlight";
+ break;
+ default:
+ return CP_OK;
+ }
+
+
+ locationURL = locationURL || aContentLocation.spec;
+ locationSite = locationSite || this.getSite(locationURL);
+
+ var untrusted = untrusted || this.isUntrusted(locationSite);
+
+ if(logBlock)
+ this.dump("[CP PASS 2] " + aMimeTypeGuess + "*" + locationURL + ", " + aContentType + ", " + aInternalCall);
+
+ if (isScript) {
+ // we must guess the right context here, see https://bugzilla.mozilla.org/show_bug.cgi?id=464754
+ contentDocument = aContext && aContext.ownerDocument || aContext;
+
+ // we get the embedding document URL explicitly,
+ // otherwise on redirection we would get the previous redirected URL
+ if (contentDocument) { // XSLT comes with no context sometimes...
+ this.cacheCodeSite(contentDocument.defaultView, locationSite);
+ originURL = contentDocument.URL;
+ } else {
+ originURL = aRequestOrigin && aRequestOrigin.spec;
+ }
+ originSite = originURL && this.getSite(originURL) || "";
+ let httpOrigin = originSite.indexOf("http") === 0;
+
+
+ let scriptElement;
+ if (aContentType === 2) { // "real" JavaScript include
+ if (!(this.cascadePermissions || this.globalHttpsWhitelist) &&
+ originSite && !this.isJSEnabled(originSite, contentDocument && contentDocument.window) &&
+ isHTTP && httpOrigin) {
+ // JavaScript-disabled page with script inclusion
+ this.syncUI(contentDocument);
+ return this.reject("Script inclusion on forbidden page", arguments);
+ }
+
+ forbid = !(originSite && locationSite == originSite);
+ scriptElement = aContext && win && (aContext instanceof win.HTMLScriptElement);
+
+ if (forbid && httpOrigin && this.requestWatchdog /* lazy init */) {
+ // XSSI protection
+ let scriptURL = locationURL;
+ if (scriptURL.lastIndexOf('/') === scriptURL.length - 1)
+ scriptURL = scriptURL.slice(0, -1); // right trim slash
+ let decodedOrigin = InjectionChecker.urlUnescape(aRequestOrigin.spec);
+ if ((decodedOrigin.indexOf(scriptURL) > 0 || // don't use 0 b/c on redirections origin == scriptURL
+ Entities.convertAll(decodedOrigin).indexOf(scriptURL) > 0) &&
+ this.getPref("xss.checkInclusions") &&
+ !new AddressMatcher(this.getPref("xss.checkInclusions.exceptions", "")).test(locationURL)
+ ) {
+ let ds = DOM.getDocShellForWindow(contentDocument.defaultView);
+ let ch = ds.currentDocumentChannel;
+ let referrerURI = IOUtil.extractInternalReferrer(ch);
+ if (referrerURI && referrerURI.scheme.indexOf("http") === 0 &&
+ this.getBaseDomain(referrerURI.host) !== this.getBaseDomain(this.getDomain(originURL))) {
+ let msg = "Blocking reflected script inclusion origin XSS from " + referrerURI.spec;
+ if (scriptElement) this.log(msg + ": " + locationURL + "\nembedded by\n" + decodedOrigin);
+ return this.reject(msg, arguments);
+ }
+ }
+ }
+ } else isScript = scriptElement = false;
+
+ if (forbid) {
+ let doc = aContext && aContext.ownerDocument || aContext;
+ forbid = !this.isJSEnabled(locationSite, win);
+ if (forbid && this.ignorePorts && /:\d+$/.test(locationSite))
+ forbid = !(this.isJSEnabled(locationSite.replace(/:\d+$/, '')) && this.autoTemp(locationSite));
+ }
+
+ if ((untrusted || forbid) && scheme !== "data") {
+ if (scriptElement) {
+ ScriptSurrogate.replaceScript(aContext);
+ }
+
+ this.syncUI(contentDocument);
+
+ return this.reject(isScript ? "Script" : "XSLT", arguments);
+ } else {
+
+ if (scriptElement) {
+
+ if (this.executingJSURL(contentDocument.defaultView.top.document) &&
+ !this.jsPolicySites.matches(this.getSite(contentDocument.defaultView.location.href))) {
+ this.bookmarkletImport(aContext, locationURL);
+ return this.reject("Bookmarklet inclusion, already imported synchronously", arguments);
+ }
+
+ }
+
+ return CP_OK;
+ }
+ }
+
+ mimeKey = mimeKey || aMimeTypeGuess || "application/x-unknown";
+
+ if (!(forbid || locationSite === "chrome:" || aContentLocation.schemeIs("moz-extension"))) {
+
+ forbid = blockThisFrame || untrusted && this.alwaysBlockUntrustedContent;
+ if (!forbid) {
+ if (this.forbidSomeContent && aMimeTypeGuess) {
+
+ forbid =
+ (
+ (isFlash = /^application\/(?:x-shockwave-flash|futuresplash)/i.test(aMimeTypeGuess)) ||
+ (isJava = /^application\/x-java\b/i.test(aMimeTypeGuess)) ||
+ (isSilverlight = /^application\/x-silverlight\b/i.test(aMimeTypeGuess))
+ ) &&
+ isFlash && this.forbidFlash ||
+ isJava && this.forbidJava ||
+ isSilverlight && this.forbidSilverlight;
+
+ // see http://heasman.blogspot.com/2008/03/defeating-same-origin-policy-part-i.html
+ if (isJava && /(?:[^\/\w\.\$\:]|^\s*\/\/)/.test(aContext.getAttribute("code") || "")) {
+ return this.reject("Illegal Java code attribute " + aContext.getAttribute("code"), arguments);
+ }
+
+ if (isFlash) this.tagWindowlessObject(aContext);
+
+ if (this.isAllowedMime(mimeKey, locationSite)) return CP_OK;
+
+ if (forbid) {
+
+ if (isSilverlight) {
+ if (logIntercept) this.dump("Silverlight " + aContentLocation.spec + " " + typeof(aContext) + " " + aContentType + ", " + aInternalCall);
+
+ this.setExpando(aContext, "silverlight", aContentType != 12);
+
+ locationURL = this.resolveSilverlightURL(aRequestOrigin, aContext);
+ locationSite = this.getSite(locationURL);
+ originURL = aRequestOrigin && aRequestOrigin.spec;
+
+ if(this.isAllowedObject(locationURL, mimeKey, locationSite) ||
+ this.isAllowedObjectByDOM(aContext, locationURL, originURL, mimeKey, locationSite)) {
+ if (logIntercept && forbid) this.dump("Silverlight " + locationURL + " is whitelisted, ALLOW");
+ this.handleClickToPlay(aContext);
+ return CP_OK;
+ }
+ } else if (isFlash) {
+ locationURL = this.addFlashVars(locationURL, aContext);
+ }
+ } else if ((forbid = this.forbidPlugins && !(isJava || isFlash || isSilverlight))) {
+ locationURL = this.addObjectParams(locationURL, aContext);
+ } else {
+ forbid = this.forbidMedia && /^(?:audio|video)\//i.test(aMimeTypeGuess);
+ }
+ }
+ } else if (blockThisFrame &&
+ this.isAllowedMime(mimeKey, locationSite) ||
+ this.isAllowedMime("FRAME", locationSite)) {
+ return CP_OK;
+ }
+ } else {
+ if (this.isAllowedMime(mimeKey, locationSite)) return CP_OK;
+ }
+
+ if (forbid && (!this.contentBlocker || /^resource:/.test(locationSite))) {
+
+ originURL = originURL || (aRequestOrigin && aRequestOrigin.spec);
+ originSite = originSite || this.getSite(originURL);
+
+ let jsRx = /^(?:javascript|data):/;
+
+ let originOK = originSite
+ ? this.isJSEnabled(originSite, win)
+ : jsRx.test(originURL); // if we've got such an origin, parent should be trusted
+
+ if (locationSite && this.checkShorthands(locationSite)) this.autoTemp(locationSite);
+
+ let locationOK = locationSite
+ ? this.isJSEnabled(locationSite, win)
+ : jsRx.test(locationURL) && originOK // use origin for javascript: or data:
+ ;
+
+ forbid = !(locationOK && (originOK ||
+ !this.getPref(blockThisFrame
+ ? "forbidIFramesParentTrustCheck" : "forbidActiveContentParentTrustCheck",
+ true)
+ ));
+ }
+
+ mustCountObject = true;
+
+ if (forbid) forbid = !(aContentLocation.schemeIs("file") && aRequestOrigin && aRequestOrigin.schemeIs("resource")); // fire.fm work around
+
+ if (forbid && this.cascadePermissions && !this.contentBlocker) {
+ let win = aContext.ownerDocument && aContext.ownerDocument.defaultView;
+ let topDoc = win.top.document;
+ forbid = untrusted || !this.isJSEnabled(this.getDocSite(topDoc), win);
+ }
+
+ if (forbid) {
+
+ if (!originSite) originSite = this.getSite(originURL || (originURL = aRequestOrigin && aRequestOrigin.spec || ""));
+
+ if (isJava && originSite && /^data:application\/x-java\b/.test(locationURL) ||
+ aContentType === 15 && locationURL === "data:,") {
+ locationURL = locationSite = originSite;
+ }
+
+ try { // moved here because of http://forums.mozillazine.org/viewtopic.php?p=3173367#3173367
+ if (this.getExpando(aContext, "allowed") ||
+ this.isAllowedObject(locationURL, mimeKey, locationSite, originSite) ||
+ this.isAllowedObjectByDOM(aContext, locationURL, originURL, mimeKey, locationSite, originSite)
+ ) {
+ this.setExpando(aContext, "allowed", true);
+ this.handleClickToPlay(aContext);
+ return CP_OK; // forceAllow
+ }
+ } catch(ex) {
+ this.dump("Error checking plugin per-object permissions:" + ex);
+ }
+
+ if (isLegacyFrame) { // inject an embed and defer to load
+ if (blockThisFrame && this.blockLegacyFrame(aContext, aContentLocation, true))
+ return this.reject("Deferred Legacy Frame " + locationURL, arguments);
+ } else {
+ try {
+ if ((aContentType === 5 || aContentType === 7 || aContentType === 12 || aContentType === 14 || aContentType === 15) && (aContext instanceof Ci.nsIDOMNode)) {
+ if (locationURL != "data:application/x-noscript-blocked,") {
+ mustCountObject = false; // we do it in _preProcessObjectElements()
+ this.delayExec(this.tagForReplacement, 0, aContext, {
+ url: locationURL,
+ site: locationSite,
+ mime: mimeKey,
+ originSite: originSite
+ });
+ }
+ } else if (this.consoleDump & LOG_CONTENT_BLOCK) this.dump("Context is not a DOMNode? " + aContentType);
+ } catch(ex) {
+ if(this.consoleDump) this.dump(ex);
+ } finally {
+ return this.reject("Forbidden " + (contentDocument ? ("IFrame " + contentDocument.URL) : "Content"), arguments);
+ }
+ }
+ } else {
+
+
+ if (isSilverlight) {
+ this.setExpando(aContext, "silverlight", aContentType != 12);
+ }
+ if (this.consoleDump & LOG_CONTENT_CALL) {
+ this.dump(locationURL + " Allowed, " + new Error().stack);
+ }
+ }
+ } catch(e) {
+ return this.reject("Content (Fatal Error, " + e + " - " + e.stack + ")", arguments);
+ } finally {
+ if (aContentType === 5) {
+ this.setExpando(aContext, "site", locationSite);
+ }
+
+ if (mustCountObject) this.countObject(aContext, locationSite);
+
+ if (!(aContext instanceof Ci.nsIDOMXULElement)) {
+ // skip XUL elements as a work around for Stylish incompatibility on Gecko < 52
+ ns.syncUI(aContext);
+ }
+ if (!aInternalCall) PolicyState.removeCheck(aContentLocation);
+
+ if (isHTTP) PolicyState.save(aContentLocation, arguments);
+
+ }
+ return CP_OK;
+ },
+
+
+ shouldProcess: function(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeType, aExtra) {
+ return this.shouldLoad(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeType, CP_SHOULDPROCESS);
+ },
+
+
+}
+
+var PolicyUtil = {
+ supportsXSL: ("TYPE_XSLT" in Ci.nsIContentPolicy),
+ isXSL: function(ctx) {
+ if (!ctx) return false;
+ let g = Cu.getGlobalForObject(ctx);
+ return !(ctx instanceof g.HTMLLinkElement || ctx instanceof g.HTMLStyleElement || ctx instanceof g.HTMLDocument);
+ },
+
+};
diff --git a/extensions/noscript/chrome/content/noscript/Profiler.js b/extensions/noscript/chrome/content/noscript/Profiler.js
new file mode 100644
index 0000000..ee1222c
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Profiler.js
@@ -0,0 +1,63 @@
+Profiler = {
+ watchlist: { NoScript: ns, requestWatchdog: RequestWatchdog.prototype,
+ InjectionChecker: InjectionChecker, ABE: ABE, IOUtil: IOUtil, DNS: DNS},
+ data: {},
+ reset: function() { return this.data = {} },
+
+ instrument: function(b) {
+ const oo = this.watchlist;
+ const pf = "profiler.function";
+ for (let v in oo) {
+ let o = oo[v]
+ for (let n in o) {
+ let f = o[n];
+ if (typeof f == "function") {
+ if (b) {
+ if (pf in f) continue;
+ let key = v + "." + n;
+ let patched = function() {
+ let t = Date.now();
+ let r = f.apply(this, arguments);
+ let pdata = Profiler.data;
+ let data = pdata[key] || (pdata[key] = {count: 0, time: 0, min: 120000, max: 0});
+ data.count++;
+ data.time += t = (Date.now() - t);
+ if (t > data.max) data.max = t;
+ if (t < data.min) data.min = t;
+ return r;
+ }
+ patched[pf] = f;
+ o[n] = patched;
+ dump(key + "\n");
+ } else {
+ if (pf in f) o[n] = f[pf];
+ }
+ }
+ }
+ }
+ },
+
+ report: function(count) {
+ if (arguments.length === 0) count = 20;
+ dump("\n\n\nProfiler Report");
+ let ar = [];
+ for (let [call, data] in Iterator(this.data)) {
+ data.avg = Math.round(data.time / data.count * 1000) / 1000;
+ ar.push({call: call, data: data});
+ }
+ let cmp = (a,b) => a > b ? - 1: a < b ? 1 : 0;
+ ar.sort((a, b) => cmp(a.data.time, b.data.time));
+ for (let l of ar) {
+ dump(l.call + ": " + l.data.toSource() + "\n");
+ if (count-- <= 0) break;
+ }
+ },
+
+ gc: function() {
+ DOM.mostRecentBrowserWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIDOMWindowUtils)
+ .garbageCollect();
+ }
+}
+
+
diff --git a/extensions/noscript/chrome/content/noscript/RequestWatchdog.js b/extensions/noscript/chrome/content/noscript/RequestWatchdog.js
new file mode 100644
index 0000000..0efd1c9
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/RequestWatchdog.js
@@ -0,0 +1,1155 @@
+ABE; // kickstart
+
+var RequestGC = {
+ INTERVAL: 5000,
+ _timer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer),
+ _pending: [],
+ _running: false,
+ notify: function(t) {
+ try {
+ let reqs = this._pending;
+ for (let j = reqs.length; j-- > 0;) {
+ let r = reqs[j];
+ if (r.status || !r.isPending()) {
+ ns.cleanupRequest(r);
+ reqs.splice(j, 1);
+ }
+ }
+ if (reqs.length === 0) {
+ this.dispose();
+ }
+ } catch(e) {
+ ns.dump(e);
+ }
+ },
+ add: function(req) {
+ this._pending.push(req);
+ if (!this._running) {
+ this._running = true;
+ this._timer.initWithCallback(this, this.INTERVAL, Ci.nsITimer.TYPE_REPEATING_SLACK);
+ }
+ },
+ dispose() {
+ if (this._running) {
+ this._timer.cancel();
+ this._running = false;
+ }
+ }
+};
+
+
+function RequestWatchdog() {
+ this.injectionChecker = InjectionChecker;
+ this.injectionChecker.logEnabled = !!(ns.consoleDump & LOG_INJECTION_CHECK);
+ this.init();
+}
+
+ns.cleanupRequest = function(channel) {
+ PolicyState.detach(channel);
+ ABERequest.clear(channel);
+};
+
+
+RequestWatchdog.prototype = {
+
+ OBSERVED_TOPICS: ns.childProcess ? [] : ["http-on-examine-response", "http-on-examine-merged-response", "http-on-examine-cached-response"],
+
+ init: function() {
+ for (var topic of this.OBSERVED_TOPICS) OS.addObserver(this, topic, true);
+ },
+ dispose: function() {
+ for (var topic of this.OBSERVED_TOPICS) OS.removeObserver(this, topic);
+ RequestGC.dispose();
+ },
+
+ callback: null,
+ externalLoad: null,
+ noscriptReload: null,
+ DOCUMENT_LOAD_FLAGS: Ci.nsIChannel.LOAD_DOCUMENT_URI
+ | Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS, // this for OBJECT subdocs
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
+
+ observe(channel, topic) {
+ try {
+ if (!(channel instanceof Ci.nsIHttpChannel)) return;
+ } catch (e) {
+ ns.dump(`${topic} failed ${uneval(e)}`);
+ return;
+ }
+
+ if(ns.consoleDump & LOG_SNIFF) {
+ ns.dump(topic + ": " + channel.URI.spec + ", " + channel.loadFlags);
+ }
+
+ let cached = true;
+
+ switch(topic) {
+
+ case "http-on-examine-response":
+ case "http-on-examine-merged-response":
+
+ HTTPS.handleSecureCookies(channel);
+ cached = false;
+
+ case "http-on-examine-cached-response":
+ ns.serializeReqData(channel);
+ if (ns.externalFilters.enabled)
+ ns.callExternalFilters(channel, cached);
+
+ if (channel.loadFlags & this.DOCUMENT_LOAD_FLAGS) {
+ ns.serializeReqData(channel);
+ ABE.handleSandbox(channel);
+ ns.onContentSniffed(channel);
+ } else {
+ if (!((ns.inclusionTypeChecking || ns.nosniff) && ns.checkInclusionType(channel)))
+ return;
+ }
+ break;
+ }
+ },
+
+ onHttpStart: function(channel) {
+
+ const loadFlags = channel.loadFlags;
+ let isDoc = loadFlags & this.DOCUMENT_LOAD_FLAGS;
+
+ PolicyState.attach(channel); // this works before bug 797684 fix, see ns.onStateChange for now
+ let abeReq = new ABERequest(channel);
+ RequestGC.add(channel);
+
+ if (HTTPS.forceChannel(channel)) return null;
+
+ try {
+
+ if (this.externalLoad && this.externalLoad === abeReq.destination) {
+ abeReq.external = true;
+ this.externalLoad = null;
+ }
+
+ if (isDoc) {
+
+ let url = abeReq.destination;
+ if (url.indexOf("#!") > 0 &&
+ (url.indexOf("?") === -1 || url.indexOf("?_escaped_fragment_=") > 0) &&
+ ns.getPref("ajaxFallback.enabled")) {
+ let qs = '?_escaped_fragment_=' + url.match(/#!(.*)/)[1].replace(/[\s&=]/g, encodeURIComponent);
+
+ let newURL = "", isReload = false;
+ if (ns.isJSEnabled(ns.getSite(url))) {
+ if (url.indexOf(qs) > 0 && (isReload = this.noscriptReload === url)) {
+ newURL = url.replace(qs, "").replace(/([^#&]+)&/, '$1?');
+ }
+ } else if (url.indexOf(qs) === -1) {
+ newURL = url.replace(/(?:\?_escaped_fragment_=[^&#]*)|(?=#!)/, qs);
+ }
+ if (newURL && newURL != url && abeReq.redirectChain.map((u) => u.spec).indexOf(newURL) === -1) {
+ let requestWatchdog = this;
+ abeReq.replace(null, IOUtil.newURI(newURL), function(replacement) {
+ if (isReload) requestWatchdog.noscriptReload = newURL;
+ replacement.open();
+ });
+ return null;
+ }
+ }
+
+ new DOSChecker(abeReq).run(function() {
+ MaxRunTime.increase(40);
+ return this.filterXSS(abeReq);
+ }, this);
+ }
+ if (!channel.status) {
+ this.handleABE(abeReq, isDoc);
+ }
+ return abeReq;
+ } catch(e) {
+ this.die(channel, e);
+ }
+ return null;
+ },
+
+ die: function(channel, e) {
+ this.abort({ channel: channel, reason: e + " --- " + e.stack, silent: true });
+ },
+
+ handleABE: function(abeReq, isDoc) {
+ if (abeReq && ABE.enabled) {
+ try {
+ // ns.dump("handleABE called for " + abeReq.serial + ", " + abeReq.destination + " at " + Components.stack.caller);
+ let res = new DOSChecker(abeReq, true).run(function() {
+ return ABE.checkRequest(abeReq);
+ });
+ if (res) {
+ this.notifyABE(res, !(isDoc && res.fatal && ns.getPref("ABE.notify")));
+ if (res.fatal) return true;
+ }
+ } catch(e) {
+ this.die(abeReq.channel, e);
+ return true;
+ }
+ }
+ return false;
+ },
+
+ notifyABE: function(abeRes, silent) {
+ var req = abeRes.request;
+ var silentLoopback = !ns.getPref("ABE.notify.namedLoopback");
+ abeRes.rulesets.forEach(
+ function(rs) {
+ var lastRule = rs.lastMatch;
+ var lastPredicate = lastRule.lastMatch;
+ if (lastPredicate.permissive) return;
+
+ var action = lastPredicate.action;
+
+ ns.log(`[ABE] < ${lastRule.destinations}> ${lastPredicate} on ${req}\n${rs.name} rule:\n${lastRule}`);
+ if (silent || rs != abeRes.lastRuleset || lastPredicate.inclusion)
+ return;
+
+ if (lastRule.local && silentLoopback) {
+ let host = req.destinationURI.host;
+ if (host != "localhost" && host != "127.0.0.1" && req.destinationURI.port <= 0) {
+ // this should hugely reduce notifications for users of bogus hosts files,
+ // while keeping "interesting" notifications
+ let dnsr = DNS.getCached(host);
+ if (dnsr && dnsr.entries.indexOf("127.0.0.1") > -1)
+ return;
+ }
+ }
+
+ let browser = this.findBrowser(req.channel);
+ if (browser)
+ browser.ownerDocument.defaultView.noscriptOverlay
+ .notifyABE({
+ request: req,
+ action: action,
+ ruleset: rs,
+ lastRule: lastRule,
+ lastPredicate: lastPredicate,
+ browser: browser,
+ });
+ }, this);
+ },
+
+ get dummyPost() {
+ const v = Cc["@mozilla.org/io/string-input-stream;1"].createInstance();
+ v.setData("", 0);
+ this.__defineGetter__("dummyPost", function() { return v; });
+ return v;
+ },
+
+ getUnsafeRequest: function(browser) {
+ return ns.getExpando(browser, "unsafeRequest");
+ },
+ setUnsafeRequest: function(browser, request) {
+ return ns.setExpando(browser, "unsafeRequest", request);
+ },
+ attachUnsafeRequest: function(requestInfo) {
+ if (requestInfo.browser && !requestInfo.silent) {
+ this.setUnsafeRequest(requestInfo.browser, requestInfo.unsafeRequest);
+ }
+ },
+
+ unsafeReload: function(browser, start) {
+ ns.setExpando(browser, "unsafeReload", start);
+ if (start) {
+ const unsafeRequest = this.getUnsafeRequest(browser);
+ if (unsafeRequest) {
+ // should we figure out what to do with unsafeRequest.loadFlags?
+ var wn = browser.webNavigation;
+ if(unsafeRequest.window) {
+ // a subframe...
+ try {
+ wn = DOM.getDocShellForWindow(unsafeRequest.window);
+ } catch(ex) {
+ ns.dump(ex);
+ }
+ unsafeRequest.window = null;
+ }
+
+ wn.loadURI(unsafeRequest.URI.spec,
+ wn.LOAD_FLAGS_BYPASS_CACHE |
+ wn.LOAD_FLAGS_IS_REFRESH,
+ unsafeRequest.referrer, unsafeRequest.postData, null);
+ unsafeRequest.issued = true;
+ } else {
+ browser.reload();
+ }
+ }
+ return start;
+ },
+
+ isUnsafeReload: function(browser) {
+ return ns.getExpando(browser, "unsafeReload");
+ },
+
+ resetUntrustedReloadInfo: function(browser, channel) {
+ if (!browser) return;
+ var window = IOUtil.findWindow(channel);
+ try {
+ if (browser.contentWindow == window) {
+ if (ns.consoleDump) this.dump(channel, "Top level document, resetting former untrusted browser info");
+ this.setUntrustedReloadInfo(browser, false);
+ }
+ } catch (e) {
+ }
+ },
+ setUntrustedReloadInfo: function(browser, status) {
+ return ns.setExpando(browser, "untrustedReload", status);
+ },
+ getUntrustedReloadInfo: function(browser) {
+ return ns.getExpando(browser, "untrustedReload");
+ },
+
+ _listeners: [],
+ addCrossSiteListener(l) {
+ if (this._listeners.indexOf(l) === -1) {
+ this._listeners.push(l);
+ }
+ },
+ removeCrossSiteListener: function(l) {
+ var pos = this._listeners.indexOf(l);
+ if (pos > -1) this._listeners.splice(pos);
+ },
+
+ onCrossSiteRequest: function(channel, origin, browser) {
+ for (var l of this._listeners) {
+ l.onCrossSiteRequest(channel, origin, browser, this);
+ }
+ },
+
+ isHome: function(url) {
+ return url instanceof Ci.nsIURL &&
+ this.getHomes().some(function(urlSpec) {
+ try {
+ return !url.getRelativeSpec(IOUtil.newURI(urlSpec));
+ } catch(e) {}
+ return false;
+ });
+ },
+ getHomes: function(pref) {
+ var homes;
+ try {
+ homes = ns.prefService.getComplexValue(pref || "browser.startup.homepage",
+ Ci.nsIPrefLocalizedString).data;
+ } catch (e) {
+ return pref ? [] : this.getHomes("browser.startup.homepage.override");
+ }
+ return homes ? homes.split("|") : [];
+ },
+
+ PAYPAL_BUTTON_RX: /^https:\/\/www\.paypal\.com\/(?:[\w\-]+\/)?cgi-bin\/webscr\b/,
+
+ filterXSS: function(abeReq) {
+
+ const channel = abeReq.channel;
+
+ let reqData = ns.reqData(channel);
+ delete reqData.xssChecked; // remove redirected info
+
+ const url = abeReq.destinationURI;
+ const originalSpec = abeReq.destination;
+
+
+ if (this.noscriptReload == originalSpec) {
+ // fast cache route for NoScript-triggered reloads
+ this.noscriptReload = null;
+ try {
+ if (ns.consoleDump) {
+ this.dump(channel, "Fast reload, original flags: " +
+ channel.loadFlags + ", " + (channel.loadGroup && channel.loadGroup.loadFlags));
+ }
+ channel.loadFlags = (channel.loadFlags & ~Ci.nsIChannel.VALIDATE_ALWAYS) |
+ Ci.nsIChannel.LOAD_FROM_CACHE | Ci.nsIChannel.VALIDATE_NEVER;
+ if (channel.loadGroup) {
+ channel.loadGroup.loadFlags = (channel.loadGroup.loadFlags & ~Ci.nsIChannel.VALIDATE_ALWAYS) |
+ Ci.nsIChannel.LOAD_FROM_CACHE | Ci.nsIChannel.VALIDATE_NEVER;
+ }
+ if (ns.consoleDump) {
+ this.dump(channel, "Fast reload, new flags: " +
+ channel.loadFlags + ", " + (channel.loadGroup && channel.loadGroup.loadFlags));
+ }
+ } catch(e) {
+ // we may have a problem here due to something Firekeeper 0.2.11 started doing..
+ ns.dump(e);
+ }
+ }
+
+
+ let origin = abeReq.origin;
+ if (origin === "[System Principal]" &&
+ !(channel.loadFlags & (channel.VALIDATE_ALWAYS | channel.LOAD_BYPASS_SERVICE_WORKER))) {
+ return; // System principal but this is not a reload or a navbar load
+ }
+
+ let originSite = null,
+ browser = this.findBrowser(channel),
+ window = null,
+ untrustedReload = false;
+
+ if (!origin) {
+ if ((channel instanceof Ci.nsIHttpChannelInternal) && channel.documentURI) {
+ if (originalSpec === channel.documentURI.spec) {
+ // check untrusted reload
+ if (!this.getUntrustedReloadInfo(browser)) {
+ if (ns.consoleDump) this.dump(channel, "Trusted reload");
+ return;
+ }
+ origin = originSite = "";
+ untrustedReload = true;
+ if (ns.consoleDump) this.dump(channel, "Untrusted reload");
+ } else {
+ origin = channel.documentURI.spec;
+ if (ns.consoleDump) this.dump(channel, "ORIGIN (from channel.documentURI): " + origin);
+ }
+ } else {
+ if (ns.consoleDump) this.dump(channel, "***** NO ORIGIN CAN BE INFERRED!!! *****");
+ }
+ } else {
+ if (channel.loadFlags & channel.LOAD_INITIAL_DOCUMENT_URI &&
+ channel.originalURI.spec == url.spec &&
+ !reqData.XSS) {
+ // clean up after user action
+ window = window || abeReq.window;
+ this.resetUntrustedReloadInfo(browser, channel);
+ var unsafeRequest = this.getUnsafeRequest(browser);
+ if (unsafeRequest && unsafeRequest.URI.spec != channel.originalURI.spec &&
+ (!window || window == window.top || window == unsafeRequest.window)) {
+ this.setUnsafeRequest(browser, null);
+ }
+ } else origin = origin.replace(/^view-source:/, '');
+ if (ns.consoleDump) this.dump(channel, "ORIGIN: " + origin);
+ }
+
+ const su = SiteUtils;
+ originSite = originSite || su.getSite(origin) || '';
+
+ let host = url.host;
+ if (host[host.length - 1] == "." && ns.getPref("canonicalFQDN", true)) {
+ try {
+ if (IOUtil.canDoDNS(channel))
+ channel.URI.host = DNS.resolve(host, 2).canonicalName;
+ if (ns.consoleDump) ns.dump("Resolving FQDN " + host);
+ } catch(ex) {
+ this.dump(channel, ex);
+ }
+ }
+
+ let targetSite;
+ const globalJS = ns.globalJS;
+ let trustedTarget = globalJS;
+ if(!trustedTarget) {
+ window = window || abeReq.window;
+ if(ns.autoAllow) {
+ if (window && window == window.top || channel.loadInfo && (channel.loadInfo.externalContentPolicyType || channel.loadInfo.contentPolicyType) === 6) {
+ targetSite = ns.getQuickSite(originalSpec, ns.autoAllow);
+ if(targetSite && !ns.isJSEnabled(targetSite, window)) {
+ ns.autoTemp(targetSite);
+ }
+ targetSite = su.getSite(originalSpec);
+ }
+ }
+ if(!trustedTarget) {
+ targetSite = su.getSite(originalSpec);
+ trustedTarget = ns.isJSEnabled(targetSite, window);
+ if(!trustedTarget) {
+ if (ns.checkShorthands(targetSite)) {
+ ns.autoTemp(targetSite);
+ trustedTarget = true;
+ } else {
+ ns.recordBlocked(targetSite, originSite);
+ }
+ }
+ }
+ }
+
+ if (!(origin || (window = abeReq.window))) {
+ if (ns.consoleDump) this.dump(channel, "-- This channel doesn't belong to any window/origin: internal browser or extension request, skipping. --");
+ return;
+ }
+
+ if (!targetSite) targetSite = su.getSite(originalSpec);
+
+ // noscript.injectionCheck about:config option adds first-line
+ // detection for XSS injections in GET requests originated by
+ // whitelisted sites and landing on top level windows. Value can be:
+ // 0 - never check
+ // 1 - check cross-site requests from temporary allowed sites
+ // 2 - check every cross-site request (default)
+ // 3 - check every request
+
+ let injectionCheck = ns.injectionCheck;
+
+ if (originSite == targetSite) {
+ if (injectionCheck < 3) return; // same origin, fast return
+ } else {
+ this.onCrossSiteRequest(channel, origin, browser);
+ }
+
+ if (this.callback && this.callback(channel, origin)) return;
+
+ /*
+ // uncomment me if you want the "old" behavior of checking only script-enabled targets
+ if (!trustedTarget) {
+ if (InjectionChecker.checkNoscript(InjectionChecker.urlUnescape(originalSpec)) && ns.getPref("injectionCheckHTML", true)) {
+ if (ns.consoleDump) this.dump(channel, "JavaScript disabled target positive to HTML injection check!");
+ } else {
+ if (ns.consoleDump) this.dump(channel, "Target is not Javascript-enabled, skipping XSS checks.");
+ return;
+ }
+ }
+ */
+
+ // fast return if nothing to do here
+ if (!(ns.filterXPost || ns.filterXGet)) return;
+
+ if (!abeReq.external && this.isUnsafeReload(browser)) {
+ if (ns.consoleDump) this.dump(channel, "UNSAFE RELOAD of [" + originalSpec +"] from [" + origin + "], SKIP");
+ return;
+ }
+
+ let unescapedSpec = unescape(originalSpec);
+
+ if (ns.filterXExceptions) {
+ try {
+ if (ns.filterXExceptions.test(unescapedSpec) &&
+ !this.isBadException(host)
+ ) {
+ // "safe" xss target exception
+ if (ns.consoleDump) this.dump(channel, "Safe target according to filterXExceptions: " + ns.filterXExceptions.toString());
+ return;
+ }
+
+ if (ns.filterXExceptions.test("@" + unescape(origin))) {
+ if (ns.consoleDump) this.dump(channel, "Safe origin according to filterXExceptions: " + ns.filterXExceptions.toString());
+ return;
+ }
+ } catch(e) {}
+ }
+
+ if (abeReq.external && /^https?:\/\/msdn\.microsoft\.com\/query\/[^<]+$/.test(unescapedSpec)) {
+ return; // MSDN from Visual Studio
+ }
+
+ if (originSite) { // specific exceptions
+
+ if (/^about:(?!blank)/.test(originSite))
+ return; // any about: URL except about:blank
+
+ if (/^https?:\/\/my\.ebay\.(?:\w{2,3}|co\.uk)\/ws\/eBayISAPI\.dll\?[^<'"%]*CurrentPage=MyeBayAllFavorites\b[^<'"%]*$/.test(origin) &&
+ /^https?:\/\/www\.ebay\.(?:\w{2,3}|co\.uk)\/sch\/i\.html\?[^<'"]*$/.test(unescapedSpec) &&
+ url.scheme === abeReq.originURI.scheme &&
+ ns.getBaseDomain(ns.getDomain(url)) === ns.getBaseDomain(ns.getDomain(abeReq.originURI)) &&
+ ns.getPref("filterXException.ebay")) {
+ if (ns.consoleDump) this.dump(channel, "Ebay exception");
+ return;
+ }
+
+ if (/^https?:\/\/(?:[^/]+\.)photobucket\.com$/.test(originSite) &&
+ /^https?:\/\/(?:[^/]+\.)photobucket\.com\/[^<]*$/.test(unescapedSpec) &&
+ url.scheme === abeReq.originURI.scheme &&
+ ns.getBaseDomain(ns.getDomain(url)) === ns.getBaseDomain(ns.getDomain(abeReq.originURI)) &&
+ ns.getPref("filterXException.photobucket")) {
+ if (ns.consoleDump) this.dump(channel, "Photobucket exception");
+ return;
+ }
+
+ if (originSite === "https://www.youtube.com" &&
+ /^https:\/\/(?:plus\.googleapis|apis\.google)\.com\/[\w/]+\/widget\/render\/comments\?/.test(originalSpec) &&
+ ns.getPref("filterXExceptions.yt_comments")
+ ) {
+ if (ns.consoleDump) this.dump(channel, "YouTube comments exception");
+ return;
+ }
+
+ if (channel.requestMethod == "POST") {
+
+ if (originSite === "https://sso.post.ch" && targetSite === "https://app.swisspost.ch") {
+ return;
+ }
+
+ if (originSite === "https://twitter.com" && /^https:\/\/.*\.twitter\.com$/.test(targetSite)) {
+ return;
+ }
+
+ {
+ let rx = /^https:\/\/(?:[a-z]+\.)?unionbank\.com$/;
+ if (rx.test(originSite) && rx.test(targetSite)) {
+ return;
+ }
+ }
+
+ if (/^https?:\/\/csr\.ebay\.(?:\w{2,3}|co\.uk)\/cse\/start\.jsf$/.test(origin) &&
+ /^https?:\/\/msa-lfn\.ebay\.(?:\w{2,3}|co\.uk)\/ws\/eBayISAPI\.dll\?[^<'"%]*$/.test(unescapedSpec) &&
+ url.scheme === abeReq.originURI.scheme &&
+ ns.getPref("filterXException.ebay")) {
+ if (ns.consoleDump) this.dump(channel, "Ebay exception");
+ return;
+ }
+
+ if (/^https:\/\/(?:cap\.securecode\.com|www\.securesuite\.net|(?:.*?\.)?firstdata\.(?:l[tv]|com))$/.test(origin) &&
+ ns.getPref("filterXException.visa")) {
+ if (ns.consoleDump) this.dump(channel, "Verified by Visa exception");
+ return;
+ }
+
+ if (/\.verizon\.com$/.test(originSite) &&
+ /^https:\/\/signin\.verizon\.com\/sso\/authsso\/forumLogin\.jsp$/.test(originalSpec) &&
+ ns.getPref("filterXExceptions.verizon")) {
+ if (ns.consoleDump) this.dump(channel, "Verizon login exception");
+ return;
+ }
+
+ if (/^https?:\/\/mail\.lycos\.com\/lycos\/mail\/MailCompose\.lycos$/.test(origin) &&
+ /\.lycosmail\.lycos\.com$/.test(targetSite) &&
+ ns.getPref("filterXExceptions.lycosmail")) {
+ if (ns.consoleDump) this.dump(channel, "Lycos Mail exception");
+ return;
+ }
+
+ if (/\.livejournal\.com$/.test(originSite) &&
+ /^https?:\/\/www\.livejournal\.com\/talkpost_do\.bml$/.test(originalSpec) &&
+ ns.getPref("filterXExceptions.livejournal")) {
+ if (ns.consoleDump) this.dump(channel, "Livejournal comments exception");
+ return;
+ }
+
+ if (originSite == "https://ssl.rapidshare.com" &&
+ ns.getBaseDomain(ns.getDomain(targetSite)) == "rapidshare.com") {
+ if (ns.consoleDump) this.dump(channel, "Rapidshare upload exception");
+ return;
+ }
+
+ if (originSite == "http://wm.letitbit.net" &&
+ /^http:\/\/http\.letitbit\.net:81\/cgi-bin\/multi\/upload\.cgi\?/.test(originalSpec) &&
+ ns.getPref("filterXExceptions.letitibit")
+ ) {
+ if (ns.consoleDump) this.dump(channel, "letitbit.net upload exception");
+ return;
+ }
+
+ if (/\.deviantart\.com$/.test(originSite) &&
+ /^http:\/\/my\.deviantart\.com\/journal\/update\b/.test(originalSpec) &&
+ ns.getPref("filterXExceptions.deviantart")
+ ) {
+ if (ns.consoleDump) this.dump(channel, "deviantart.com journal post exception");
+ return;
+ }
+
+ if (originSite == "https://www.mymedicare.gov" &&
+ targetSite == "https://myporal.medicare.gov" &&
+ ns.getPref("filterXExceptions.medicare")
+ ) {
+ if (ns.consoleDump) this.dump(channel, "mymedicare.gov exception");
+ return;
+ }
+
+ if (/^https?:\/\/(?:draft|www)\.blogger\.com\/template-editor\.g\?/.test(origin) &&
+ /^https?:\/\/[\w\-]+\.blogspot\.com\/b\/preview\?/.test(originalSpec) &&
+ ns.getPref("filterXExceptions.blogspot")
+ ) {
+ if (ns.consoleDump) this.dump(channel, "blogspot.com template preview exception");
+ return;
+ }
+
+ if (/^https?:\/\/www\.readability\.com\/articles\/queue$/.test(originalSpec) &&
+ ns.getPref("filterXExceptions.readability")) {
+ if (ns.consoleDump) this.dump(channel, "Readability exception");
+ return;
+ }
+
+ if (/^https?:\/\/pdf\.printfriendly\.com\/pdfs\/make$/.test(originalSpec) &&
+ ns.getPref("filterXExceptions.printfriendly")) {
+ if (ns.consoleDump) this.dump(channel, "Printfriendly exception");
+ return;
+ }
+
+ }
+
+ }
+
+
+
+ let originalAttempt;
+ let postInjection = false;
+
+ window = window || abeReq.window;
+
+ // neutralize window.name-based attack
+ if (window && window.name) {
+
+ if (ns.compatEvernote && window.frameElement && window.name.indexOf("iframe") > 0 &&
+ /^https?:\/\/(?:[a-z]+\.)*evernote\.com\/clip\.action$/.test(originalSpec) &&
+ channel.requestMethod == "POST") {
+ // Evernote Web Clipper hack
+ window.frameElement.addEventListener("load", ns.compatEvernote.onload, false);
+ if (ns.consoleDump) this.dump(channel, "Evernote frame detected (noscript.compat.evernote)");
+ return;
+ }
+ }
+
+
+ if (!/^(?:https:\/\/.*\.nwolb\.com){2}$/.test(originSite + targetSite)) {
+ reqData.checkWindowName = true;
+ } else {
+ this.dump(channel, "nwolb.com window.name check exception.");
+ }
+
+ let focusedBrowserWin = DOM.mostRecentBrowserWindow;
+ let trustedOrigin = globalJS || ns.isJSEnabled(originSite, focusedBrowserWin && focusedBrowserWin.content) ||
+ !origin ||
+ // we consider null origin as "trusted" (i.e. we check for injections but
+ // don't strip POST unconditionally) to make some extensions (e.g. Google Gears)
+ // work. For dangerous edge cases we should have moz-null-principal: now, anyway.
+ origin.substring(0, 5) == "file:";
+
+ let originDomain = ns.getDomain(originSite),
+ targetDomain = ns.getDomain(url);
+
+ if (trustedOrigin) {
+
+ if (origin &&
+ (
+ /^https?:\/\/(?:[^\/]+.)?facebook\.com\/[\w\.\-\/]+fbml\.php$/.test(originalSpec) && channel.requestMethod == "POST" ||
+ /^https?:\/\/www\.facebook\.com\/plugins\/serverfbml.php\?/.test(originalSpec) ||
+ /^https?:\/\/api\.connect\.facebook\.com$/.test(originSite)
+
+ ) &&
+ ns.getPref("filterXExceptions.fbconnect")) {
+ if (ns.consoleDump) this.dump(channel, 'Facebook connect exception');
+ return;
+ }
+
+
+ this.resetUntrustedReloadInfo(browser, channel);
+
+ // here we exceptionally consider same site also https->http with same domain
+
+ if (injectionCheck < 3 && originSite && abeReq.originURI.schemeIs("https")) {
+
+ if (targetDomain === originDomain || ns.getBaseDomain(originDomain) === ns.getBaseDomain(targetDomain)) {
+ this.dump(channel, "Same base domain with HTTPS origin");
+ return;
+ }
+ }
+ }
+
+ let stripPost = trustedTarget && originDomain && !trustedOrigin && ns.filterXPost &&
+ ns.getBaseDomain(originDomain) !== ns.getBaseDomain(targetDomain);
+
+ // check for injections
+
+ let injectionAttempt = injectionCheck && (injectionCheck > 1 || !trustedOrigin || ns.isTemp(originSite)) &&
+ (!window || ns.injectionCheckSubframes || window == window.top);
+
+
+
+ if (injectionAttempt) {
+ let skipArr, skipRx;
+ let isPaypal = this.PAYPAL_BUTTON_RX.test(originalSpec);
+
+ if (isPaypal) {
+ stripPost = false;
+ // Paypal buttons encrypted parameter causes a DOS, strip it out
+ skipArr = ['encrypted'];
+ } else if ("https://secure.przelewy24.pl/" === targetSite) {
+ stripPost = true;
+ } else if (/\.adnxs\.com$/.test(originSite) && /\.adnxs\.com$/.test(targetSite)) {
+ skipArr = ['udj'];
+ } else if (/^https?:\/\/www\.mendeley\.com\/import\/bookmarklet\/$/.test(originalSpec)) {
+ skipArr = ['html'];
+ } else if (/^https?:\/\/[\w\-\.]+\/talkpost_do(?:\.bml)?$/.test(originalSpec) &&
+ ns.getBaseDomain(ns.getDomain(originalSpec)) == ns.getBaseDomain(ns.getDomain(originSite)) &&
+ ns.getPref("filterXExceptions.livejournal")) {
+ if (ns.consoleDump) this.dump(channel, "Livejournal-like comments exception");
+ skipArr = ['body'];
+ } else if (url.ref && trustedOrigin &&
+ (/^https?:\/\/api\.facebook\.com\//.test(origin) && ns.getPref("filterXExceptions.fbconnect") ||
+ /^https:\/\/tbpl\.mozilla\.org\//.test(origin) || // work-around for hg reftest DOS
+ /^https:\/\/[^\/]+\.googleusercontent\.com\/gadgets\/ifr\?/.test(originalSpec) && ns.getPref("filterXExceptions.ggadgets") // Google gadgets
+ )) {
+ skipRx = /#[^#]+$/; // remove receiver's hash
+ } else if (/^https?:\/\/apps\.facebook\.com\//.test(origin) && ns.getPref("filterXExceptions.fbconnect")) {
+ skipRx = /&invite_url=javascript[^&]+/; // Zynga stuff
+ } else if (/^https?:\/\/l\.yimg\.com\/j\/static\/frame\?e=/.test(originalSpec) &&
+ /\.yahoo\.com$/.test(originSite) &&
+ ns.getPref("filterXExceptions.yahoo")) {
+ skipArr = ['e'];
+ if (ns.consoleDump) this.dump(channel, "Yahoo exception");
+ } else if (/^https?:\/\/wpcomwidgets\.com\/\?/.test(originalSpec)) {
+ skipArr = ["_data"];
+ } else if (/^https:\/\/docs\.google\.com\/picker\?/.test(originalSpec)) {
+ skipArr = ["nav", "pp"];
+ } else if (/^https:\/\/.*[\?&]scope=/.test(originalSpec)) {
+ skipRx = /[\?&]scope=[+\w]+(?=&|$)/;
+ }
+ if (skipArr) {
+ skipRx = new RegExp("(?:^|[&?])(?:" + skipArr.join('|') + ")=[^&]+", "g");
+ }
+
+
+ let injectionChecker = ns.injectionChecker;
+
+ injectionChecker.reset();
+
+ if (!stripPost)
+ stripPost = postInjection =
+ ns.filterXPost &&
+ (!origin || originSite != "chrome:") &&
+ channel.requestMethod == "POST" && injectionChecker.checkPost(channel, skipArr);
+
+ let protectName = injectionChecker.nameAssignment;
+
+ injectionAttempt = ns.filterXGet && injectionChecker.checkURL(
+ skipRx ? originalSpec.replace(skipRx, '') : originalSpec);
+
+ reqData.protectName = (protectName = (protectName || injectionChecker.nameAssignment));
+
+ if (ns.consoleDump) {
+ if (injectionAttempt) this.dump(channel, "Detected injection attempt at level " + injectionCheck);
+ if (postInjection) this.dump(channel, "Detected POST injection attempt at level " + injectionCheck);
+ if (protectName) this.dump(channel, "Name assignment detected, gonna protect window.name");
+ }
+ }
+
+ reqData.xssChecked = true;
+
+ if (trustedOrigin && !(injectionAttempt || stripPost))
+ return;
+
+ if (untrustedReload && browser) {
+ this.resetUntrustedReloadInfo(browser, channel);
+ }
+
+
+ // -- DANGER ZONE --
+
+ let requestInfo = new RequestInfo(channel, url, origin, window);
+
+ // transform upload requests into no-data GETs
+ if (ns.filterXPost && stripPost &&
+ (channel instanceof Ci.nsIUploadChannel) && channel.uploadStream
+ ) {
+ try {
+ channel.requestMethod = "GET";
+ } catch (e) {}
+ requestInfo.unsafeRequest.postData = channel.uploadStream;
+ channel.setUploadStream(this.dummyUpload, "", -1);
+ this.notify(this.addXssInfo(requestInfo, {
+ reason: "filterXPost",
+ originalAttempt: originalSpec + (postInjection ? "###DATA###" + postInjection : ""),
+ silent: untrustedReload
+ }));
+
+ this.attachUnsafeRequest(requestInfo);
+ }
+
+ if (!(injectionAttempt || postInjection)) return;
+
+ if (ns.filterXGet && ns.filterXGetRx) {
+ var changes = null;
+ var xsan = ns.createXSanitizer();
+ // sanitize referrer
+ if (channel.referrer && channel.referrer.spec) {
+ originalAttempt = channel.referrer.spec;
+ xsan.brutal = /'"</.test(Entities.convertAll(InjectionChecker.urlUnescape(originalAttempt)));
+ try {
+ if (channel.referrer instanceof Ci.nsIURL) {
+ changes = xsan.sanitizeURL(channel.referrer);
+ } else {
+ channel.referrer.spec = xsan.sanitizeURIComponent(originalAttempt);
+ }
+ } catch(e) {
+ this.dump("Failed sanitizing referrer " + channel.referrer.spec + ", " + e);
+ channel.referrer.spec = "";
+ }
+ try {
+ if (!changes) {
+ changes = {
+ minor: !channel.referrer.spec ||
+ unescape(originalAttempt) != unescape(channel.referrer.spec)
+ };
+ }
+ if (changes.minor) {
+ channel.referrer = channel.referrer.clone();
+ this.notify(this.addXssInfo(requestInfo, {
+ reason: "filterXGetRef",
+ originalAttempt: originalSpec + " (REF: " + originalAttempt + ")",
+ silent: !postInjection,
+ sanitizedURI: channel.referrer
+ }));
+ }
+ } catch(e) {
+ this.dump("Failed notifying referrer sanitization: " + channel.referrer.spec + ", " + e);
+ channel.referrer.spec = "";
+ channel.referrer = channel.referrer.clone();
+ }
+ }
+
+ originalAttempt = originalSpec;
+
+ let newURI = url.clone();
+
+ if (injectionAttempt) {
+ xsan.brutal = injectionAttempt;
+ changes = xsan.sanitizeURL(newURI);
+ if (changes.minor) {
+ this.notify(this.addXssInfo(requestInfo, {
+ reason: "filterXGet",
+ originalAttempt: originalAttempt,
+ sanitizedURI: newURI,
+ silent: !(changes.major || postInjection)
+ }));
+ }
+ if (newURI.spec != url.spec) {
+ if (!abeReq.replace(null, newURI)) {
+ this.proxyHack(channel);
+ url.spec = newURI.spec;
+ }
+ }
+ }
+ }
+
+ if (requestInfo.xssMaybe) {
+ // avoid surprises from history & cache
+ if (channel instanceof Ci.nsICachingChannel) {
+
+ const CACHE_FLAGS = channel.LOAD_FROM_CACHE |
+ channel.VALIDATE_NEVER |
+ channel.LOAD_ONLY_FROM_CACHE;
+
+ channel.loadFlags = channel.loadFlags & ~CACHE_FLAGS | channel.LOAD_BYPASS_CACHE;
+ if (this.consoleDump) this.dump(channel, "SKIPPING CACHE");
+ }
+
+ this.attachUnsafeRequest(requestInfo);
+ }
+
+
+ },
+
+
+
+ isBadException: function(host) {
+ // TLD check for Google search
+ let m = host.match(/\bgoogle\.((?:[a-z]{1,3}\.)?[a-z]+)$/i);
+ return m && ns.getPublicSuffix(host) != m[1];
+ },
+
+
+
+ proxyHack: function(channel) {
+ // Work-around for channel.URI not being used directly here:
+ // http://mxr.mozilla.org/mozilla/source/netwerk/protocol/http/src/nsHttpChannel.cpp#504
+
+ var proxyInfo = IOUtil.getProxyInfo(channel);
+ if (proxyInfo && proxyInfo.type == "http") {
+ if (channel.URI.userPass === "") {
+ channel.URI.userPass = "xss:xss";
+ // resetting this bit will avoid auth confirmation prompt
+ channel.loadFlags = channel.loadFlags & ~channel.LOAD_INITIAL_DOCUMENT_URI;
+ }
+ }
+ },
+
+ abortChannel: function(channel, reason) {
+ let originURI = ABERequest.getOrigin(channel);
+ let requestInfo = this.addXssInfo(new RequestInfo(channel), {
+ reason: reason || "filterXGet",
+ originalAttempt: channel.name,
+ origin: originURI && originURI.spec || "",
+ silent: false,
+ });
+ this.abort(requestInfo);
+ this.attachUnsafeRequest(requestInfo);
+ },
+
+ abort: function(requestInfo) {
+ var channel = requestInfo.channel;
+
+ if (channel instanceof Ci.nsIRequest)
+ IOUtil.abort(channel);
+
+ if (requestInfo.browser) {
+ requestInfo.browser.stop(requestInfo.browser.STOP_ALL);
+ }
+ this.dump(channel, "Aborted - " + requestInfo.reason);
+
+ this.notify(requestInfo);
+ },
+
+ mergeDefaults: function(o1, o2) {
+ for (let p in o2) {
+ if (!(p in o1)) o1[p] = o2[p];
+ }
+ return o1;
+ },
+
+ addXssInfo: function(requestInfo, xssInfo) {
+ try {
+ requestInfo.window = requestInfo.window || IOUtil.findWindow(requestInfo.channel);
+ requestInfo.browser = requestInfo.browser || IOUtil.findBrowser(requestInfo.channel);
+ } catch(e) {}
+ requestInfo.xssMaybe = true;
+ return this.mergeDefaults(xssInfo, requestInfo);
+ },
+
+ notify: function(requestInfo) {
+ var msg = "[NoScript XSS] " + ns.getString("xss.reason." + requestInfo.reason, [
+ requestInfo.originalAttempt || "N/A",
+ requestInfo.unsafeRequest && requestInfo.unsafeRequest.origin || "",
+ requestInfo.sanitizedURI && requestInfo.sanitizedURI.spec || ""
+ ]);
+ this.dump(requestInfo.channel, "Notifying " + msg + "\n\n\n");
+ ns.log(msg);
+ try {
+ let sync = requestInfo.channel.status !== 0;
+ let loadInfo = requestInfo.channel.loadInfo;
+ let cpType = loadInfo && (loadInfo.externalContentPolicyType || loadInfo.contentPolicyType);
+ if (!cpType && requestInfo.window) {
+ cpType = requestInfo.window === requestInfo.window.top ? 6 : 7;
+ }
+ if (requestInfo.silent || !(cpType === 6 || cpType === 7) || !ns.getPref("xss.notify", true))
+ return;
+ if(cpType !== 6) {
+ // subframe
+
+ var cur = this.getUnsafeRequest(requestInfo.browser);
+ if(cur && !cur.issued) return;
+
+ requestInfo.unsafeRequest.window = requestInfo.window;
+ this.observeSubframeXSS(requestInfo.originalAttempt, requestInfo.unsafeRequest);
+
+ if(!ns.getPref("xss.notify.subframes", true))
+ return;
+
+ sync = true;
+ }
+
+ if (sync) {
+ let overlay = ns.findOverlay(requestInfo.browser);
+ if(overlay) overlay.notifyXSS(requestInfo);
+ }
+
+ requestInfo.wrappedJSObject = requestInfo;
+ ns.reqData(requestInfo.channel).XSS = requestInfo;
+ } catch(e) {
+ dump(e + "\n");
+ }
+ },
+
+ observeSubframeXSS: function(url, unsafeRequest) {
+ unsafeRequest.window.addEventListener("unload", function(ev) {
+ var w = ev.currentTarget;
+ if(w.location.href != url) return;
+ w.removeEventListener("unload", arguments.callee, false);
+ unsafeRequest.window = null;
+ }, false);
+ },
+
+
+ findBrowser: function(channel) {
+ return IOUtil.findBrowser(channel);
+ },
+
+ dump: function(channel, msg) {
+ if (!(ns.consoleDump & LOG_XSS_FILTER)) return;
+ dump("[NoScript] ");
+ dump((channel.URI && channel.URI.spec) || "null URI?" );
+ if (channel.originalURI && channel.originalURI.spec != channel.URI.spec) {
+ dump(" (" + channel.originalURI.spec + ")");
+ }
+ dump(" *** ");
+ dump(msg);
+ dump("\n");
+ }
+
+
+};
+
+function RequestInfo(channel, url, origin, window) {
+ this.channel = channel;
+ if (!url) url = channel.URI;
+ this.sanitizedURI = url;
+ this.window = window || IOUtil.findWindow(channel);
+ if (!origin) {
+ let originURI = ABERequest.getOrigin(channel);
+ origin = originURI && originURI.spec || "???";
+ }
+ this.unsafeRequest = {
+ URI: url.clone(),
+ postData: null,
+ referrer: channel.referrer && channel.referrer.clone(),
+ origin: origin,
+ loadFlags: channel.loadFlags,
+ issued: false,
+ window: null
+ };
+}
+RequestInfo.prototype = {
+ xssMaybe: false
+};
+
+
+function DOSChecker(request, canSpin) {
+ this.request = request;
+ this.canSpin = canSpin;
+ Thread.asap(this.check, this);
+}
+
+DOSChecker.abort = function(req, info) {
+ if (req) IOUtil.abort(("channel" in req) ? req.channel : req, true);
+ ns.log("[NoScript DOS] Aborted potential DOS attempt: " +
+ ( ("name" in req) ? req.name : req ) +
+ "\n" + (info || new Error().stack));
+};
+
+DOSChecker.prototype = {
+ done: false,
+ lastClosure: null,
+ run: function(closure, self) {
+ this.done = false;
+ this.lastClosure = closure;
+ try {
+ return self ? closure.apply(self) : closure();
+ } finally {
+ this.done = true;
+ }
+ },
+ check: function() {
+ MaxRunTime.restore();
+
+ if (!(this.done || this.canSpin && Thread.activeLoops))
+ DOSChecker.abort(this.request, (this.lastClosure && this.lastClosure.toSource()));
+ }
+};
+
+var MaxRunTime = {
+ branch: Cc["@mozilla.org/preferences-service;1"]
+ .getService(Ci.nsIPrefService).getBranch("dom."),
+ prefs: ["max_script_run_time", "max_chrome_script_run_time"],
+ stored: [],
+ increase: function(v) {
+ let prefs = this.prefs, stored = this.stored;
+ for (let j = prefs.length; j-- > 0;) {
+ let cur, pref = prefs[j];
+ try {
+ cur = this.branch.getIntPref(pref);
+ } catch(e) {
+ cur = -1;
+ }
+ if (cur <= 0 || cur >= v) return;
+ if (typeof stored[j] === "undefined") try {
+ stored[j] = cur;
+ } catch(e) {}
+ this.branch.setIntPref(pref, v);
+ }
+ },
+ restore: function() {
+ let prefs = this.prefs, stored = this.stored;
+ for (let j = stored.length; j-- > 0;) {
+ this.branch.setIntPref(prefs[j], stored[j]);
+ }
+ stored.length = 0;
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/Restartless.jsm b/extensions/noscript/chrome/content/noscript/Restartless.jsm
new file mode 100644
index 0000000..ba5ab0a
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Restartless.jsm
@@ -0,0 +1,248 @@
+var EXPORTED_SYMBOLS = ["startup", "shutdown", "upgrade", "loadIntoWindow", "unloadFromWindow"];
+var { utils: Cu, interfaces: Ci } = Components;
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import(`chrome://noscript/content/importer.jsm`);
+
+Services.scriptloader.loadSubScript(NO_CACHE("loader.js"), this);
+
+function loadPrefs(branch, uriOrFile, filter = null) {
+ try {
+ let setPref = (name, value) => {
+ try {
+ switch (typeof value) {
+ case "boolean":
+ branch.setBoolPref(name, value);
+ break;
+
+ case "number":
+ branch.setIntPref(name, value);
+ break;
+
+ case "string":
+ COMPAT.setStringPref(branch, name, value);
+ break;
+ }
+ } catch (e) {
+ Cu.reportError(`NoScript could not set default pref value for ${name}: ${e}`);
+ }
+ };
+
+ if (typeof uriOrFile === "string") {
+ let uri = uriOrFile;
+ let pref = filter ? (name, value) => filter(name, value) && setPref(name, value)
+ : setPref;
+ Services.scriptloader.loadSubScript(uri, { pref });
+ } else {
+ INCLUDE("IO");
+ let file = uriOrFile;
+ let prefJSON = JSON.parse(`[${IO.readFile(file).replace(/^[^p].*/mg, '')
+ .replace(/^pref\((.*)\);$/mg, "[$1],")
+ .replace(/,\s*$/, '')}]`);
+ if (filter) prefJSON = prefJSON.filter(([name, value]) => filter(name, value));
+ prefJSON.forEach(([name, value]) => setPref(name, value));
+ }
+ } catch (err) {
+ Cu.reportError(err);
+ }
+}
+
+function loadDefaultPrefs(xpiURI) {
+ let branch = Services.prefs.getDefaultBranch("");
+ let seen = null;
+ let overrides = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
+ overrides.append("preferences");
+ if (overrides.exists() && overrides.isDirectory()) {
+ seen = new Set();
+ let filter = name => name.startsWith("noscript.") && seen.add(name);
+ for (let entries = overrides.directoryEntries, file; (file = entries.getNext()) instanceof Ci.nsIFile;) {
+ if (file.path.endsWith(".js")) {
+ loadPrefs(branch, file, filter);
+ }
+ }
+ }
+ let filter = seen && seen.size ? name => !seen.has(name) : null;
+ loadPrefs(branch, `${xpiURI}/defaults/preferences/noscript.js`, filter);
+}
+
+function startup(addonData, browserStartup) {
+
+ loadDefaultPrefs(addonData.resourceURI.spec);
+
+ INCLUDE("Main");
+ Main.bootstrap();
+
+
+ Main.init();
+ if (Main.webExt && addonData.webExtension) {
+ Main.webExt.init(addonData.webExtension);
+ }
+ Main.checkVersion();
+}
+
+function shutdown(addonData) {
+ if (CustomizableUI && widgetTemplate) {
+ try {
+ CustomizableUI.destroyWidget(widgetTemplate.id);
+ } catch (e) {
+ }
+ }
+ Main.shutdown();
+ UNLOAD_ALL();
+}
+
+
+try {
+ Cu.import("resource:///modules/CustomizableUI.jsm");
+} catch(e) {
+ var CustomizableUI = null;
+}
+var widgetTemplate = null;
+var overlayURL = NO_CACHE(`noscriptOverlay-noStatusBar.xul`);
+
+function createWidgetTemplate(window, callback) {
+ let xhr = new window.XMLHttpRequest();
+ if (window.document.getElementById("status-bar")) {
+ overlayURL = overlayURL.replace("-noStatusBar", "");
+ }
+ xhr.open("GET", overlayURL);
+
+ try {
+ // work around to resolve overlay's XML entities despite the Tor Browser
+ let TOR_PREF = "extensions.torbutton.resource_and_chrome_uri_fingerprinting";
+ let torPrefValue = Services.prefs.getBoolPref(TOR_PREF);
+ let restorePref = () => Services.prefs.setBoolPref(TOR_PREF, torPrefValue);
+ for (let e of ["progress", "loadend"]) { // restore as early as possible (almost sync)
+ xhr.addEventListener(e, restorePref);
+ }
+ xhr.addEventListener("loadstart", () => {
+ Services.prefs.setBoolPref(TOR_PREF, true);
+ });
+ } catch (e) {
+ // no pref value, it doesn't seem to be a Tor Browser :)
+ }
+
+ xhr.addEventListener("load", () => {
+ createWidget(xhr.responseXML.getElementById("noscript-tbb"));
+ if (callback) callback();
+ });
+
+
+ xhr.send(null);
+}
+
+function createWidget(template) {
+ widgetTemplate = template;
+ if (CustomizableUI) {
+ CustomizableUI.createWidget({
+ id: widgetTemplate.id,
+ type: "custom",
+ onBuild(doc) {
+ return doc.importNode(widgetTemplate);
+ },
+ onCreated(node) {
+ let noscriptOverlay = node.ownerDocument.defaultView.noscriptOverlay;
+ if (noscriptOverlay) node.ownerDocument.defaultView.noscriptOverlay.initPopups();
+ }
+ });
+ }
+}
+
+
+function placeWidgetNoAustralis(document) {
+ let id = widgetTemplate.id;
+ let widget = document.getElementById(id) || document.importNode(widgetTemplate);
+ if (widget.parentNode) return;
+ let toolbar = document.querySelector(`toolbar[currentset*="${id}"],toolbar[currentset*=",${id},"],toolbar[currentset^="${id},"],toolbar[currentset=",${id}"]`);
+ if (toolbar) {
+ let currentSet = toolbar.getAttribute("currentset");
+ if (toolbar.currentSet !== currentSet) {
+ toolbar.currentSet = currentSet;
+ try {
+ document.defaultView.BrowserToolboxCustomizeDone(true);
+ } catch (e) {}
+ }
+ let items = currentSet.split(",");
+ let next = items.indexOf(id) + 1;
+ let nextNode = next > items.length ? null : document.getElementById(items[next]);
+ toolbar.insertBefore(widget, nextNode);
+ } else {
+ toolbar = document.querySelector("toolbar");
+ if (toolbar && toolbar.toolbox && toolbar.toolbox.palette) {
+ toolbar.toolbox.palette.appendChild(widget);
+ }
+ }
+}
+
+var overlayLoading = false;
+var overlayQueue = [];
+var overlaid = new WeakSet();
+function overlayNext() {
+ overlayLoading = false;
+ if (overlayQueue.length) {
+ let next = overlayQueue.shift();
+ Thread.asap(() => loadIntoWindow(next));
+ }
+}
+function loadIntoWindow(w, early = false) {
+ if (w.noscriptOverlay || typeof overlayQueue === "undefined") return;
+
+ if (overlayLoading) {
+ overlayQueue.push(w);
+ return;
+ }
+ overlayLoading = true;
+
+ if (!widgetTemplate) {
+ createWidgetTemplate(w, () => {
+ overlayLoading = false;
+ loadIntoWindow(w);
+ });
+ return;
+ }
+
+ try {
+ if (overlaid.has(w)) {
+ overlayNext();
+ return;
+ }
+ overlaid.add(w);
+ w.document.loadOverlay(overlayURL, {
+ observe() {
+ if (!early) {
+ if (CustomizableUI) {
+ let widget = w.document.getElementById(widgetTemplate.id);
+ if (widget) widget.hidden = false;
+ else {
+ Main.dump(`${widgetTemplate.id} not found!`);
+ CustomizableUI.ensureWidgetPlacedInWindow(widgetTemplate.id, w);
+ }
+ } else {
+ placeWidgetNoAustralis(w.document);
+ }
+
+ (function initWindow() {
+ if (w.noscriptOverlay) {
+ w.noscriptOverlay.listeners.onLoad();
+ } else {
+ w.setTimeout(initWindow, 300);
+ }
+ })();
+ }
+ Main.dump(`Overlay loaded ${early}, ${w.noscriptOverlay}`);
+ overlayNext();
+ }
+ });
+ } catch (e) {
+ Cu.reportError(e);
+ Cu.reportError(`Could not overlay ${w.location.href}`);
+ overlayNext();
+ }
+
+}
+
+
+function unloadFromWindow(w) {
+ if (w.noscriptOverlay) w.noscriptOverlay.listeners.onUnload();
+}
+
diff --git a/extensions/noscript/chrome/content/noscript/ScriptSurrogate.js b/extensions/noscript/chrome/content/noscript/ScriptSurrogate.js
new file mode 100644
index 0000000..7de5aad
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/ScriptSurrogate.js
@@ -0,0 +1,440 @@
+var ScriptSurrogate = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
+ JS_VERSION: "1.8",
+ enabled: true,
+ prefs: null,
+ sandbox: true,
+ sandboxInclusions: true,
+
+ get syntaxChecker() {
+ delete this.syntaxChecker;
+ return this.syntaxChecker = new SyntaxChecker(this.JS_VERSION);
+ },
+ get mappings() {
+ delete this.mappings;
+ this._init();
+ return this.mappings;
+ },
+
+
+ _init: function() {
+ this.prefs = ns.prefService.getBranch("noscript.surrogate.");
+ this._syncPrefs();
+ ns.onDisposal(() => { this.dispose(); });
+ },
+
+ _observingPrefs: false,
+ _syncPrefs: function() {
+ const prefs = this.prefs;
+
+ for (let p of ["enabled", "debug", "sandbox", "matchPrivileged"]) this[p] = prefs.getBoolPref(p);
+
+ this.sandboxInclusions = this.sandbox;
+
+ const map = {__proto__: null};
+ var key;
+ for (key of prefs.getChildList("", {})) {
+ this._parseMapping(prefs, key, map);
+ }
+
+ const mappings = {forPage: [], noScript: [], inclusion: [], before: [], after: [], all: map};
+
+ var mapping;
+ for (key in map) {
+ mapping = map[key];
+ if (mapping.forPage) mappings.forPage.push(mapping);
+ if (mapping.noScript) mappings.noScript.push(mapping);
+ else if (!mapping.forPage) {
+ if (!(mapping.before || mapping.after)) mappings.inclusion.push(mapping);
+ else {
+ if (mapping.before) mappings.before.push(mapping);
+ if (mapping.after) mappings.after.push(mapping);
+ }
+ }
+ }
+
+ this.mappings = mappings;
+
+ if (!this._observingPrefs) {
+ prefs.addObserver("", this, true);
+ this._observingPrefs = true;
+ }
+ },
+
+ _parseMapping: function(prefs, key, map) {
+ var keyParts = key.split(".");
+ var name = keyParts[0];
+ var member = keyParts[1];
+ if (!(name && member)) return;
+ try {
+ let value = prefs.getCharPref(key);
+ if (!value) return;
+ let mapping = (name in map)
+ ? map[name]
+ : map[name] = new SurrogateMapping(name);
+ switch(member) {
+ case "sources":
+ let prefix = true;
+ do {
+ switch(value[0]) {
+ case '@': mapping.forPage = true; break;
+ case '!': mapping.noScript = true; break;
+ case '<': mapping.before = true; break;
+ case '>': mapping.after = true; break;
+ case ' ': break;
+ default:
+ prefix = false;
+ }
+ if (prefix) value = value.substring(1);
+ } while(prefix);
+
+ case "exceptions":
+ value = new AddressMatcher(value);
+ break;
+
+ // case "exceptions": case "replacement": // deferred, see SurrogateMapping.replacement
+
+ default:
+ return;
+ }
+
+ mapping[member] = value;
+ } catch (e) {
+ Cu.reportError(e);
+ }
+ },
+ loadReplacementFile(path) {
+ return IO.readFile(IOS.newURI(this._resolveFile(path), null, null)
+ .QueryInterface(Ci.nsIFileURL).file);
+ },
+ getReplacement(name) {
+ return COMPAT.getStringPref(this.prefs, name + ".replacement");
+ },
+ initReplacement: function(m) {
+ var r;
+ try {
+ r = this.getReplacement(m.name);
+ if (/^(?:file:\/\/|\.\.?\/)/.test(r)) {
+ r = Services.cpmm.sendSyncMessage(IPC_P_MSG.LOAD_SURROGATE, m.name)[0];
+ }
+
+ if (r && !this.syntaxChecker.check(r)) {
+ throw this.syntaxChecker.lastError;
+ }
+ } catch (e) {
+ m.error = e;
+ Cu.reportError("Error loading " + m.name + " surrogate: " + e + (r ? "\n" + r : ""));
+ r = "";
+ }
+ return r;
+ },
+
+ _sandboxes: null,
+ createSandboxForWindow(w, ...args) {
+ if (!this._sandboxes) {
+ this._sandboxes = new Map();
+ OS.addObserver(this, "inner-window-destroyed", true);
+ }
+ let s = new Cu.Sandbox(...args);
+ let weakRef = Cu.getWeakReference(s);
+ let windowId = w.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
+ let sandboxes = this._sandboxes.get(windowId);
+ if (!sandboxes) {
+ this._sandboxes.set(windowId, sandboxes = [weakRef]);
+ } else {
+ sandboxes.push(weakRef);
+ }
+ return s;
+ },
+ _: {Ci, Cu},
+ observe(subject, topic, key) {
+ let {Ci, Cu} = this._;
+
+ if (topic === "inner-window-destroyed") {
+ let windowId = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
+ let sandboxes = this._sandboxes.get(windowId);
+ if (sandboxes) {
+ this._sandboxes.delete(windowId);
+ for (let weakRef of sandboxes) {
+ let s = weakRef.get();
+ if (s) {
+ try {
+ Cu.nukeSandbox(s);
+ } catch (e) {
+ Cu.reportError(e);
+ }
+ }
+ }
+ }
+ return;
+ }
+
+ if (subject instanceof Ci.nsIPrefBranch) {
+ this.prefs.removeObserver("", this, true);
+ this._observingPrefs = false;
+ if (typeof Thread !== "undefined") {
+ Thread.asap(this._syncPrefs, this);
+ }
+ return;
+ }
+
+ },
+
+ _resolveFile: function(fileURI) {
+ const profileURI = IOS.newFileURI(
+ Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties)
+ .get("ProfD", Ci.nsIFile));
+ return (this._resolveFile = function(fileURI) {
+ return profileURI.resolve(fileURI);
+ })(fileURI);
+ },
+
+ getScripts: function(scriptURL, pageURL, noScript, scripts) {
+
+ var isPage = scriptURL === pageURL;
+
+ const list = noScript
+ ? this.mappings.noScript
+ : isPage
+ ? this.mappings.forPage
+ : pageURL === '<'
+ ? this.mappings.before
+ : pageURL === '>'
+ ? this.mappings.after
+ : this.mappings.inclusion;
+
+ for (let j = list.length; j-- > 0;) {
+ let mapping = list[j];
+ if (mapping.sources && mapping.sources.test(scriptURL) &&
+ !(mapping.exceptions && mapping.exceptions.test(pageURL)) &&
+ mapping.replacement) {
+ let code = mapping.replacement;
+
+ if (!noScript && mapping.noScript)
+ code = 'window.addEventListener("DOMContentLoaded", function(event) {' +
+ code + '}, true)';
+
+ if (!scripts) scripts = [code];
+ else scripts.push(code);
+ }
+ }
+ return scripts;
+ },
+
+ _listener(ev) {
+ if (typeof ScriptSurrogate === "undefined") { // disabled / uninstalled
+ let f = arguments.callee;
+ let t = ev.currentTarget;
+ for (let et of ["error", "beforescriptexecute", "afterscriptexecute"]) {
+ t.removeEventListener(et, f, true);
+ }
+ return;
+ }
+
+ let s = ev.target;
+ if (s.localName !== "script") return;
+ let url = s.src;
+ if (!url) return;
+
+ let doc = s.ownerDocument;
+ let et = ev.type;
+
+ if (et !== "error") { // onbefore/onafter script execution
+ ScriptSurrogate.apply(doc, url, et[0] === 'b' ? "<" : ">", false);
+ return;
+ }
+
+ // onerror
+ let hasSurrogate = ScriptSurrogate.apply(doc, url);
+ if (!hasSurrogate) return;
+
+ let fakeLoad = ns.fakeScriptLoadEvents;
+ if (fakeLoad.enabled &&
+ !(fakeLoad.onlyRequireJS && !s.hasAttribute("data-requiremodule") ||
+ fakeLoad.exceptions && fakeLoad.exceptions.test(url) ||
+ fakeLoad.docExceptions && fakeLoad.docExceptions.test(doc.URL)
+ )
+ ) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ ev = doc.createEvent('HTMLEvents');
+ ev.initEvent('load', false, true);
+ s.dispatchEvent(ev);
+ }
+
+
+
+ },
+
+ replaceScript: function(scriptElement) {
+ if (scriptElement._surrogated) return true;
+
+ let src = scriptElement.src;
+ let doc = scriptElement.ownerDocument;
+
+ return (src && doc) && this.apply(doc, src, false, false) &&
+ (ns.getExpando(doc, "surrogates", {})[src] =
+ scriptElement._surrogated = true);
+ },
+
+ _privilegedRx: /^(?:chrome|resource|moz-extension):/,
+ apply: function(document, scriptURL, pageURL, noScript, scripts) {
+ if (typeof(noScript) !== "boolean") noScript = !!noScript;
+
+ if (this.enabled && (this.matchPrivileged || !this._privilegedRx.test(scriptURL))) {
+ scripts = this.getScripts(scriptURL, pageURL, noScript, scripts);
+ if (pageURL && !noScript) {
+ let w = document.defaultView;
+ let events = ["error"];
+ for (let when of ["before", "after"]) {
+ if (this.mappings[when].length) events.push(`${when}scriptexecute`);
+ }
+ for (let e of events) {
+ w.addEventListener(e, this._listener, true);
+ }
+ }
+ }
+
+ if (!scripts) return false;
+
+ const runner = noScript ? this.fallback :
+ scriptURL === pageURL ?
+ document.defaultView !== document.defaultView.top ?
+ this.executeSandbox
+ : (this.sandbox ? this.execute : this.executeDOM)
+ : this.sandboxInclusions ? this.executeSandbox : this.executeDOM;
+
+ if (this.debug) {
+ // we run each script separately and don't swallow exceptions
+ scripts.forEach(function(s) {
+ runner.call(this, document, "{" + this._preamble(s) + "}");
+ }, this);
+ } else {
+ runner.call(this, document,this._preamble(
+ "try{" +
+ scripts.join("}catch(e){}\ntry{") +
+ "}catch(e){}")
+ );
+ }
+ return true;
+ },
+
+ _testAll: function(document) {
+ let scripts = [];
+ let all = this.mappings.all;
+ for (let k in all) scripts.push(all[k].replacement);
+ scripts.forEach(function(s) {
+ this.executeSandbox(document, "{" + this._preamble(s) + "}");
+ }, this);
+ },
+
+ _preamble: function(s) {
+ delete this._preamble;
+ return (this._preamble = (ns.geckoVersionCheck("37") >= 0
+ ? (s) => s.indexOf("$S(") !== -1
+ ? "{let $S; {let nsmHandler={get:(t,n)=>n in t?t[n]:(...x)=>t.__noSuchMethod__(n,...x)};$S=(o)=>new Proxy(o||{},nsmHandler);}\n" + s + "\n}"
+ : s
+ : s => `{let $S=o=>o||{};\n${s}\n}`
+ ))(s);
+ },
+
+ fallback: function(document, scriptBlock) {
+ document.addEventListener("DOMContentLoaded", function(ev) {
+ ScriptSurrogate.executeSandbox(ev.currentTarget, scriptBlock);
+ }, false);
+ },
+
+ execute: function(document, scriptBlock) {
+ this.execute = ns.geckoVersionCheck("1.9.1") < 0 || ns.geckoVersionCheck("2") >= 0
+ ? this.executeSandbox
+ : this.executeDOM;
+ this.execute(document, scriptBlock);
+ },
+
+ _sandboxParams: {
+ wantXrays: false,
+ sandboxName: ""
+ },
+
+ getPrincipal: (doc) => doc.nodePrincipal,
+
+ executeSandbox: function(document, scriptBlock, env) {
+ var w = document.defaultView;
+ var wrapper = w;
+ var s = null;
+ try {
+ if (typeof w.wrappedJSObject === "object") w = w.wrappedJSObject;
+ this._sandboxParams.sandboxName = "NoScript::ScriptSurrogate@" + document.documentURI;
+ this._sandboxParams.sandboxPrototype = w;
+ s = this.createSandboxForWindow(wrapper, this.getPrincipal(document), this._sandboxParams);
+ if (!("top" in s)) s.__proto__ = w;
+ if (typeof env !== "undefined") {
+ s.env = env;
+ let ep = {};
+ for (let p in env) {
+ ep[p] = "rw";
+ }
+ env.__exposedProps__ = ep;
+ }
+ let code = "with(window){" + scriptBlock + "}delete this.env;";
+ if ("keys" in Object) code += "Object.keys(this).forEach(function(p) { window[p] = this[p] }, this);";
+ Cu.evalInSandbox(code, s);
+ } catch (e) {
+ if (ns.consoleDump) {
+ ns.dump(e);
+ ns.dump(scriptBlock);
+ }
+ if (this.debug) Cu.reportError(e);
+ } finally {
+ delete this._sandboxParams.sandboxPrototype;
+ }
+ },
+
+ executeDOM: function(document, scriptBlock) {
+ var de = document.documentElement;
+ try {
+ if (!de) {
+ this.executeSandbox(document, scriptBlock);
+ return;
+ }
+
+ var se = document.createElement("script");
+ se.type = "application/javascript;version=" + ScriptSurrogate.JS_VERSION;
+ se.appendChild(document.createTextNode(scriptBlock));
+ de.appendChild(se);
+ de.removeChild(se);
+ } catch (e) {
+ if (ns.consoleDump) ns.dump(e);
+ if (this.debug) Cu.reportError(e);
+ }
+ },
+
+ dispose() {
+ if (this._observingPrefs) {
+ this.prefs.removeObserver("", this, true);
+ }
+ }
+
+
+
+};
+
+function SurrogateMapping(name) {
+ this.name = name;
+ this.__defineGetter__("replacement", this._replacement);
+}
+SurrogateMapping.prototype = {
+ sources: null,
+ _replacement: function() {
+ delete this.replacement;
+ return this.replacement = ScriptSurrogate.initReplacement(this);
+ },
+ exceptions: null,
+ error: null,
+
+ forPage: false,
+ noScript: false,
+ before: false,
+ after: false
+};
diff --git a/extensions/noscript/chrome/content/noscript/ScriptlessBGThumbs.js b/extensions/noscript/chrome/content/noscript/ScriptlessBGThumbs.js
new file mode 100644
index 0000000..962c060
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/ScriptlessBGThumbs.js
@@ -0,0 +1,48 @@
+{
+ let scope = {};
+ Cu.import("resource://gre/modules/BackgroundPageThumbs.jsm", scope);
+
+ let bpt = scope.BackgroundPageThumbs;
+
+ if (!bpt._NoScript_) {
+ let patched = bpt._NoScript_ = {};
+ let patch = (name, f) => {
+ patched[name] = bpt[name];
+ bpt[name] = f;
+ };
+ patch("capture", function() {
+ Cu.import("resource://gre/modules/PageThumbs.jsm", scope);
+ let PageThumbs = scope.PageThumbs;
+ let e = PageThumbs._prefEnabled;
+ if (!ns.getPref("bgThumbs.allowed")) {
+ PageThumbs._prefEnabled = () => false;
+ }
+ try {
+ bpt._NoScript_.capture.apply(bpt, arguments);
+ } finally {
+ PageThumbs._prefEnabled = e;
+ }
+ });
+
+ bpt._destroyBrowser();
+
+ patch("_ensureBrowser", function() {
+ if (!this._thumbBrowser) {
+ this._NoScript_._ensureBrowser.apply(this, arguments);
+ if (this._thumbBrowser && ns.getPref("bgThumbs.disableJS"))
+ this._thumbBrowser.messageManager.loadFrameScript(
+ "data:text/javascript,docShell.allowJavascript = false", false);
+ }
+ });
+
+ ns.onDisposal(() => {
+ let patched = bpt._NoScript_;
+ if (!patched) return;
+ for(let name of Object.keys(patched)) {
+ bpt[name] = patched[name];
+ }
+ delete bpt._NoScript_;
+ });
+ }
+
+}
diff --git a/extensions/noscript/chrome/content/noscript/SiteUtils.js b/extensions/noscript/chrome/content/noscript/SiteUtils.js
new file mode 100644
index 0000000..8d75a09
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/SiteUtils.js
@@ -0,0 +1,358 @@
+var SiteUtils = new function() {
+ const _domainPattern = this.domainPattern = /^[\w\u0080-\uffff][\w\-\.\u0080-\uffff]*$/;
+ this.ios = IOS;
+ this.uriFixup = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup);
+
+ function sorter(a, b) {
+ if (a == b) return 0;
+ if (!a) return 1;
+ if (!b) return -1;
+ const dp = _domainPattern;
+ return dp.test(a) ?
+ (dp.test(b) ? (a < b ? -1 : 1) : -1)
+ : (dp.test(b) ? 1 : a < b ? -1 : 1);
+ }
+
+ this.sort = function(ss) {
+ return ss.sort(sorter);
+ };
+
+ this.getSite = function(url) {
+ if (!url ||
+ url.charCodeAt(0) < 33 && // needs trimming
+ !(url = url.replace(/^\s*(.*?)\s*$/, '$1'))) {
+ return "";
+ }
+
+ if (url[0] === '[' && /^\[\w.*\]$/.test(url)) {
+ // special principal
+ return url.replace(/\s+/g, '+');
+ }
+
+ if (url.indexOf(":") == -1) {
+ return this.domainMatch(url);
+ }
+
+ var scheme;
+ try {
+ scheme = this.ios.extractScheme(url).toLowerCase();
+ switch (scheme) {
+ case "http": case "https": // commonest case first
+ break;
+ case "javascript": case "data":
+ return "";
+ case "about":
+ return url.split(/[\?#]/, 1)[0];
+ case "chrome":
+ return "chrome:";
+ }
+ scheme += ":";
+ if (url == scheme) return url;
+ } catch(ex) {
+ return this.domainMatch(url);
+ }
+ try {
+ let uri = this.uriFixup.createExposableURI( // fix wyciwyg: and zaps userpass
+ IOUtil.unwrapURL(url) // unwrap JAR and view-source uris
+ );
+
+ try {
+ return uri.prePath;
+ } catch(exNoPrePath) {
+ scheme = uri.scheme;
+ let host = uri.spec.substring(scheme.length);
+ return /^\/\/[^\/]/.test(host) && (host = this.domainMatch(host.replace(/^\/\/([^\/]+).*/, "$1")))
+ ? scheme + "//" + host
+ : scheme;
+ }
+ } catch(ex) {
+ return url.slice(-2) === ":0" ? this.getSite(url.slice(0, -2)) + ":0" : "";
+ }
+ };
+
+ this.list2set = function(sl) {
+ // kill duplicates
+ var prevSite = "";
+ var site;
+ for (var j = sl.length; j--> 0;) {
+ site = sl[j];
+ if ((!site) || site == prevSite) {
+ sl.splice(j, 1);
+ } else {
+ prevSite = site;
+ }
+ }
+ return sl;
+ };
+
+ this.sortedSet = function(sl) {
+ return this.list2set(this.sort(sl));
+ }
+
+ this.splitString = function(s) {
+ return s && /\S/.test(s) && s.split(/\s+/) || [];
+ };
+
+ this.domainMatch = function(url) {
+ const m = url.match(this.domainPattern);
+ return m ? m[0].toLowerCase() : "";
+ };
+
+ this.sanitizeList = function(sl) {
+ for (var j = sl.length; j-- > 0; ) {
+ sl[j] = this.getSite(sl[j]);
+ }
+ return sl;
+ };
+
+ this.sanitizeMap = function(sm) {
+ var site;
+ delete sm[""];
+ for (var url in sm) {
+ site = this.getSite(url);
+ if (site != url) {
+ if (site) sm[site] = sm[url];
+ delete sm[url];
+ }
+ }
+ return sm;
+ };
+
+ this.sanitizeString = function(s) {
+ return this.set2string(this.string2set(s));
+ };
+
+ this.string2set = function(s) {
+ return this.sortedSet(this.sanitizeList(this.splitString(s)));
+ };
+
+ this.set2string = function(ss) {
+ return ss.join(" ");
+ };
+
+ this.crop = function(url, max) {
+ max = max || 1000;
+ if (url.length > max) {
+ return this.crop(url.substring(0, max / 2)) + "\n[...]\n" +
+ this.crop(url.substring(url.length - max / 2));
+ }
+ return url.replace(/\w{20}/g, "$&\u200B");
+ };
+}
+
+function PolicySites(sitesString) {
+ if (sitesString) this.sitesString = sitesString;
+}
+PolicySites.prototype = {
+ clone: function() {
+ return new PolicySites(this.sitesString);
+ }
+,
+ equals: function(other) {
+ return other && (this.sitesString == other.sitesString);
+ }
+,
+ _sitesString: "",
+ get sitesString() {
+ return this._sitesString;
+ },
+ set sitesString(s) {
+ if (s !== this._siteString) {
+
+ s = SiteUtils.sanitizeString(s);
+ if (s != this._sitesString) {
+ this._sitesString = s;
+ this._sitesMap = null;
+ this._sitesList = null;
+ }
+ }
+ return s;
+ }
+,
+ _sitesList: null,
+ get sitesList() {
+ return this._sitesList ? this._sitesList : this._sitesList = SiteUtils.splitString(this.sitesString);
+ },
+ set sitesList(sl) {
+ this.sitesString = SiteUtils.set2string(SiteUtils.sortedSet(SiteUtils.sanitizeList(sl)));
+ return this.sitesList;
+ }
+,
+ _sitesMap: null,
+ get sitesMap() {
+ if (!this._sitesMap) {
+ const sm = {__proto__: null};
+ const sl = SiteUtils.splitString(this.sitesString);
+ if (sl) {
+ for (var j = sl.length; j-- > 0;) {
+ sm[sl[j]] = true;
+ }
+ }
+ this._sitesMap = sm;
+ }
+ return this._sitesMap;
+ },
+ set sitesMap(sm) {
+ sm = sm ? SiteUtils.sanitizeMap(sm) : {__proto__: null};
+ var sl = [];
+ for (var s in sm) {
+ sl.push(s);
+ }
+
+ this._sitesString = SiteUtils.set2string(SiteUtils.sort(sl));
+ this._sitesList = null;
+ return this._sitesMap = sm;
+ }
+,
+ fromPref: function(pref, name = "sites") {
+ if (!this.settingPref) {
+ try {
+ this.sitesString = pref.getCharPref(name)
+ .replace(/[^\u0000-\u007f]+/g, function($0) { return decodeURIComponent(escape($0)) });
+ } catch(e) {
+ ns.dump(e);
+ this.sitesString = "";
+ return false;
+ }
+ }
+ return true;
+ }
+,
+ settingPref: false,
+ toPref: function(pref, name) {
+ if (!name) name = "sites";
+ try {
+ if (pref.prefIsLocked(name)) {
+ this.fromPref(pref);
+ return;
+ }
+ } catch (e) {
+ // gonna fail in child process
+ }
+ var change;
+ var s = this.sitesString.replace(/[^\u0000-\u007f]+/g,function($0) { return unescape(encodeURIComponent($0)) });
+ try {
+ change = s != pref.getCharPref(name);
+ } catch(ex) {
+ change = true;
+ }
+
+ if (change) {
+ this.settingPref = true;
+ try {
+ pref.setCharPref(name, s);
+ } finally {
+ this.settingPref = false;
+ }
+ }
+ }
+,
+ // returns the shortest match for a site, or "" if no match is found
+ matches: function(site) {
+ if (!site) return "";
+ const sm = this.sitesMap;
+ var match;
+ var dots; // track "dots" for fix to 2nd level domain policy lookup flaw
+ var pos = site.indexOf(':') + 1;
+ if (pos > 0 && (pos == site.length || site[pos] == '/')) {
+ if (sm[match = site.substring(0, pos)]) return match; // scheme match
+ if (++pos >= site.length || site[pos] != '/') return "";
+ match = site.substring(pos + 1);
+ dots = 0;
+ } else {
+ match = site;
+ dots = 1;
+ }
+
+ var submatch;
+ for (pos = match.lastIndexOf('.'); pos > 0; dots++) {
+ pos = match.lastIndexOf('.', pos - 1);
+ if ((dots || pos > -1) && sm[submatch = match.substring(pos + 1)]) {
+ return submatch; // domain/subdomain match
+ }
+ }
+
+ if (sm[match]
+ && (dots > 1 || sm[site]) // strict CAPS-style matching
+ ) return match; // host match
+ return sm[site] ? site : ""; // full match
+ }
+,
+
+
+ _remove: function(site) {
+ const sm = this.sitesMap;
+ delete sm[site];
+ if (site.indexOf(":") < 0 && site.indexOf(".") == site.lastIndexOf(".")) {
+ // base domain hack
+ delete sm["http://" + site];
+ delete sm["https://" + site];
+ delete sm["file://" + site];
+ delete sm["ftp://" + site];
+ }
+ },
+ remove: function(sites, keepUp, keepDown) {
+ if (!sites) return false;
+ if (!(typeof(sites) == "object" && "push" in sites))
+ return this.remove([sites], keepUp, keepDown);
+ keepUp = keepUp || false;
+ keepDown = keepDown || false;
+
+ const sm = this.sitesMap;
+ var change = false;
+ var site, match;
+ var tmp = keepDown ? null : new PolicySites();
+ for (var j = sites.length; j-- > 0;) {
+ site = sites[j];
+ if (site[site.length - 1] != ":") { // not a scheme only site
+ if (!keepUp) {
+ while ((match = this.matches(site)) && site != match) { // remove ancestors
+ this._remove(match);
+ change = true;
+ }
+ }
+ if (!keepDown) {
+ tmp.sitesString = site;
+ for (match in sm) { // remove descendants
+ if (tmp.matches(match)) {
+ if (site != match) delete sm[match];
+ change = true;
+ }
+ }
+ this._remove(site);
+ }
+ }
+
+ if (site in sm) {
+ this._remove(site);
+ change = true;
+ }
+ }
+ if (change) this.sitesMap = this._sitesMap;
+ return change;
+ },
+
+ _add: function(site) {
+ return (site in this.sitesMap ? false : this.sitesMap[site] = true);
+ },
+
+ add: function(sites) {
+ if (!sites) return false;
+ if (!(typeof(sites) == "object" && "push" in sites))
+ return this.add([sites]);
+
+ var change = false;
+ var site;
+ for (var j = sites.length; j-- > 0;) {
+ site = sites[j];
+ if (site.indexOf(":") < 0 && site.indexOf(".") == site.lastIndexOf(".")) {
+ // base domain hack
+ if(this._add("http://" + site)) change = true;
+ if(this._add("https://" + site)) change = true;
+ }
+ if (this._add(site)) change = true;
+ }
+ if (change) this.sitesMap = this._sitesMap;
+ return change;
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/Strings.js b/extensions/noscript/chrome/content/noscript/Strings.js
new file mode 100644
index 0000000..38fd8e5
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Strings.js
@@ -0,0 +1,37 @@
+function Strings(chromeName) {
+ this.chromeName = chromeName;
+}
+
+Strings.wrap = (s, count) => s.replace(new RegExp("\\w{" + (parseInt(count) || 20) + "}", 'g'), "$&\u200B");
+
+Strings.prototype = {
+ _rnd: `${Math.random()}-${Date.now()}`,
+ bundles: {},
+ getBundle: function(path) {
+ if (path in this.bundles) return this.bundles[path];
+ try {
+ return this.bundles[path] =
+ Cc["@mozilla.org/intl/stringbundle;1"]
+ .getService(Ci.nsIStringBundleService)
+ .createBundle(
+ `chrome://${this.chromeName}/${path}/${this.chromeName}.properties?${this._rnd}`
+ );
+ } catch(ex) {
+ return this.bundles[path] = null;
+ }
+ },
+
+
+ _stringFrom: function(bundle, name, parms) {
+ try {
+ return parms ? bundle.formatStringFromName(name, parms, parms.length) : bundle.GetStringFromName(name);
+ } catch(ex) {
+ return null;
+ }
+ }
+,
+ getString: function(name, parms) {
+ var s = this._stringFrom(this.getBundle("locale"), name, parms);
+ return s || name;
+ }
+}
diff --git a/extensions/noscript/chrome/content/noscript/SyntaxChecker.js b/extensions/noscript/chrome/content/noscript/SyntaxChecker.js
new file mode 100644
index 0000000..3797d45
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/SyntaxChecker.js
@@ -0,0 +1,31 @@
+function SyntaxChecker(version) {
+ this.version = version || "1.5";
+ this.sandbox = new Cu.Sandbox("about:");
+}
+
+SyntaxChecker.prototype = {
+ lastError: null,
+ lastFunction: null,
+ check: function(script) {
+ this.sandbox.script = script;
+ try {
+ return !!(this.lastFunction = this.ev("new Function(script)"));
+ } catch(e) {
+ this.lastError = e;
+ this.lastFunction = null;
+ }
+ return false;
+ },
+ unquote: function(s, q) {
+ if (!(s[0] == q && s[s.length - 1] == q &&
+ !s.replace(/\\./g, '').replace(/^(['"])[^\n\r]*?\1/, "")
+ )) return null;
+ try {
+ return this.ev(s);
+ } catch(e) {}
+ return null;
+ },
+ ev: function(s) {
+ return Cu.evalInSandbox(s, this.sandbox);
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/Thread.js b/extensions/noscript/chrome/content/noscript/Thread.js
new file mode 100644
index 0000000..371cfa5
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/Thread.js
@@ -0,0 +1,95 @@
+var Thread = {
+
+ hostRunning: true,
+ activeLoops: 0,
+
+ spin: function(ctrl) {
+ ctrl.startTime = ctrl.startTime || Date.now();
+ ctrl.timeout = false;
+ this.activeLoops++;
+ this._spinInternal(ctrl);
+ this.activeLoops--;
+ ctrl.elapsed = Date.now() - ctrl.startTime;
+ return ctrl.timeout;
+ },
+
+ _spinInternal: function(ctrl) {
+ var t = ctrl.startTime;
+ var maxTime = parseInt(ctrl.maxTime);
+ if (maxTime) {
+ while(ctrl.running && this.hostRunning) {
+ this.yield();
+ if (Date.now() - t > maxTime) {
+ ctrl.timeout = true;
+ ctrl.running = false;
+ break;
+ }
+ }
+ } else while(ctrl.running && this.hostRunning) this.yield();
+ },
+
+ yield: function() {
+ this.current.processNextEvent(true);
+ },
+
+ yieldAll: function() {
+ var t = this.current;
+ while(t.hasPendingEvents()) t.processNextEvent(false);
+ },
+
+ get current() {
+ delete this.current;
+ var obj = "@mozilla.org/thread-manager;1" in Cc
+ ? Cc["@mozilla.org/thread-manager;1"].getService()
+ : Cc["@mozilla.org/thread;1"].createInstance(Ci.nsIThread);
+ this.__defineGetter__("current", function() { return obj.currentThread; });
+ return this.current;
+ },
+
+ get currentQueue() {
+ delete this.currentQueue;
+ var eqs = null;
+ const CTRID = "@mozilla.org/event-queue-service;1";
+ if (CTRID in Cc) {
+ const IFace = Ci.nsIEventQueueService;
+ eqs = Cc[CTRID].getService(IFace);
+ }
+ this.__defineGetter__("currentQueue", eqs
+ ? function() { return eqs.getSpecialEventQueue(IFace.CURRENT_THREAD_EVENT_QUEUE); }
+ : this.__lookupGetter__("current")
+ );
+ return this.currentQueue;
+ },
+
+ delay: function(callback, time = 0, self = null, args = DUMMY_ARRAY) {
+ var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback({
+ notify: this._delayRunner,
+ context: { callback, args, self }
+ }, time, 0);
+ },
+
+ dispatch: function(runnable) {
+ this.current.dispatch(runnable, Ci.nsIEventTarget.DISPATCH_NORMAL);
+ },
+
+ asap: function(callback, self, args = DUMMY_ARRAY) {
+ this.current.dispatch({
+ run: function() {
+ callback.apply(self, args);
+ }
+ }, Ci.nsIEventTarget.DISPATCH_NORMAL);
+ },
+
+ _delayRunner: function(timer) {
+ var ctx = this.context;
+ try {
+ if (typeof Thread === "undefined") return;
+ ctx.callback.apply(ctx.self, ctx.args);
+ } finally {
+ this.context = null;
+ timer.cancel();
+ }
+ }
+
+};
diff --git a/extensions/noscript/chrome/content/noscript/UISync.jsm b/extensions/noscript/chrome/content/noscript/UISync.jsm
new file mode 100644
index 0000000..f1feadb
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/UISync.jsm
@@ -0,0 +1,316 @@
+'use strict';
+
+var EXPORTED_SYMBOLS = ["UISync"];
+
+let { interfaces: Ci, classes: Cc, utils: Cu, results: Cr } = Components;
+
+const messages = ["NoScript:reload", "NoScript:reloadAllowedObjects",
+ "NoScript:executeJSURL",
+ "NoScript:purgeRecent", "NoScript:forceSync",
+ "NoScript:unload"];
+
+function UISync(ctx) {
+ this.ctx = ctx;
+ this.listeners = [];
+ this.wire();
+ this.scheduleSync();
+}
+
+UISync.prototype = {
+ eraser: {
+ tapped: null,
+ delKey: false,
+ },
+
+ addListener(type, handler, ...opts) {
+ this.ctx.addEventListener(type, handler, ...opts);
+ this.listeners.push({type, handler, opts});
+ },
+ removeListeners() {
+ let ctx = this.ctx;
+ let ns = ctx.ns;
+ for(let {type, handler, opts} of this.listeners) {
+ if (ns.consoleDump) ns.dump(`Removing listener ${type}, ${uneval(handler)}, ${uneval(opts)}`);
+ ctx.removeEventListener(type, handler, ...opts);
+ }
+ },
+
+ _wired: false,
+ wire() {
+ this._wired = true;
+ let ctx = this.ctx;
+ let ns = ctx.ns;
+ let eraser = this.eraser;
+
+ this.addListener("DOMWindowCreated", () => this.sync());
+ this.addListener("NoScript:syncUI", ev => {
+ ev.stopPropagation();
+ this.scheduleSync();
+ }, true);
+ this.addListener("DOMContentLoaded", ev => {
+ this.onContentLoad(ev);
+ }, true);
+ this.addListener("pageshow", ev => {
+ this.onPageShow(ev);
+ }, true);
+ this.addListener("pagehide", ev => {
+ eraser.tapped = null;
+ eraser.delKey = false;
+ this.onPageHide(ev);
+ }, true);
+
+
+ this.addListener("keyup", ev => {
+ let el = eraser.tapped;
+ if (el && ev.keyCode === 46 &&
+ ns.getPref("eraseFloatingElements")
+ ) {
+ eraser.tapped = null;
+ eraser.delKey = true;
+ let doc = el.ownerDocument;
+ let w = doc.defaultView;
+ if (w.getSelection().isCollapsed) {
+ let root = doc.body || doc.documentElement;
+ let posRx = /^(?:absolute|fixed)$/;
+ do {
+ if (posRx.test(w.getComputedStyle(el, '').position)) {
+ (eraser.tapped = el.parentNode).removeChild(el);
+ break;
+ }
+ } while ((el = el.parentNode) && el != root);
+ }
+ }
+ }, true);
+
+ this.addListener("mousedown", ev => {
+ if (ev.button === 0) {
+ eraser.tapped = ev.target;
+ eraser.delKey = false;
+ }
+ }, true);
+
+ this.addListener("mouseup", ev => {
+ if (eraser.delKey) {
+ eraser.delKey = false;
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ eraser.tapped = null;
+ }, true);
+
+ let fixLinksHandler = ev => {
+ if (!ns.getPref("fixLinks")) return;
+ let doc = ev.target.ownerDocument;
+ if (ns.isJSEnabled(ns.getDocSite(doc), doc.defaultView)) return;
+ switch(ev.type) {
+ case "click":
+ ns.onContentClick(ev);
+ break;
+ case "change":
+ ns.onContentChange(ev);
+ break;
+ }
+ };
+ this.addListener("click", fixLinksHandler, true);
+ this.addListener("change", fixLinksHandler, true);
+ if (ns.implementToStaticHTML) {
+ this.addListener("NoScript:toStaticHTML", ctx.ns.toStaticHTMLHandler, false, true);
+ }
+ for (let m of messages) {
+ ctx.addMessageListener(m, this);
+ }
+ this.messages = messages;
+ ns.clearClickHandler.install(ctx);
+ if (ns.consoleDump && ctx.content && ctx.content.location)
+ ns.dump(`Wired frame script at ${ctx.content.location.href}`);
+ },
+
+ unwire() {
+ if (!this._wired) return;
+ this._wired = false;
+ let ctx = this.ctx;
+ let ns = ctx.ns;
+
+ ns.clearClickHandler.uninstall(ctx);
+ for (let m of this.messages) {
+ try {
+ ctx.removeMessageListener(m, this);
+ } catch (e) {
+ }
+ }
+ this.removeListeners();
+ if (ns.consoleDump && ctx.content && ctx.content.location)
+ ns.dump(`Unwired frame script at ${ctx.content.location.href}`);
+ },
+
+ receiveMessage: function(msg) {
+ let ctx = this.ctx;
+ let ns = ctx.ns;
+ if (ns.consoleDump) try {
+ ns.dump(`Received message ${msg.name} ${uneval(msg.data)}`);
+ } catch (e) {}
+ switch(msg.name) {
+ case "NoScript:reload":
+ let { innerWindowID, snapshots, reloadPolicy, mustReload } = msg.data;
+ ns.reload(msg.target, snapshots, mustReload, reloadPolicy, innerWindowID);
+ break;
+ case "NoScript:reloadAllowedObjects":
+ ns.reloadAllowedObjectsChild(msg.target, msg.data.mime);
+ break;
+ case "NoScript:executeJSURL":
+ {
+ let browser = msg.target;
+ let {url, callbackId, fromURLBar} = msg.data;
+ let openCallback = ns.IPC.child.callback(callbackId);
+ ns.executeJSURLInContent(browser, browser.content, url, openCallback, fromURLBar);
+ }
+ break;
+ case "NoScript:resetClearClickTimeout":
+ ns.clearClickHandler.rapidFire.ts = 0;
+ break;
+ case "NoScript:purgeRecent":
+ ns.recentlyBlocked = [];
+ case "NoScript:forceSync":
+ this.sync();
+ break;
+ case "NoScript:unload":
+ this.unwire();
+ break;
+ }
+ },
+
+ _syncScheduled: false,
+ scheduleSync() {
+ if (this._syncScheduled) return;
+ this.ctx.ns.delayExec(() => this.sync(), 500);
+ this._syncScheduled = true;
+ },
+ sync() {
+ this._syncScheduled = false;
+ let ctx = this.ctx;
+ let sites = ctx.ns.getSites(this.ctx);
+ if (sites.pluginExtras && sites.pluginExtras.length) {
+ sites.pluginExtras = sites.pluginExtras.map(
+ pes => pes.length ? pes.map(pe => {
+ if (pe.placeholder || pe.document) {
+ pe = Object.assign({}, pe);
+ if (pe.placeholder) pe.placeholder = { parentNode: !!pe.placeholder.parentNode };
+ if (pe.document) pe.document = true;
+ }
+ return pe;
+ }) : pes
+ );
+ }
+ try {
+ ctx.sendAsyncMessage("NoScript:syncUI", sites);
+ } catch (ex) {
+ ctx.ns.dump(ex);
+ ctx.ns.dump(sites.toSource());
+ }
+ },
+
+ notifyMetaRefresh(info) {
+ this.ctx.sendAsyncMessage("NoScript:notifyMetaRefresh", info);
+ },
+
+ onContentLoad(ev) {
+ var doc = ev.originalTarget;
+ let w = doc.defaultView;
+ if (w) {
+
+ let ns = this.ctx.ns;
+ ns.setExpando(doc, "domLoaded", true);
+ if (w === w.top) {
+ let url = doc.URL;
+ let jsBlocked = /^https?:/.test(url) && !ns.isJSEnabled(ns.getSite(url), w);
+ if (jsBlocked) {
+ ns.processMetaRefresh(doc, this.notifyMetaRefresh);
+ w.addEventListener("pageshow", ev => this.onPageShowNS(ev), false);
+ }
+ } else {
+ ns.frameContentLoaded(w);
+ }
+ this.sync();
+ }
+ },
+
+ onPageShow(ev) {
+ let d = ev.originalTarget;
+ if (d.defaultView) {
+ try {
+ if (ev.persisted) {
+ this.toggleObjectsVisibility(d, true);
+ }
+ } catch(e) {}
+ }
+ let ns = this.ctx.ns;
+ ns.setExpando(d, "domLoaded", true);
+ ns.dump(`Sync on pageshow ${d.URL}`);
+ this.sync();
+ },
+ onPageShowNS(ev) {
+ let w = ev.currentTarget;
+ w.setTimeout(() => this.ctx.ns.detectJSRedirects(w.document), 50);
+ },
+ onPageHide(ev) {
+ let d = ev.originalTarget;
+ if (d.defaultView) {
+ this.toggleObjectsVisibility(d, false);
+ }
+ this.sync();
+ },
+
+ _tags: ["object", "embed"],
+ toggleObjectsVisibility(d, v) {
+ var ns = this.ctx.ns;
+ var rx = ns.hideOnUnloadRegExp;
+ if (!rx) return;
+ var callback = v ? showObject : hideObject;
+ var params = {
+ document: d,
+ mimeRx: rx,
+ classRx: ns.hideObjClassNameRx,
+ className: ns.hideObjClassName,
+ };
+ let aa = null;
+ for (let t of this._tags) {
+ let oo = d.getElementsByTagName(t);
+ let j = oo.length;
+ if (j) {
+ aa = aa || [oo[--j]];
+ while(j-- > 0) {
+ aa.push(oo[j]);
+ }
+ }
+ }
+ if (aa) {
+ for (let j = aa.length; j-- > 0;) {
+ callback(params, aa[j]);
+ }
+ }
+ },
+
+};
+
+function hideObject(p, o) {
+ if (!p.mimeRx.test(o.type)) return;
+
+ var r = p.document.createElement("object");
+ r.style.width = o.offsetWidth + "px";
+ r.style.height = o.offsetHeight + "px";
+ r.style.display = "inline-block";
+ o.className += " " + p.className;
+ o.parentNode.insertBefore(r, o);
+}
+
+function showObject(p, o) {
+ var cs = o.className;
+ cs = cs.replace(p.classRx, '');
+ if (cs != o.className) {
+ o.className = cs;
+ var r = o.previousSibling;
+ if (r instanceof HTMLObjectElement) {
+ r.parentNode.removeChild(r);
+ }
+ }
+}
diff --git a/extensions/noscript/chrome/content/noscript/URIValidator.js b/extensions/noscript/chrome/content/noscript/URIValidator.js
new file mode 100644
index 0000000..b7cb757
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/URIValidator.js
@@ -0,0 +1,49 @@
+var URIValidator = {
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
+
+ // returns false if absolute URI is not valid, undefined if it cannot be validated (i.e. no validator is found for this scheme)
+ validate: function(uriSpec) {
+ if (!uriSpec) return false;
+ var parts = uriSpec.split(":");
+ if (parts.length < 2) return false;
+ var scheme = parts.shift().toLowerCase();
+ if (!scheme) return false;
+ var validator = this.validators[scheme];
+ try {
+ // using unescape rather than decodeURI for a reason:
+ // many external URL (e.g. mailto) default to ISO8859, and we would fail,
+ // but on the other hand rules marking as invalid non-null high unicode chars are unlikely (let's hope it)
+ return validator && validator.test(unescape(parts.join(":")));
+ } catch(e) {
+ return false;
+ }
+ },
+
+ get validators() {
+ delete this.validators;
+ this._init();
+ return this.validators;
+ },
+
+ prefs: null,
+ _init: function() {
+ this.validators = {};
+ this.prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService)
+ .getBranch("noscript.urivalid.");
+ for (var key of this.prefs.getChildList("", {})) {
+ this.parseValidator(key);
+ }
+ this.prefs.addObserver("", this, true);
+ },
+ parseValidator: function(key) {
+ try {
+ this.validators[key] = new RegExp("^" + this.prefs.getCharPref(key) + "$");
+ } catch(e) {
+ delete this.validators[key];
+ }
+ },
+ observe: function(prefs, topic, key) {
+ this.parseValidator(key);
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/WebExt.js b/extensions/noscript/chrome/content/noscript/WebExt.js
new file mode 100644
index 0000000..dec3747
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/WebExt.js
@@ -0,0 +1,49 @@
+var WebExt = {
+ enabled: false,
+ started: false,
+ running: false,
+ port: null,
+ saveData(json = ns.conf2JSON(true)) {
+ this.tell("saveData", json);
+ },
+ dumpData() {
+ this.tell("dumpData");
+ },
+ tell(type, data) {
+ if (this.port) try {
+ this.port.postMessage({ type, data });
+ } catch (e) {
+ if (!/\bdead object\b/.test(e.message)) { // normal on uninstall
+ Cu.reportError(e);
+ }
+ }
+ },
+
+ init(embeddedWebExtension) {
+ WebExt.enabled = true;
+ embeddedWebExtension.startup().then(({browser}) => {
+ WebExt.started = true;
+ ns.dump(`Embedded webext started`);
+ browser.runtime.onMessage.addListener(msg => {
+ switch(msg) {
+ case "STARTED":
+ WebExt.running = true;
+ break;
+ case "STOPPED":
+ WebExt.running = false;
+ break;
+ }
+ ns.dump(`Received message from embedded webext ${msg}`);
+ });
+ browser.runtime.onConnect.addListener(port => {
+ ns.dump(`Webext connected`);
+ WebExt.port = port;
+ WebExt.saveData();
+ });
+ }).catch(err => {
+ Components.utils.reportError(
+ `Embedded webext startup failed: ${err.message} ${err.stack}\n`
+ );
+ });
+ },
+};
diff --git a/extensions/noscript/chrome/content/noscript/WebGLInterception.js b/extensions/noscript/chrome/content/noscript/WebGLInterception.js
new file mode 100644
index 0000000..b129f8c
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/WebGLInterception.js
@@ -0,0 +1,64 @@
+var WebGLInterception = {
+ sites: {},
+ handler(ev) {
+ WebGLInterception.record(ev.target, ns.getSite(ev.target.documentURI || ev.target.ownerDocument.documentURI), true);
+ },
+ record(ctx, site, fromDOM) {
+ ns.tagForReplacement(ctx, {
+ url: site,
+ site: site,
+ originSite: site,
+ mime: "WebGL"
+ });
+ let doc = ctx.ownerDocument || ctx;
+ if (fromDOM) {
+ let ds = DOM.getDocShellForWindow(doc.defaultView);
+ if (ds.isLoadingDocument) { // prevent fallback redirection from hiding us
+ let sites = this.sites;
+ sites[site] = doc.documentURI;
+ doc.defaultView.addEventListener("load", () => delete sites[site], false);
+ }
+ }
+ ns.recordBlocked(site, site);
+ },
+ get interceptionDef() {
+ delete this.interceptionDef;
+ return (this.interceptionDef = function() {
+ var proto = HTMLCanvasElement.prototype;
+ var getContext = proto.getContext;
+ proto.getContext = function(type, ...rest) {
+ if (type && type.toLowerCase().includes("webgl")) {
+ var ev = this.ownerDocument.createEvent("Events");
+ ev.initEvent("NoScript:WebGL", true, false);
+ (this.parentNode ? this : this.ownerDocument)
+ .dispatchEvent(ev);
+ return null;
+ }
+ return getContext.call(this, type, ...rest);
+ };
+ }.toSource() + "()");
+ },
+ reloadAllowed(docShell) {
+ let curURL = docShell.currentURI.spec;
+ let site = ns.getSite(curURL);
+ if (site in this.sites) {
+ let url = this.sites[site];
+ delete this.sites[site];
+ if (url !== curURL) {
+ docShell.loadURI(url, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);
+ return true;
+ }
+ }
+ return false;
+ },
+ hook(doc, site) {
+ if (!(ns.isAllowedObject(site, "WebGL", site, site) || ns.isAllowedMime("WebGL", site))) {
+ doc.addEventListener("NoScript:WebGL", this.handler, false, true);
+ if (site in this.sites) {
+ this.record(doc, site);
+ }
+ return this.interceptionDef;
+ }
+ return null;
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/WinScript.js b/extensions/noscript/chrome/content/noscript/WinScript.js
new file mode 100644
index 0000000..84edb6c
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/WinScript.js
@@ -0,0 +1,78 @@
+var WinScript = {
+ supported: true,
+ block: function(window) {
+ if (window._blockScriptForGlobal) return;
+ try {
+ Cu.blockScriptForGlobal(window);
+ if (!("_blockScriptForGlobal" in window)) {
+ this.patchStyle(window.document);
+ }
+ } catch (e) {
+ if (e.message === "Script may not be disabled for system globals") {
+ try {
+ window.console.log("NoScript could not disable scripts for system global " + window.document.nodePrincipal.origin);
+ } catch(e) {}
+ return;
+ }
+ if (!this._childDo("block", window)) throw e;
+ }
+ window._blockScriptForGlobal = true;
+ },
+ unblock: function(window) {
+ if (!window._blockScriptForGlobal) return;
+ try {
+ Cu.unblockScriptForGlobal(window);
+ } catch (e) {
+ if (this._childDo("unblock", window)) throw e;
+ }
+ window._blockScriptForGlobal = false;
+ },
+ isBlocked: function(window) {
+ return window._blockScriptForGlobal;
+ },
+ isDecided: function(window) {
+ return "_blockScriptForGlobal" in window;
+ },
+ get _childDo() {
+ return (this._childDo = IPC.parent && IPC.parent.mm && ("isCrossProcessWrapper" in Cu) ?
+ function(verb, window) {
+ if (Cu.isCrossProcessWrapper(window)) {
+ IPC.parent.mm.broadcastAsyncMessage("NoScript:WinScript", verb, { window: window });
+ return true;
+ }
+ return false;
+ }
+ : function() { return false; }
+ );
+ },
+ _domUtils: Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils),
+ patchStyle: function(doc) {
+ let ss = this._domUtils.getAllStyleSheets(doc);
+ // reverse loop because the preference stylesheet is almost always the last one
+ for (let j = ss.length; j-- > 0;) {
+ let s = ss[j];
+ switch(s.href) {
+
+ case "about:PreferenceStyleSheet":
+ {
+ let rules = s.cssRules;
+ // skip 1st & 2nd, as they are HTML & SVG namespaces
+ for (let j = 2, len = rules.length; j < len; j++) {
+ let r = rules[j];
+ if (r.cssText === "noscript { display: none ! important; }") {
+ s.deleteRule(j);
+ return;
+ }
+ }
+ }
+ break;
+ case "data:text/css,noscript%20{%20display%3A%20none%20!important%3B%20}":
+ case "resource://gre-resources/noscript.css":
+ doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils)
+ .loadSheetUsingURIString("data:text/css,noscript { display: initial !important }", 0);
+ return;
+ }
+ }
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/about.xul b/extensions/noscript/chrome/content/noscript/about.xul
new file mode 100644
index 0000000..b691856
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/about.xul
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?><?xml-stylesheet href="chrome://noscript/skin/about.css" type="text/css"?><!DOCTYPE dialog SYSTEM "chrome://noscript/locale/noscript.dtd">
+<dialog title="About NoScript" chromehidden="menubar toolbar location directories status extrachrome" id="genericAbout" onload="about_onload()" buttons="accept" xmlns:em="http://www.mozilla.org/2004/em-rdf#" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<script type="application/x-javascript" src="chrome://noscript/content/noscript.js"/>
+<script type="application/x-javascript">
+function about_onload() {
+ const strings=document.getElementById("about-strings");
+ const stringsFB=document.getElementById("about-stringsFB");
+ function stringFrom(bundle,key,parms) {
+ try {
+ return parms?bundle.getFormattedString(key,parms):bundle.getString(key);
+ } catch(ex) {
+ return null;
+ }
+ }
+
+ function getString(key,parms) {
+ var s=stringFrom(strings,key,parms);
+ return s ? s : stringFrom(stringsFB, key, parms);
+ }
+
+ function setString(id, attr, key) {
+ var s=getString(key || id);
+ if(!s) return;
+
+ var el=document.getElementById(id);
+ if(!el) return;
+ if(el.tagName=="description") {
+ el.firstChild.nodeValue=s;
+ return;
+ }
+ if(!attr) attr="value";
+ el.setAttribute(attr,s);
+ }
+
+ function tip(id) {
+ setString(id,"tooltiptext", id +".tip");
+ }
+
+ function label(id) {
+ setString(id);
+ tip(id);
+ }
+
+
+
+ window.focus();
+
+ var str = getString("aboutTitle",["NoScript"]);
+ if(str) document.title = str;
+ str = getString("version", ["5.1.8.5"]);
+ if(str) document.getElementById("extensionVersion").setAttribute("value", str);
+
+ setString("extensionDescription",null,"extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description");
+
+ label("extensionCreatorLabel");
+ label("extensionContributors");
+ label("license");
+ label("changelog");
+
+ tip("logo");
+ tip("sponsor");
+ tip("informaction");
+ tip("extensionHomepage");
+ tip("extensionCreator");
+}
+
+function about_open(url, features) {
+ noscriptUtil.browse(url, features);
+ window.close();
+}
+
+
+</script>
+<stringbundleset id="stringbundleset">
+<stringbundle id="about-strings" src="chrome://noscript/locale/about.properties"/>
+<stringbundle id="about-stringsFB" src="chrome://noscript/content/en-US/about.properties"/>
+</stringbundleset>
+<vbox id="clientBox">
+<vbox id="clientBoxInternal" flex="1">
+<hbox align="start">
+<vbox id="logoBox">
+<image id="logo" src="chrome://noscript/skin/icon80.png" class="text-link" tooltiptext="Visit Extension Home Page" onclick="about_open('https://noscript.net')"/>
+</vbox>
+<vbox flex="1">
+<hbox id="headBox" align="end">
+<vbox flex="1">
+<label value="NoScript" id="extensionName" crop="right"/>
+<label value="Version 5.1.8.5" id="extensionVersion" crop="right"/>
+</vbox>
+<vbox flex="1" align="end">
+<hbox align="end">
+<vbox>
+<image src="chrome://noscript/skin/ia.png" id="informaction" class="text-link" tooltiptext="Visit InformAction Home Page" onclick="about_open('http://www.informaction.com')"/>
+</vbox>
+</hbox>
+</vbox>
+</hbox>
+<spacer flex="1"/>
+<hbox id="creatorBox">
+<label id="extensionCreatorLabel" value="Author:"/>
+<label id="extensionCreator" class="text-link" tooltiptext="Visit Author Home Page" onclick="about_open('http://maone.net')" value="Giorgio Maone" flex="1"/>
+</hbox>
+</vbox>
+</hbox>
+<separator class="thin"/>
+<description id="extensionDescription">Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality... Experts will agree: Firefox is really safer with NoScript :-)</description>
+<separator class="thin"/>
+<label id="extensionContributors" value="Contributors:"/>
+<hbox flex="1">
+<vbox flex="1" id="contributorsBox">
+<description class="contributor" xmlns="">aivo (Estonian translation)</description>
+<description class="contributor" xmlns="">Alberto Martínez, EduLeo &amp; Urko (Spanish translation)</description>
+<description class="contributor" xmlns="">Algimantas MargeviÄius (Lithuanian translation)</description>
+<description class="contributor" xmlns="">Asaf Bartov &amp; baryoni (Hebrew translation)</description>
+<description class="contributor" xmlns="">Alf and Liesbeth (Dutch translation)</description>
+<description class="contributor" xmlns="">Alexander Sokolov, Sergei Smirnov and negodnik (Russian translation)</description>
+<description class="contributor" xmlns="">Batuhan Çetin, Volkan Gezer and eveterinary (Turkish translation)</description>
+<description class="contributor" xmlns="">Baurzhan Muftakhidinov (Kazakh translation)</description>
+<description class="contributor" xmlns="">Beerboy &amp; Haebaru (Japanese translation)</description>
+<description class="contributor" xmlns="">Carsten Winkler (Danish translation)</description>
+<description class="contributor" xmlns="">Chiou Po-Jung (Chinese Traditional translation)</description>
+<description class="contributor" xmlns="">Dario Ornelas (Portuguese translation)</description>
+<description class="contributor" xmlns="">drAcOniS and Petr Jirsa (Czech translation)</description>
+<description class="contributor" xmlns="">Drive DRKA and Dzmitry Drazdou (Belarusian translation)</description>
+<description class="contributor" xmlns="">Engin Yazılan, Erkan Kaplan &amp; Fathi (Turkish translation)</description>
+<description class="contributor" xmlns="">Georgi Marchev (Bulgarian translation)</description>
+<description class="contributor" xmlns="">Håvard Mork (Norwegian bokmål translation)</description>
+<description class="contributor" xmlns="">Hwasung Kim (Places bookmarklet patch)</description>
+<description class="contributor" xmlns="">Ivan Pesic, dragan021 (Serbian translation)</description>
+<description class="contributor" xmlns="">Ivan Jonoski (Macedonian translation)</description>
+<description class="contributor" xmlns="">Jameka (Swedish translation)</description>
+<description class="contributor" xmlns="">Joan-Josep Bargues (Catalan translation)</description>
+<description class="contributor" xmlns="">Joshua Issac (Malay translation)</description>
+<description class="contributor" xmlns="">Khaled Hosny &amp; Nassim Dhaher (Arabic translation)</description>
+<description class="contributor" xmlns="">Krcko (Croatian translation)</description>
+<description class="contributor" xmlns="">Ian Moody (English GB translation)</description>
+<description class="contributor" xmlns="">LocaLiceR (Hungarian translation)</description>
+<description class="contributor" xmlns="">Lukasz Biegaj &amp; Teo (Polish translation)</description>
+<description class="contributor" xmlns="">Michela Venuto (inspiration)</description>
+<description class="contributor" xmlns="">Mika Pirinen (Finnish translation)</description>
+<description class="contributor" xmlns="">Mindaugas Jakutis (Lithuanian translation)</description>
+<description class="contributor" xmlns="">Mikes Kaszmán István (Hungarian translation)</description>
+<description class="contributor" xmlns="">MozUA (Ukrainian translation)</description>
+<description class="contributor" xmlns="">Pedram Veisi (Persian translation)</description>
+<description class="contributor" xmlns="">Peter Bradley (Welsh translation)</description>
+<description class="contributor" xmlns="">Raryel Costa Souza (Brazilian Portuguese)</description>
+<description class="contributor" xmlns="">regfreak (Indonesian translation)</description>
+<description class="contributor" xmlns="">roebek (Galician translation)</description>
+<description class="contributor" xmlns="">Qen (Thai translation)</description>
+<description class="contributor" xmlns="">seaousak (Korean translation)</description>
+<description class="contributor" xmlns="">SlovakSoft (Slovak translation)</description>
+<description class="contributor" xmlns="">Sonickydon (Greek translation)</description>
+<description class="contributor" xmlns="">Stiepan A. Kovac (Croatian translation)</description>
+<description class="contributor" xmlns="">swarnava (Bengali translation)</description>
+<description class="contributor" xmlns="">Tomaz Macus (Slovenian translation)</description>
+<description class="contributor" xmlns="">Thomas, milupo &amp; Volker Hable (German translation)</description>
+<description class="contributor" xmlns="">tonynguyen and loveleeyoungae (Vietnamese translation)</description>
+<description class="contributor" xmlns="">x10firefox and Ultravioletu (Romanian translation)</description>
+<description class="contributor" xmlns="">Xavier Robin &amp; BlackJack (French translation)</description>
+<description class="contributor" xmlns="">X.F Mao &amp; George C. Tsoi (Simplified Chinese)</description>
+</vbox>
+</hbox>
+<hbox>
+<label id="license" class="text-link" tooltiptext="Read end-user license" onclick="about_open('chrome://noscript/content/NoScript_License.txt')">License</label>
+<spacer flex="1"/>
+<label id="changelog" class="text-link" align="center" tooltiptext="See Changelog" onclick="about_open('https://noscript.net/changelog#5.1.8.5')">Changelog</label>
+<spacer flex="1"/>
+<label id="extensionHomepage" class="text-link" tooltiptext="Visit Extension Home Page" onclick="about_open('https://noscript.net')">https://noscript.net</label>
+</hbox>
+</vbox>
+</vbox>
+</dialog>
diff --git a/extensions/noscript/chrome/content/noscript/antlr.js b/extensions/noscript/chrome/content/noscript/antlr.js
new file mode 100644
index 0000000..d354663
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/antlr.js
@@ -0,0 +1,11 @@
+/*
+Copyright (c) 2003-2008 Terence Parr. All rights reserved.
+Code licensed under the BSD License:
+http://www.antlr.org/license.html
+
+Some parts of the ANTLR class:
+Copyright (c) 2008, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+*/
+if(typeof org=="undefined"||!org){var org={}}if(typeof org.antlr=="undefined"||!org.antlr){org.antlr={}}org.antlr.global=(function(){return this}).call(null);org.antlr.namespace=function(){var A=arguments,E=null,C,B,D;for(C=0;C<A.length;C=C+1){D=A[C].split(".");E=org.antlr.global;for(B=0;B<D.length;B=B+1){E[D[B]]=E[D[B]]||{};E=E[D[B]]}}return E};org.antlr.env=org.antlr.env||{};org.antlr.env.ua=function(){var D={ie:0,opera:0,gecko:0,webkit:0,mobile:null,air:0,rhino:false};var B,A;try{B=navigator.userAgent;if((/KHTML/).test(B)){D.webkit=1}A=B.match(/AppleWebKit\/([^\s]*)/);if(A&&A[1]){D.webkit=parseFloat(A[1]);if(/ Mobile\//.test(B)){D.mobile="Apple"}else{A=B.match(/NokiaN[^\/]*/);if(A){D.mobile=A[0]}}A=B.match(/AdobeAIR\/([^\s]*)/);if(A){D.air=A[0]}}if(!D.webkit){A=B.match(/Opera[\s\/]([^\s]*)/);if(A&&A[1]){D.opera=parseFloat(A[1]);A=B.match(/Opera Mini[^;]*/);if(A){D.mobile=A[0]}}else{A=B.match(/MSIE\s([^;]*)/);if(A&&A[1]){D.ie=parseFloat(A[1])}else{A=B.match(/Gecko\/([^\s]*)/);if(A){D.gecko=1;A=B.match(/rv:([^\s\)]*)/);if(A&&A[1]){D.gecko=parseFloat(A[1])}}}}}}catch(C){}try{if(typeof window=="undefined"&&loadClass){D.rhino=true}}catch(C){}return D}();org.antlr.namespace("org.antlr.runtime.tree");org.antlr.lang=org.antlr.lang||{isArray:function(B){if(B){var A=org.antlr.lang;return A.isNumber(B.length)&&A.isFunction(B.splice)}return false},isBoolean:function(A){return typeof A==="boolean"},isFunction:function(A){return typeof A==="function"},isNull:function(A){return A===null},isNumber:function(A){return typeof A==="number"&&isFinite(A)},isObject:function(A){return(A&&(typeof A==="object"||org.antlr.lang.isFunction(A)))||false},isString:function(A){return typeof A==="string"},isUndefined:function(A){return typeof A==="undefined"},_IEEnumFix:function(C,B){if(org.antlr.env.ua.ie){var E=["toString","valueOf"],A;for(A=0;A<E.length;A=A+1){var F=E[A],D=B[F];if(org.antlr.lang.isFunction(D)&&D!=Object.prototype[F]){C[F]=D}}}},extend:function(D,E,C){if(!E||!D){throw new Error("org.antlr.lang.extend failed, please check that all dependencies are included.")}var B=function(){};B.prototype=E.prototype;D.prototype=new B();D.prototype.constructor=D;D.superclass=E.prototype;if(E.prototype.constructor==Object.prototype.constructor){E.prototype.constructor=E}if(C){for(var A in C){D.prototype[A]=C[A]}org.antlr.lang._IEEnumFix(D.prototype,C)}},augmentObject:function(E,D){if(!D||!E){throw new Error("Absorb failed, verify dependencies.")}var A=arguments,C,F,B=A[2];if(B&&B!==true){for(C=2;C<A.length;C=C+1){E[A[C]]=D[A[C]]}}else{for(F in D){if(B||!E[F]){E[F]=D[F]}}org.antlr.lang._IEEnumFix(E,D)}},augmentProto:function(D,C){if(!C||!D){throw new Error("Augment failed, verify dependencies.")}var A=[D.prototype,C.prototype];for(var B=2;B<arguments.length;B=B+1){A.push(arguments[B])}org.antlr.lang.augmentObject.apply(this,A)},merge:function(){var D={},B=arguments;for(var C=0,A=B.length;C<A;C=C+1){org.antlr.lang.augmentObject(D,B[C],true)}return D},isValue:function(B){var A=org.antlr.lang;return(A.isObject(B)||A.isString(B)||A.isNumber(B)||A.isBoolean(B))},array:{peek:function(B){if(!org.antlr.lang.isArray(B)){throw new Error("org.antlr.lang.array.peek: a is not an array.")}var A=B.length;if(A<=0){throw new Error("org.antlr.lang.array.peek: a is empty.")}return B[A-1]}}};org.antlr.runtime.RecognizerSharedState=function(){this.following=[];this._fsp=-1;this.errorRecovery=false;this.lastErrorIndex=-1;this.failed=false;this.syntaxErrors=0;this.backtracking=0;this.ruleMemo=null;this.token=null;this.tokenStartCharIndex=-1;this.text=null};org.antlr.runtime.IndexOutOfBoundsException=function(A){org.antlr.runtime.IndexOutOfBoundsException.superclass.constructor.call(this,A)};org.antlr.lang.extend(org.antlr.runtime.IndexOutOfBoundsException,Error,{name:"org.antlr.runtime.IndexOutOfBoundsException"});org.antlr.runtime.RecognitionException=function(A){org.antlr.runtime.RecognitionException.superclass.constructor.call(this);this.input=A;this.index=A.index();if(A instanceof org.antlr.runtime.CommonTokenStream){this.token=A.LT(1);this.line=this.token.getLine();this.charPositionInLine=this.token.getCharPositionInLine()}if(A instanceof org.antlr.runtime.tree.TreeNodeStream){this.extractInformationFromTreeNodeStream(A)}else{if(A instanceof org.antlr.runtime.ANTLRStringStream){this.c=A.LA(1);this.line=A.getLine();this.charPositionInLine=A.getCharPositionInLine()}else{this.c=A.LA(1)}}this.message=this.toString()};org.antlr.lang.extend(org.antlr.runtime.RecognitionException,Error,{input:null,index:null,token:null,node:null,c:null,line:null,name:"org.antlr.runtime.RecognitionException",charPositionInLine:null,approximateLineInfo:null,extractInformationFromTreeNodeStream:function(F){var A=F,E,I,D,H,C;this.node=A.LT(1);var B=A.getTreeAdaptor(),G=B.getToken(this.node);if(G){this.token=G;if(G.getLine()<=0){C=-1;E=A.LT(C);while(E){priorPayload=B.getToken(E);if(priorPayload&&priorPayload.getLine()>0){this.line=priorPayload.getLine();this.charPositionInLine=priorPayload.getCharPositionInLine();this.approximateLineInfo=true;break}--C;E=A.LT(C)}}else{this.line=G.getLine();this.charPositionInLine=G.getCharPositionInLine()}}else{if(this.node instanceof org.antlr.runtime.tree.CommonTree){this.line=this.node.getLine();this.charPositionInLine=this.node.getCharPositionInLine();if(this.node instanceof org.antlr.runtime.tree.CommonTree){this.token=this.node.token}}else{D=B.getType(this.node);H=B.getText(this.node);this.token=new org.antlr.runtime.CommonToken(D,H)}}},getUnexpectedType:function(){if(this.input instanceof org.antlr.runtime.CommonTokenStream){return this.token.getType()}else{if(this.input instanceof org.antlr.runtime.tree.TreeNodeStream){var A=this.input;var B=A.getTreeAdaptor();return B.getType(this.node)}else{return this.c}}}});org.antlr.runtime.MismatchedTokenException=function(B,A){if(arguments.length===0){this.expecting=org.antlr.runtime.Token.INVALID_TOKEN_TYPE}else{org.antlr.runtime.MismatchedTokenException.superclass.constructor.call(this,A);this.expecting=B}};org.antlr.lang.extend(org.antlr.runtime.MismatchedTokenException,org.antlr.runtime.RecognitionException,{toString:function(){return"MismatchedTokenException("+this.getUnexpectedType()+"!="+this.expecting+")"},name:"org.antlr.runtime.MismatchedTokenException"});org.antlr.runtime.UnwantedTokenException=function(B,A){if(arguments.length>0){org.antlr.runtime.UnwantedTokenException.superclass.constructor.call(this,B,A)}};org.antlr.lang.extend(org.antlr.runtime.UnwantedTokenException,org.antlr.runtime.MismatchedTokenException,{getUnexpectedToken:function(){return this.token},toString:function(){var A=", expected "+this.expecting;if(this.expecting===org.antlr.runtime.Token.INVALID_TOKEN_TYPE){A=""}if(!org.antlr.lang.isValue(this.token)){return"UnwantedTokenException(found="+A+")"}return"UnwantedTokenException(found="+this.token.getText()+A+")"},name:"org.antlr.runtime.UnwantedTokenException"});org.antlr.runtime.MissingTokenException=function(B,A,C){if(arguments.length>0){org.antlr.runtime.MissingTokenException.superclass.constructor.call(this,B,A);this.inserted=C}};org.antlr.lang.extend(org.antlr.runtime.MissingTokenException,org.antlr.runtime.MismatchedTokenException,{getMissingType:function(){return this.expecting},toString:function(){if(org.antlr.lang.isValue(this.inserted)&&org.antlr.lang.isValue(this.token)){return"MissingTokenException(inserted "+this.inserted+" at "+this.token.getText()+")"}if(org.antlr.lang.isValue(this.token)){return"MissingTokenException(at "+this.token.getText()+")"}return"MissingTokenException"},name:"org.antlr.runtime.MissingTokenException"});org.antlr.runtime.NoViableAltException=function(C,B,D,A){org.antlr.runtime.NoViableAltException.superclass.constructor.call(this,A);this.grammarDecisionDescription=C;this.decisionNumber=B;this.stateNumber=D};org.antlr.lang.extend(org.antlr.runtime.NoViableAltException,org.antlr.runtime.RecognitionException,{toString:function(){if(this.input instanceof org.antlr.runtime.ANTLRStringStream){return"NoViableAltException('"+this.getUnexpectedType()+"'@["+this.grammarDecisionDescription+"])"}else{return"NoViableAltException("+this.getUnexpectedType()+"@["+this.grammarDecisionDescription+"])"}},name:"org.antlr.runtime.NoViableAltException"});org.antlr.runtime.EarlyExitException=function(B,A){org.antlr.runtime.EarlyExitException.superclass.constructor.call(this,A);this.decisionNumber=B};org.antlr.lang.extend(org.antlr.runtime.EarlyExitException,org.antlr.runtime.RecognitionException,{name:"org.antlr.runtime.EarlyExitException"});org.antlr.runtime.MismatchedSetException=function(B,A){org.antlr.runtime.MismatchedSetException.superclass.constructor.call(this,A);this.expecting=B};org.antlr.lang.extend(org.antlr.runtime.MismatchedSetException,org.antlr.runtime.RecognitionException,{toString:function(){return"MismatchedSetException("+this.getUnexpectedType()+"!="+this.expecting+")"},name:"org.antlr.runtime.MismatchedSetException"});org.antlr.runtime.MismatchedNotSetException=function(B,A){org.antlr.runtime.MismatchedNotSetException.superclass.constructor.call(this,B,A)};org.antlr.lang.extend(org.antlr.runtime.MismatchedNotSetException,org.antlr.runtime.MismatchedSetException,{toString:function(){return"MismatchedNotSetException("+this.getUnexpectedType()+"!="+this.expecting+")"},name:"org.antlr.runtime.MismatchedNotSetException"});org.antlr.runtime.MismatchedRangeException=function(B,A,C){if(arguments.length===0){return this}org.antlr.runtime.MismatchedRangeException.superclass.constructor.call(this,C);this.a=B;this.b=A};org.antlr.lang.extend(org.antlr.runtime.MismatchedRangeException,org.antlr.runtime.RecognitionException,{toString:function(){return"MismatchedRangeException("+this.getUnexpectedType()+" not in ["+this.a+","+this.b+"])"},name:"org.antlr.runtime.MismatchedRangeException"});org.antlr.runtime.FailedPredicateException=function(A,C,B){org.antlr.runtime.FailedPredicateException.superclass.constructor.call(this,A);this.ruleName=C;this.predicateText=B};org.antlr.lang.extend(org.antlr.runtime.FailedPredicateException,org.antlr.runtime.RecognitionException,{toString:function(){return"FailedPredicateException("+this.ruleName+",{"+this.predicateText+"}?)"},name:"org.antlr.runtime.FailedPredicateException"});org.antlr.runtime.BitSet=function(A){if(!A){A=org.antlr.runtime.BitSet.BITS}if(org.antlr.lang.isArray(A)){this.bits=A}else{if(org.antlr.lang.isNumber(A)){this.bits=[]}}};org.antlr.lang.augmentObject(org.antlr.runtime.BitSet,{BITS:32,LOG_BITS:5,MOD_MASK:31,bitMask:function(B){var A=B&org.antlr.runtime.BitSet.MOD_MASK;return 1<<A},numWordsToHold:function(A){return(A>>org.antlr.runtime.BitSet.LOG_BITS)+1},wordNumber:function(A){return A>>org.antlr.runtime.BitSet.LOG_BITS},of:function(D,A){var B,F,C,E;if(org.antlr.lang.isNumber(D)){if(org.antlr.lang.isNumber(A)){C=new org.antlr.runtime.BitSet(A+1);for(B=D;B<=A;B++){F=org.antlr.runtime.BitSet.wordNumber(B);C.bits[F]|=org.antlr.runtime.BitSet.bitMask(B)}return C}else{C=new org.antlr.runtime.BitSet(D+1);C.add(D);return C}}else{if(org.antlr.lang.isArray(D)){C=new org.antlr.runtime.BitSet();for(B=D.length-1;B>=0;B--){C.add(D[B])}return C}else{if(D instanceof org.antlr.runtime.BitSet){if(!D){return null}return D}else{if(D instanceof org.antlr.runtime.IntervalSet){if(!D){return null}C=new org.antlr.runtime.BitSet();C.addAll(D);return C}else{if(org.antlr.lang.isObject(D)){E=[];for(B in D){if(org.antlr.lang.isNumber(B)){E.push(B)}}return org.antlr.runtime.BitSet.of(E)}}}}}}});org.antlr.runtime.BitSet.prototype={add:function(A){var B=org.antlr.runtime.BitSet.wordNumber(A);if(B>=this.bits.length){this.growToInclude(A)}this.bits[B]|=org.antlr.runtime.BitSet.bitMask(A)},addAll:function(C){var A,B,D;if(C instanceof org.antlr.runtime.BitSet){this.orInPlace(C)}else{if(C instanceof org.antlr.runtime.IntervalSet){A=C}else{if(org.antlr.lang.isArray(C)){for(B=0;B<C.length;B++){D=C[B];this.add(D)}}else{return }}}},and:function(A){var B=this.clone();B.andInPlace(A);return B},andInPlace:function(A){var C=Math.min(this.bits.length,A.bits.length),B;for(B=C-1;B>=0;B--){this.bits[B]&=A.bits[B]}for(B=C;B<this.bits.length;B++){this.bits[B]=0}},clear:function(B){if(arguments.length===0){var A;for(A=this.bits.length-1;A>=0;A--){this.bits[A]=0}return }var C=org.antlr.runtime.BitSet.wordNumber(B);if(C>=this.bits.length){this.growToInclude(B)}this.bits[C]&=~org.antlr.runtime.BitSet.bitMask(B)},clone:function(){var C,B,A=[];for(C=0,B=this.bits.length;C<B;C++){A[C]=this.bits[C]}return new org.antlr.runtime.BitSet(A)},size:function(){var B=0,A,C,D;for(A=this.bits.length-1;A>=0;A--){C=this.bits[A];if(C!==0){for(D=org.antlr.runtime.BitSet.BITS-1;D>=0;D--){if((C&(1<<D))!==0){B++}}}}return B},equals:function(A){if(!A||!(A instanceof org.antlr.runtime.BitSet)){return false}var B=A,C,D=Math.min(this.bits.length,B.bits.length);for(C=0;C<D;C++){if(this.bits[C]!=B.bits[C]){return false}}if(this.bits.length>D){for(C=D+1;C<this.bits.length;C++){if(this.bits[C]!==0){return false}}}else{if(B.bits.length>D){for(C=D+1;C<B.bits.length;C++){if(B.bits[C]!==0){return false}}}}return true},growToInclude:function(D){var A=Math.max(this.bits.length<<1,org.antlr.runtime.BitSet.numWordsToHold(D)),C=[],B;for(B=0,len=this.bits.length;B<len;B++){C[B]=this.bits[B]}this.bits=C},member:function(A){var B=org.antlr.runtime.BitSet.wordNumber(A);if(B>=this.bits.length){return false}return(this.bits[B]&org.antlr.runtime.BitSet.bitMask(A))!==0},getSingleElement:function(){var A;for(A=0;A<(this.bits.length<<org.antlr.runtime.BitSet.LOG_BITS);A++){if(this.member(A)){return A}}return -1},isNil:function(){var A;for(A=this.bits.length-1;A>=0;A--){if(this.bits[A]!==0){return false}}return true},complement:function(B){if(B){return B.subtract(this)}else{var A=this.clone();A.notInPlace();return A}},notInPlace:function(){var A,D,B,C;if(arguments.length===0){for(B=this.bits.length-1;B>=0;B--){this.bits[B]=~this.bits[B]}}else{if(arguments.length===1){A=0;D=arguments[0]}else{A=arguments[0];D=arguments[1]}this.growToInclude(D);for(B=A;B<=D;B++){C=org.antlr.runtime.BitSet.wordNumber(B);this.bits[C]^=org.antlr.runtime.BitSet.bitMask(B)}}},or:function(A){if(!A){return this}var B=this.clone();B.orInPlace(A);return B},orInPlace:function(A){if(!A){return }if(A.bits.length>this.bits.length){this.setSize(A.bits.length)}var C=Math.min(this.bits.length,A.bits.length),B;for(B=C-1;B>=0;B--){this.bits[B]|=A.bits[B]}},remove:function(A){var B=org.antlr.runtime.BitSet.wordNumber(A);if(B>=this.bits.length){this.growToInclude(A)}this.bits[B]&=~org.antlr.runtime.BitSet.bitMask(A)},setSize:function(A){var B=A-this.bits.length;while(B>=0){this.bits.push(0);B--}},numBits:function(){return this.bits.length<<org.antlr.runtime.BitSet.LOG_BITS},lengthInLongWords:function(){return this.bits.length},subset:function(A){if(!A){return false}return this.and(A).equals(this)},subtractInPlace:function(A){if(!A){return }var B;for(B=0;B<this.bits.length&&B<A.bits.length;B++){this.bits[B]&=~A.bits[B]}},subtract:function(A){if(!A||!(A instanceof org.antlr.runtime.BitSet)){return null}var B=this.clone();B.subtractInPlace(A);return B},toArray:function(){var A=[],C,B=0;for(C=0;C<(this.bits.length<<org.antlr.runtime.BitSet.LOG_BITS);C++){if(this.member(C)){A[B++]=C}}return A},toPackedArray:function(){return this.bits},toString:function(){if(arguments.length===0){return this.toString1(null)}else{if(org.antlr.lang.isString(arguments[0])){if(!org.antlr.lang.isValue(arguments[1])){return this.toString1(null)}else{return this.toString2(arguments[0],arguments[1])}}else{return this.toString1(arguments[0])}}},toString1:function(D){var A="{",E=",",B,C=false;for(B=0;B<(this.bits.length<<org.antlr.runtime.BitSet.LOG_BITS);B++){if(this.member(B)){if(B>0&&C){A+=E}if(D){A+=D.getTokenDisplayName(B)}else{A+=B.toString()}C=true}}return A+"}"},toString2:function(C,B){var D="",A;for(A=0;A<(this.bits.length<<org.antlr.runtime.BitSet.LOG_BITS);A++){if(this.member(A)){if(D.length>0){D+=C}if(A>=B.size()){D+="'"+A+"'"}else{if(!org.antlr.lang.isValue(B.get(A))){D+="'"+A+"'"}else{D+=B.get(A)}}}}return D}};org.antlr.runtime.CharStream={EOF:-1};org.antlr.runtime.CommonToken=function(){var A;this.charPositionInLine=-1;this.channel=0;this.index=-1;if(arguments.length==1){if(org.antlr.lang.isNumber(arguments[0])){this.type=arguments[0]}else{A=arguments[0];this.text=A.getText();this.type=A.getType();this.line=A.getLine();this.index=A.getTokenIndex();this.charPositionInLine=A.getCharPositionInLine();this.channel=A.getChannel();if(A instanceof org.antlr.runtime.CommonToken){this.start=A.start;this.stop=A.stop}}}else{if(arguments.length==2){this.type=arguments[0];this.text=arguments[1];this.channel=0}else{if(arguments.length==5){this.input=arguments[0];this.type=arguments[1];this.channel=arguments[2];this.start=arguments[3];this.stop=arguments[4]}}}};org.antlr.runtime.CommonToken.prototype={getType:function(){return this.type},setLine:function(A){this.line=A},getText:function(){if(org.antlr.lang.isString(this.text)){return this.text}if(!this.input){return null}this.text=this.input.substring(this.start,this.stop);return this.text},setText:function(A){this.text=A},getLine:function(){return this.line},getCharPositionInLine:function(){return this.charPositionInLine},setCharPositionInLine:function(A){this.charPositionInLine=A},getChannel:function(){return this.channel},setChannel:function(A){this.channel=A},setType:function(A){this.type=A},getStartIndex:function(){return this.start},setStartIndex:function(A){this.start=A},getStopIndex:function(){return this.stop},setStopIndex:function(A){this.stop=A},getTokenIndex:function(){return this.index},setTokenIndex:function(A){this.index=A},getInputStream:function(){return this.input},setInputStream:function(A){this.input=A},toString:function(){var B="";if(this.channel>0){B=",channel="+this.channel}var A=this.getText();if(!org.antlr.lang.isNull(A)){A=A.replace(/\n/g,"\\\\n");A=A.replace(/\r/g,"\\\\r");A=A.replace(/\t/g,"\\\\t")}else{A="<no text>"}return"[@"+this.getTokenIndex()+","+this.start+":"+this.stop+"='"+A+"',<"+this.type+">"+B+","+this.line+":"+this.getCharPositionInLine()+"]"}};org.antlr.runtime.Token=function(){};org.antlr.lang.augmentObject(org.antlr.runtime.Token,{EOR_TOKEN_TYPE:1,DOWN:2,UP:3,MIN_TOKEN_TYPE:4,EOF:org.antlr.runtime.CharStream.EOF,EOF_TOKEN:new org.antlr.runtime.CommonToken(org.antlr.runtime.CharStream.EOF),INVALID_TOKEN_TYPE:0,INVALID_TOKEN:new org.antlr.runtime.CommonToken(0),SKIP_TOKEN:new org.antlr.runtime.CommonToken(0),DEFAULT_CHANNEL:0,HIDDEN_CHANNEL:99});org.antlr.lang.augmentObject(org.antlr.runtime.CommonToken,org.antlr.runtime.Token);org.antlr.runtime.tree.RewriteCardinalityException=function(A){this.elementDescription=A};org.antlr.lang.extend(org.antlr.runtime.tree.RewriteCardinalityException,Error,{getMessage:function(){if(org.antlr.lang.isString(this.elementDescription)){return this.elementDescription}return null},name:function(){return"org.antlr.runtime.tree.RewriteCardinalityException"}});org.antlr.runtime.tree.RewriteEmptyStreamException=function(B){var A=org.antlr.runtime.tree.RewriteEmptyStreamException.superclass;A.constructor.call(this,B)};org.antlr.lang.extend(org.antlr.runtime.tree.RewriteEmptyStreamException,org.antlr.runtime.tree.RewriteCardinalityException,{name:function(){return"org.antlr.runtime.tree.RewriteEmptyStreamException"}});org.antlr.runtime.tree.RewriteEarlyExitException=function(B){var A=org.antlr.runtime.tree.RewriteEarlyExitException.superclass;if(org.antlr.lang.isUndefined(B)){B=null}A.constructor.call(this,B)};org.antlr.lang.extend(org.antlr.runtime.tree.RewriteEarlyExitException,org.antlr.runtime.tree.RewriteCardinalityException,{name:function(){return"org.antlr.runtime.tree.RewriteEarlyExitException"}});org.antlr.runtime.MismatchedTreeNodeException=function(B,A){if(B&&A){org.antlr.runtime.MismatchedTreeNodeException.superclass.constructor.call(this,A);this.expecting=B}};org.antlr.lang.extend(org.antlr.runtime.MismatchedTreeNodeException,org.antlr.runtime.RecognitionException,{toString:function(){return"MismatchedTreeNodeException("+this.getUnexpectedType()+"!="+this.expecting+")"},name:"org.antlr.runtime.MismatchedTreeNodeException"});org.antlr.runtime.tree.BaseTree=function(){};org.antlr.runtime.tree.BaseTree.prototype={getChild:function(A){if(!this.children||A>=this.children.length){return null}return this.children[A]},getChildren:function(){return this.children},getFirstChildWithType:function(C){var B,A;for(B=0;this.children&&B<this.children.length;B++){A=this.children[B];if(A.getType()===C){return A}}return null},getChildCount:function(){if(!this.children){return 0}return this.children.length},addChild:function(B){if(!org.antlr.lang.isValue(B)){return }var C=B,E,A,D;if(C.isNil()){if(this.children&&this.children==C.children){throw new Error("attempt to add child list to itself")}if(C.children){if(this.children){E=C.children.length;for(A=0;A<E;A++){D=C.children[A];this.children.push(D);D.setParent(this);D.setChildIndex(this.children.length-1)}}else{this.children=C.children;this.freshenParentAndChildIndexes()}}}else{if(!this.children){this.children=this.createChildrenList()}this.children.push(B);C.setParent(this);C.setChildIndex(this.children.length-1)}},addChildren:function(A){var C,B;for(C=0;C<A.length;C++){B=A[C];this.addChild(B)}},setChild:function(B,A){if(!A){return }if(A.isNil()){throw new Error("Can't set single child to a list")}if(!this.children){this.children=this.createChildrenList()}this.children[B]=A;A.setParent(this);A.setChildIndex(B)},deleteChild:function(B){if(!this.children){return null}if(B<0||B>=this.children.length){throw new Error("Index out of bounds.")}var A=this.children.splice(B,1)[0];this.freshenParentAndChildIndexes(B);return A},replaceChildren:function(H,I,P){if(!this.children){throw new Error("indexes invalid; no children in list")}var O=I-H+1;var A;var K=P;var D=null;if(K.isNil()){D=K.children}else{D=[];D.push(K)}A=D.length;var B=D.length;var N=O-A;var F,G,C,E,M,J,L;if(N===0){F=0;for(G=H;G<=I;G++){C=D[F];this.children[G]=C;C.setParent(this);C.setChildIndex(G);F++}}else{if(N>0){for(F=0;F<B;F++){this.children[H+F]=D[F]}E=H+B;for(M=E;M<=I;M++){J=this.children.splice(E,1)[0]}this.freshenParentAndChildIndexes(H)}else{for(F=0;F<O;F++){this.children[H+F]=D[F]}L=A-O;for(F=O;F<A;F++){this.children.splice(H+F,0,D[F])}this.freshenParentAndChildIndexes(H)}}},createChildrenList:function(){return[]},isNil:function(){return false},freshenParentAndChildIndexes:function(A){if(!org.antlr.lang.isNumber(A)){A=0}var D=this.getChildCount(),C,B;for(C=A;C<D;C++){B=this.getChild(C);B.setChildIndex(C);B.setParent(this)}},sanityCheckParentAndChildIndexes:function(B,A){if(arguments.length===0){B=null;A=-1}if(B!==this.getParent()){throw new Error("parents don't match; expected "+B+" found "+this.getParent())}if(A!==this.getChildIndex()){throw new Error("child indexes don't match; expected "+A+" found "+this.getChildIndex())}var E=this.getChildCount(),D,C;for(D=0;D<E;D++){C=this.getChild(D);C.sanityCheckParentAndChildIndexes(this,D)}},getChildIndex:function(){return 0},setChildIndex:function(A){},getParent:function(){return null},setParent:function(A){},getTree:function(){return this},toStringTree:function(){if(!this.children||this.children.length===0){return this.toString()}var A="",C,B;if(!this.isNil()){A+="(";A+=this.toString();A+=" "}for(C=0;this.children&&C<this.children.length;C++){B=this.children[C];if(C>0){A+=" "}A+=B.toStringTree()}if(!this.isNil()){A+=")"}return A},getLine:function(){return 0},getCharPositionInLine:function(){return 0}};org.antlr.runtime.tree.CommonTree=function(A){this.startIndex=-1;this.stopIndex=-1;this.childIndex=-1;this.parent=null;this.token=null;if(A instanceof org.antlr.runtime.tree.CommonTree){org.antlr.runtime.tree.CommonTree.superclass.constructor.call(this,A);this.token=A.token;this.startIndex=A.startIndex;this.stopIndex=A.stopIndex}else{if(A instanceof org.antlr.runtime.CommonToken){this.token=A}}};org.antlr.lang.extend(org.antlr.runtime.tree.CommonTree,org.antlr.runtime.tree.BaseTree,{getToken:function(){return this.token},dupNode:function(){return new org.antlr.runtime.tree.CommonTree(this)},isNil:function(){return !this.token},getType:function(){if(!this.token){return org.antlr.runtime.Token.INVALID_TOKEN_TYPE}return this.token.getType()},getText:function(){if(!this.token){return null}return this.token.getText()},getLine:function(){if(!this.token||this.token.getLine()===0){if(this.getChildCount()>0){return this.getChild(0).getLine()}return 0}return this.token.getLine()},getCharPositionInLine:function(){if(!this.token||this.token.getCharPositionInLine()===-1){if(this.getChildCount()>0){return this.getChild(0).getCharPositionInLine()}return 0}return this.token.getCharPositionInLine()},getTokenStartIndex:function(){if(this.token){return this.token.getTokenIndex()}return this.startIndex},setTokenStartIndex:function(A){this.startIndex=A},getTokenStopIndex:function(){if(this.token){return this.token.getTokenIndex()}return this.stopIndex},setTokenStopIndex:function(A){this.stopIndex=A},getChildIndex:function(){return this.childIndex},getParent:function(){return this.parent},setParent:function(A){this.parent=A},setChildIndex:function(A){this.childIndex=A},toString:function(){if(this.isNil()){return"nil"}if(this.getType()===org.antlr.runtime.Token.INVALID_TOKEN_TYPE){return"<errornode>"}if(!this.token){return null}return this.token.getText()}});org.antlr.runtime.tree.Tree={INVALID_NODE:new org.antlr.runtime.tree.CommonTree(org.antlr.runtime.Token.INVALID_TOKEN)};org.antlr.runtime.tree.CommonErrorNode=function(A,D,B,C){if(!B||(B.getTokenIndex()<D.getTokenIndex()&&B.getType()!=org.antlr.runtime.Token.EOF)){B=D}this.input=A;this.start=D;this.stop=B;this.trappedException=C};org.antlr.lang.extend(org.antlr.runtime.tree.CommonErrorNode,org.antlr.runtime.tree.CommonTree,{isNil:function(){return false},getType:function(){return org.antlr.runtime.Token.INVALID_TOKEN_TYPE},getText:function(){var C=null;if(this.start instanceof org.antlr.runtime.CommonToken){var B=this.start.getTokenIndex();var A=this.stop.getTokenIndex();if(this.stop.getType()===org.antlr.runtime.Token.EOF){A=this.input.size()}C=this.input.toString(B,A)}else{if(this.start instanceof org.antlr.runtime.tree.CommonTree){C=this.input.toString(this.start,this.stop)}else{C="<unknown>"}}return C},toString:function(){if(this.trappedException instanceof org.antlr.runtime.MissingTokenException){return"<missing type: "+this.trappedException.getMissingType()+">"}else{if(this.trappedException instanceof org.antlr.runtime.UnwantedTokenException){return"<extraneous: "+this.trappedException.getUnexpectedToken()+", resync="+this.getText()+">"}else{if(this.trappedException instanceof org.antlr.runtime.MismatchedTokenException){return"<mismatched token: "+this.trappedException.token+", resync="+this.getText()+">"}else{if(this.trappedException instanceof org.antlr.runtime.NoViableAltException){return"<unexpected: "+this.trappedException.token+", resync="+this.getText()+">"}}}}return"<error: "+this.getText()+">"}});org.antlr.runtime.tree.BaseTreeAdaptor=function(){this.uniqueNodeID=1};org.antlr.runtime.tree.BaseTreeAdaptor.prototype={nil:function(){return this.create(null)},errorNode:function(A,E,C,D){var B=new org.antlr.runtime.tree.CommonErrorNode(A,E,C,D);return B},isNil:function(A){return A.isNil()},dupTree:function(B,C){if(arguments.length===1){C=null}if(!B){return null}var D=this.dupNode(B);this.setChildIndex(D,this.getChildIndex(B));this.setParent(D,C);var G=this.getChildCount(B),A,F,E;for(A=0;A<G;A++){F=this.getChild(B,A);E=this.dupTree(F,B);this.addChild(D,E)}return D},addChild:function(A,B){if(A&&org.antlr.lang.isValue(B)){A.addChild(B)}},becomeRoot:function(D,C){if(D instanceof org.antlr.runtime.CommonToken||!D){D=this.create(D)}var A=D,B=C;if(!C){return D}if(A.isNil()){if(A.getChildCount()>1){throw new Error("more than one node as root (TODO: make exception hierarchy)")}A=A.getChild(0)}A.addChild(B);return A},rulePostProcessing:function(A){var B=A;if(B&&B.isNil()){if(B.getChildCount()===0){B=null}else{if(B.getChildCount()===1){B=B.getChild(0);B.setParent(null);B.setChildIndex(-1)}}}return B},create:function(C,B){var D,A;if(arguments.length===2){if(org.antlr.lang.isString(arguments[1])){D=arguments[1];B=this.createToken(C,D);A=this.create(B);return A}else{B=this.createToken(B);B.setType(C);A=this.create(B);return A}}else{if(arguments.length===3){D=arguments[2];B=this.createToken(B);B.setType(C);B.setText(D);A=this.create(B);return A}}},getType:function(A){A.getType();return 0},setType:function(A,B){throw new Error("don't know enough about Tree node")},getText:function(A){return A.getText()},setText:function(A,B){throw new Error("don't know enough about Tree node")},getChild:function(B,A){return B.getChild(A)},setChild:function(B,A,C){B.setChild(A,C)},deleteChild:function(B,A){return B.deleteChild(A)},getChildCount:function(A){return A.getChildCount()},getUniqueID:function(B){if(!this.treeToUniqueIDMap){this.treeToUniqueIDMap={}}var C=this.treeToUniqueIDMap[B];if(org.antlr.lang.isValue(C)){return C}var A=this.uniqueNodeID;this.treeToUniqueIDMap[B]=A;this.uniqueNodeID++;return A}};org.antlr.runtime.tree.CommonTreeAdaptor=function(){};org.antlr.lang.extend(org.antlr.runtime.tree.CommonTreeAdaptor,org.antlr.runtime.tree.BaseTreeAdaptor,{dupNode:function(A){if(!org.antlr.lang.isValue(A)){return null}return A.dupNode()},create:function(A){if(arguments.length>1){return org.antlr.runtime.tree.CommonTreeAdaptor.superclass.create.apply(this,arguments)}return new org.antlr.runtime.tree.CommonTree(A)},createToken:function(A){if(arguments.length===2){return new org.antlr.runtime.CommonToken(arguments[0],arguments[1])}else{return new org.antlr.runtime.CommonToken(arguments[0])}},setTokenBoundaries:function(C,E,A){if(!org.antlr.lang.isValue(C)){return }var D=0,B=0;if(org.antlr.lang.isValue(E)){if(E.getTokenIndex){D=E.getTokenIndex()}else{if(E.getStartIndex){D=E.getStartIndex()}else{D=E.getTokenStartIndex()}}}if(org.antlr.lang.isValue(A)){if(B.getTokenIndex){B=A.getTokenIndex()}else{if(A.getStopIndex){B=A.getStopIndex()}else{B=A.getTokenStopIndex()}}}C.setTokenStartIndex(D);C.setTokenStopIndex(B)},getTokenStartIndex:function(A){if(!A){return -1}return A.getTokenStartIndex()},getTokenStopIndex:function(A){if(!A){return -1}return A.getTokenStopIndex()},getText:function(A){if(!A){return null}return A.getText()},getType:function(A){if(!A){return org.antlr.runtime.Token.INVALID_TOKEN_TYPE}return A.getType()},getToken:function(A){if(A instanceof org.antlr.runtime.tree.CommonTree){return A.getToken()}return null},getChild:function(B,A){if(!B){return null}return B.getChild(A)},getChildCount:function(A){if(!A){return 0}return A.getChildCount()},getParent:function(A){return A.getParent()},setParent:function(A,B){A.setParent(B)},getChildIndex:function(A){return A.getChildIndex()},setChildIndex:function(B,A){B.setChildIndex(A)},replaceChildren:function(D,B,A,C){if(D){D.replaceChildren(B,A,C)}}});org.antlr.runtime.ANTLRStringStream=function(A){this.p=0;this.line=1;this.charPositionInLine=0;this.markDepth=0;this.markers=null;this.lastMarker=null;this.data=A;this.n=A.length};org.antlr.runtime.ANTLRStringStream.prototype={reset:function(){this.p=0;this.line=1;this.charPositionInLine=0;this.markDepth=0},consume:function(){if(this.p<this.n){this.charPositionInLine++;if(this.data.charAt(this.p)==="\n"){this.line++;this.charPositionInLine=0}this.p++}},LA:function(B){if(B<0){B++}var A=this.p+B-1;if(A>=this.n||A<0){return org.antlr.runtime.CharStream.EOF}return this.data.charAt(A)},index:function(){return this.p},size:function(){return this.n},mark:function(){if(!this.markers){this.markers=[];this.markers.push(null)}this.markDepth++;var A=null;if(this.markDepth>=this.markers.length){A={};this.markers.push(A)}else{A=this.markers[this.markDepth]}A.p=this.p;A.line=this.line;A.charPositionInLine=this.charPositionInLine;this.lastMarker=this.markDepth;return this.markDepth},rewind:function(A){if(!org.antlr.lang.isNumber(A)){A=this.lastMarker}var B=this.markers[A];this.seek(B.p);this.line=B.line;this.charPositionInLine=B.charPositionInLine;this.release(A)},release:function(A){this.markDepth=A;this.markDepth--},seek:function(A){if(A<=this.p){this.p=A;return }while(this.p<A){this.consume()}},substring:function(B,A){return this.data.substr(B,A-B+1)},getLine:function(){return this.line},getCharPositionInLine:function(){return this.charPositionInLine},setLine:function(A){this.line=A},setCharPositionInLine:function(A){this.charPositionInLine=A},getSourceName:function(){return null}};org.antlr.runtime.ANTLRStringStream.LT=org.antlr.runtime.ANTLRStringStream.LA;org.antlr.runtime.CommonTokenStream=function(A,B){this.p=-1;this.channel=org.antlr.runtime.Token.DEFAULT_CHANNEL;this.v_discardOffChannelTokens=false;this.tokens=[];if(arguments.length>=2){this.channel=B}else{if(arguments.length===1){this.tokenSource=A}}};org.antlr.runtime.CommonTokenStream.prototype={setTokenSource:function(A){this.tokenSource=A;this.tokens=[];this.p=-1;this.channel=org.antlr.runtime.Token.DEFAULT_CHANNEL},fillBuffer:function(){var B=0,C=this.tokenSource.nextToken(),A,D;while(org.antlr.lang.isValue(C)&&C.getType()!=org.antlr.runtime.CharStream.EOF){A=false;if(this.channelOverrideMap){D=this.channelOverrideMap[C.getType()];if(org.antlr.lang.isValue(D)){C.setChannel(D)}}if(this.discardSet&&this.discardSet[C.getType()]){A=true}else{if(this.v_discardOffChannelTokens&&C.getChannel()!=this.channel){A=true}}if(!A){C.setTokenIndex(B);this.tokens.push(C);B++}C=this.tokenSource.nextToken()}this.p=0;this.p=this.skipOffTokenChannels(this.p)},consume:function(){if(this.p<this.tokens.length){this.p++;this.p=this.skipOffTokenChannels(this.p)}},skipOffTokenChannels:function(A){var B=this.tokens.length;while(A<B&&(this.tokens[A]).getChannel()!=this.channel){A++}return A},skipOffTokenChannelsReverse:function(A){while(A>=0&&(this.tokens[A]).getChannel()!=this.channel){A--}return A},setTokenTypeChannel:function(B,A){if(!this.channelOverrideMap){this.channelOverrideMap={}}this.channelOverrideMap[B]=A},discardTokenType:function(A){if(!this.discardSet){this.discardSet={}}this.discardSet[A]=true},discardOffChannelTokens:function(A){this.v_discardOffChannelTokens=A},getTokens:function(F,D,C){if(this.p===-1){this.fillBuffer()}if(arguments.length===0){return this.tokens}if(org.antlr.lang.isArray(C)){C=new org.antlr.runtime.BitSet(C)}else{if(org.antlr.lang.isNumber(C)){C=org.antlr.runtime.BitSet.of(C)}}if(D>=this.tokens.length){D=this.tokens.length-1}if(F<0){F=0}if(F>D){return null}var E=[],B,A;for(B=F;B<=D;B++){A=this.tokens[B];if(!this.types||C.member(A.getType())){E.push(A)}}if(E.length===0){E=null}return E},LT:function(A){if(this.p===-1){this.fillBuffer()}if(A===0){return null}if(A<0){return this.LB(-1*A)}if((this.p+A-1)>=this.tokens.length){return org.antlr.runtime.Token.EOF_TOKEN}var B=this.p,C=1;while(C<A){B=this.skipOffTokenChannels(B+1);C++}if(B>=this.tokens.length){return org.antlr.runtime.Token.EOF_TOKEN}return this.tokens[B]},LB:function(A){if(this.p===-1){this.fillBuffer()}if(A===0){return null}if((this.p-A)<0){return null}var B=this.p,C=1;while(C<=A){B=this.skipOffTokenChannelsReverse(B-1);C++}if(B<0){return null}return this.tokens[B]},get:function(A){return this.tokens[A]},LA:function(A){return this.LT(A).getType()},mark:function(){if(this.p===-1){this.fillBuffer()}this.lastMarker=this.index();return this.lastMarker},release:function(A){},size:function(){return this.tokens.length},index:function(){return this.p},rewind:function(A){if(!org.antlr.lang.isNumber(A)){A=this.lastMarker}this.seek(A)},reset:function(){this.p=-1;this.lastMarker=0},seek:function(A){this.p=A},getTokenSource:function(){return this.tokenSource},getSourceName:function(){return this.getTokenSource().getSourceName()},toString:function(D,C){if(arguments.length===0){if(this.p===-1){this.fillBuffer()}D=0;C=this.tokens.length-1}if(!org.antlr.lang.isNumber(D)&&!org.antlr.lang.isNumber(C)){if(org.antlr.lang.isValue(D)&&org.antlr.lang.isValue(C)){D=D.getTokenIndex();C=C.getTokenIndex()}else{return null}}var A="",B;if(D<0||C<0){return null}if(this.p==-1){this.fillBuffer()}if(C>=this.tokens.length){C=this.tokens.length-1}for(B=D;B<=C;B++){t=this.tokens[B];A=A+this.tokens[B].getText()}return A}};org.antlr.runtime.TokenRewriteStream=function(){var A=org.antlr.runtime.TokenRewriteStream.superclass;this.programs=null;this.lastRewriteTokenIndexes=null;if(arguments.length===0){this.init()}else{A.constructor.apply(this,arguments);this.init()}};(function(){var A=org.antlr.runtime.TokenRewriteStream;org.antlr.lang.augmentObject(A,{DEFAULT_PROGRAM_NAME:"default",PROGRAM_INIT_SIZE:100,MIN_TOKEN_INDEX:0});A.RewriteOperation=function(B,C){this.index=B;this.text=C};A.RewriteOperation.prototype={execute:function(B){return this.index},toString:function(){return this.text}};A.InsertBeforeOp=function(B,C){A.InsertBeforeOp.superclass.constructor.call(this,B,C)};org.antlr.lang.extend(A.InsertBeforeOp,A.RewriteOperation,{execute:function(B){B.push(this.text);return this.index}});A.ReplaceOp=function(D,C,B){A.ReplaceOp.superclass.constructor.call(this,D,B);this.lastIndex=C};org.antlr.lang.extend(A.ReplaceOp,A.RewriteOperation,{execute:function(B){if(org.antlr.lang.isValue(this.text)){B.push(this.text)}return this.lastIndex+1}});A.DeleteOp=function(C,B){A.DeleteOp.superclass.constructor.call(this,C,B)};org.antlr.lang.extend(A.DeleteOp,A.ReplaceOp);org.antlr.lang.extend(A,org.antlr.runtime.CommonTokenStream,{init:function(){this.programs={};this.programs[A.DEFAULT_PROGRAM_NAME]=[];this.lastRewriteTokenIndexes={}},rollback:function(){var B,C;if(arguments.length===1){B=A.DEFAULT_PROGRAM_NAME;C=arguments[0]}else{if(arguments.length===2){B=arguments[0];C=arguments[1]}}var D=this.programs[B];if(D){programs[B]=D.slice(A.MIN_TOKEN_INDEX,this.instructionIndex)}},deleteProgram:function(B){B=B||A.DEFAULT_PROGRAM_NAME;this.rollback(B,A.MIN_TOKEN_INDEX)},addToSortedRewriteList:function(){var H,E;if(arguments.length===1){H=A.DEFAULT_PROGRAM_NAME;E=arguments[0]}else{if(arguments.length===2){H=arguments[0];E=arguments[1]}}var F=this.getProgram(H);var G,I,D,J,B,C;for(I=0,G=F.length;I<G;I++){D=F[I];if(D.index===E.index){if(E instanceof A.ReplaceOp){J=false;for(C=I;C<F.length;C++){B=F[I];if(B.index!==E.index){break}if(B instanceof A.ReplaceOp){F[I]=E;J=true;break}}if(!J){F.splice(C,0,E)}}else{F.splice(I,0,E)}break}else{if(D.index>E.index){F.splice(I,0,E);break}}}if(I===G){F.push(E)}},insertAfter:function(){var C,B,D;if(arguments.length===2){B=A.DEFAULT_PROGRAM_NAME;C=arguments[0];D=arguments[1]}else{if(arguments.length===3){B=arguments[0];C=arguments[1];D=arguments[2]}}if(C instanceof org.antlr.runtime.CommonToken){C=C.index}this.insertBefore(B,C+1,D)},insertBefore:function(){var C,B,D;if(arguments.length===2){B=A.DEFAULT_PROGRAM_NAME;C=arguments[0];D=arguments[1]}else{if(arguments.length===3){B=arguments[0];C=arguments[1];D=arguments[2]}}if(C instanceof org.antlr.runtime.CommonToken){C=C.index}this.addToSortedRewriteList(B,new A.InsertBeforeOp(C,D))},replace:function(){var B,E,C,D;if(arguments.length===2){B=A.DEFAULT_PROGRAM_NAME;E=arguments[0];C=arguments[0];D=arguments[1]}else{if(arguments.length===3){B=A.DEFAULT_PROGRAM_NAME;E=arguments[0];C=arguments[1];D=arguments[2]}}if(arguments.length===4){B=arguments[0];E=arguments[1];C=arguments[2];D=arguments[3]}if(E instanceof org.antlr.runtime.CommonToken){E=E.index}if(C instanceof org.antlr.runtime.CommonToken){C=C.index}if(E>C||C<0||E<0){return }this.addToSortedRewriteList(B,new A.ReplaceOp(E,C,D))},remove:function(){var B=[],C=arguments.length-1;while(C>=0){B[C]=arguments[C];C--}B.push("");this.replace.apply(this,B)},getLastRewriteTokenIndex:function(B){B=B||A.DEFAULT_PROGRAM_NAME;return this.lastRewriteTokenIndexes[B]||-1},setLastRewriteTokenIndex:function(B,C){this.lastRewriteTokenIndexes[B]=C},getProgram:function(B){var C=this.programs[B];if(!C){C=this.initializeProgram(B)}return C},initializeProgram:function(B){var C=[];this.programs[B]=C;return C},toOriginalString:function(E,B){if(!org.antlr.lang.isNumber(E)){E=A.MIN_TOKEN_INDEX}if(!org.antlr.lang.isNumber(B)){B=this.size()-1}var C=[],D;for(D=E;D>=A.MIN_TOKEN_INDEX&&D<=B&&D<this.tokens.length;D++){C.push(this.get(D).getText())}return C.join("")},toString:function(){var J,B,F;if(arguments.length===0){J=A.DEFAULT_PROGRAM_NAME;B=A.MIN_TOKEN_INDEX;F=this.size()-1}else{if(arguments.length===1){J=arguments[0];B=A.MIN_TOKEN_INDEX;F=this.size()-1}else{if(arguments.length===2){J=A.DEFAULT_PROGRAM_NAME;B=arguments[0];F=arguments[1]}}}var H=this.programs[J];if(!H||H.length===0){return this.toOriginalString(B,F)}var E=0,D=B,C=[],G;while(D>=A.MIN_TOKEN_INDEX&&D<=F&&D<this.tokens.length){if(E<H.length){G=H[E];while(G.index<D&&E<H.length){E++;if(E<H.length){G=H[E]}}while(D===G.index&&E<H.length){D=G.execute(C);E++;if(E<H.length){G=H[E]}}}if(D<=F){C.push(this.get(D).getText());D++}}var I;for(I=E;I<H.length;I++){G=H[I];if(G.index>=this.size()){G.execute(C)}}return C.join("")},toDebugString:function(E,B){if(!org.antlr.lang.isNumber(E)){E=A.MIN_TOKEN_INDEX}if(!org.antlr.lang.isNumber(B)){B=this.size()-1}var C=[],D;for(D=E;D>=A.MIN_TOKEN_INDEX&&D<=B&&D<this.tokens.length;D++){C.push(this.get(D))}return C.join("")}})})();org.antlr.runtime.tree.TreeNodeStream=function(){};org.antlr.runtime.tree.CommonTreeNodeStream=function(D,A,B){if(arguments.length===1){A=D;D=new org.antlr.runtime.tree.CommonTreeAdaptor()}if(arguments.length<=2){B=org.antlr.runtime.tree.CommonTreeNodeStream.DEFAULT_INITIAL_BUFFER_SIZE}this.uniqueNavigationNodes=false;this.p=-1;var C=org.antlr.runtime.Token;this.root=A;this.adaptor=D;this.nodes=[];this.down=this.adaptor.create(C.DOWN,"DOWN");this.up=this.adaptor.create(C.UP,"UP");this.eof=this.adaptor.create(C.EOF,"EOF")};org.antlr.lang.augmentObject(org.antlr.runtime.tree.CommonTreeNodeStream,{DEFAULT_INITIAL_BUFFER_SIZE:100,INITIAL_CALL_STACK_SIZE:10});org.antlr.lang.extend(org.antlr.runtime.tree.CommonTreeNodeStream,org.antlr.runtime.tree.TreeNodeStream,{StreamIterator:function(){var C=0,B=this.nodes,A=this.eof;return{hasNext:function(){return C<B.length},next:function(){var D=C;C++;if(D<B.length){return B[D]}return A},remove:function(){throw new Error("cannot remove nodes from stream")}}},fillBuffer:function(C){var B=false;if(org.antlr.lang.isUndefined(C)){C=this.root;B=true}var A=this.adaptor.isNil(C);if(!A){this.nodes.push(C)}var F=this.adaptor.getChildCount(C);if(!A&&F>0){this.addNavigationNode(org.antlr.runtime.Token.DOWN)}var E,D;for(E=0;E<F;E++){D=this.adaptor.getChild(C,E);this.fillBuffer(D)}if(!A&&F>0){this.addNavigationNode(org.antlr.runtime.Token.UP)}if(B){this.p=0}},getNodeIndex:function(C){if(this.p==-1){this.fillBuffer()}var B,A;for(B=0;B<this.nodes.length;B++){A=this.nodes[B];if(A===C){return B}}return -1},addNavigationNode:function(B){var A=null;if(B===org.antlr.runtime.Token.DOWN){if(this.hasUniqueNavigationNodes()){A=this.adaptor.create(org.antlr.runtime.Token.DOWN,"DOWN")}else{A=this.down}}else{if(this.hasUniqueNavigationNodes()){A=this.adaptor.create(org.antlr.runtime.Token.UP,"UP")}else{A=this.up}}this.nodes.push(A)},get:function(A){if(this.p===-1){this.fillBuffer()}return this.nodes[A]},LT:function(A){if(this.p===-1){this.fillBuffer()}if(A===0){return null}if(A<0){return this.LB(-1*A)}if((this.p+A-1)>=this.nodes.length){return this.eof}return this.nodes[this.p+A-1]},getCurrentSymbol:function(){return this.LT(1)},LB:function(A){if(A===0){return null}if((this.p-A)<0){return null}return this.nodes[this.p-A]},getTreeSource:function(){return this.root},getSourceName:function(){return this.getTokenStream().getSourceName()},getTokenStream:function(){return this.tokens},setTokenStream:function(A){this.tokens=A},getTreeAdaptor:function(){return this.adaptor},setTreeAdaptor:function(A){this.adaptor=A},hasUniqueNavigationNodes:function(){return this.uniqueNavigationNodes},setUniqueNavigationNodes:function(A){this.uniqueNavigationNodes=A},consume:function(){if(this.p===-1){this.fillBuffer()}this.p++},LA:function(A){return this.adaptor.getType(this.LT(A))},mark:function(){if(this.p===-1){this.fillBuffer()}this.lastMarker=this.index();return this.lastMarker},release:function(A){},index:function(){return this.p},rewind:function(A){if(!org.antlr.lang.isNumber(A)){A=this.lastMarker}this.seek(A)},seek:function(A){if(this.p===-1){this.fillBuffer()}this.p=A},push:function(A){if(!this.calls){this.calls=[]}this.calls.push(this.p);this.seek(A)},pop:function(){var A=this.calls.pop();this.seek(A);return A},reset:function(){this.p=-1;this.lastMarker=0;if(this.calls){this.calls=[]}},size:function(){if(this.p===-1){this.fillBuffer()}return this.nodes.length},iterator:function(){if(this.p===-1){this.fillBuffer()}return this.StreamIterator()},replaceChildren:function(D,B,A,C){if(D){this.adaptor.replaceChildren(D,B,A,C)}},toTokenString:function(E,D){if(this.p===-1){this.fillBuffer()}var A="",C,B;for(C=E;C<this.nodes.length&&C<=D;C++){B=this.nodes[C];A+=" "+this.adaptor.getToken(B)}return A},toString:function(H,D){var A="",E,C,B;if(arguments.length===0){if(this.p===-1){this.fillBuffer()}for(B=0;B<this.nodes.length;B++){C=this.nodes[B];A+=" ";A+=this.adaptor.getType(C)}return A}else{if(!org.antlr.lang.isNumber(H)||!org.antlr.lang.isNumber(D)){return null}if(this.p===-1){this.fillBuffer()}if(H instanceof org.antlr.runtime.tree.CommonTree){}else{}if(D instanceof org.antlr.runtime.tree.CommonTree){}else{}var G,F;if(this.tokens){G=this.adaptor.getTokenStartIndex(H);F=this.adaptor.getTokenStopIndex(D);if(this.adaptor.getType(D)===org.antlr.runtime.Token.UP){F=this.adaptor.getTokenStopIndex(H)}else{if(this.adaptor.getType(D)==org.antlr.runtime.Token.EOF){F=this.size()-2}}return this.tokens.toString(G,F)}C=null;B=0;for(;B<this.nodes.length;B++){C=this.nodes[B];if(C===H){break}}A=E="";C=this.nodes[B];while(C!==D){E=this.adaptor.getText(C);if(!org.antlr.lang.isString(E)){E=" "+this.adaptor.getType(C).toString()}A+=E;B++;C=nodes[B]}E=this.adaptor.getText(D);if(!org.antlr.lang.isString(E)){E=" "+this.adaptor.getType(D).toString()}A+=E;return A}}});org.antlr.runtime.tree.RewriteRuleElementStream=function(C,B,A){this.cursor=0;this.dirty=false;this.elementDescription=B;this.adaptor=C;if(A){if(org.antlr.lang.isArray(A)){this.singleElement=null;this.elements=A}else{this.add(A)}}};org.antlr.runtime.tree.RewriteRuleElementStream.prototype={reset:function(){this.cursor=0;this.dirty=true},add:function(A){if(!org.antlr.lang.isValue(A)){return }if(this.elements){this.elements.push(A);return }if(!org.antlr.lang.isValue(this.singleElement)){this.singleElement=A;return }this.elements=[];this.elements.push(this.singleElement);this.singleElement=null;this.elements.push(A)},nextTree:function(){var B=this.size(),A;if(this.dirty||(this.cursor>=B&&B==1)){A=this._next();return this.dup(A)}A=this._next();return A},_next:function(){var B=this.size();if(B===0){throw new org.antlr.runtime.tree.RewriteEmptyStreamException(this.elementDescription)}if(this.cursor>=B){if(B===1){return this.toTree(this.singleElement)}throw new org.antlr.runtime.tree.RewriteCardinalityException(this.elementDescription)}if(org.antlr.lang.isValue(this.singleElement)){this.cursor++;return this.toTree(this.singleElement)}var A=this.toTree(this.elements[this.cursor]);this.cursor++;return A},toTree:function(A){if(A&&A.getTree){return A.getTree()}return A},hasNext:function(){return(org.antlr.lang.isValue(this.singleElement)&&this.cursor<1)||(this.elements&&this.cursor<this.elements.length)},size:function(){var A=0;if(org.antlr.lang.isValue(this.singleElement)){A=1}if(this.elements){return this.elements.length}return A},getDescription:function(){return this.elementDescription}};org.antlr.runtime.tree.RewriteRuleNodeStream=function(C,B,A){org.antlr.runtime.tree.RewriteRuleNodeStream.superclass.constructor.apply(this,arguments)};org.antlr.lang.extend(org.antlr.runtime.tree.RewriteRuleNodeStream,org.antlr.runtime.tree.RewriteRuleElementStream,{nextNode:function(){return this._next()},toTree:function(A){return this.adaptor.dupNode(A)},dup:function(){throw new Error("dup can't be called for a node stream.")}});org.antlr.runtime.tree.RewriteRuleTokenStream=function(D,C,B){var A=org.antlr.runtime.tree.RewriteRuleTokenStream.superclass;A.constructor.apply(this,arguments)};org.antlr.lang.extend(org.antlr.runtime.tree.RewriteRuleTokenStream,org.antlr.runtime.tree.RewriteRuleElementStream,{nextNode:function(){var A=this._next();return this.adaptor.create(A)},nextToken:function(){return this._next()},toTree:function(A){return A},dup:function(A){throw new Error("dup can't be called for a token stream.")}});org.antlr.runtime.tree.RewriteRuleSubtreeStream=function(){var A=org.antlr.runtime.tree.RewriteRuleSubtreeStream.superclass;A.constructor.apply(this,arguments)};org.antlr.lang.extend(org.antlr.runtime.tree.RewriteRuleSubtreeStream,org.antlr.runtime.tree.RewriteRuleElementStream,{nextNode:function(){var B=this.size(),A;if(this.dirty||(this.cursor>=B&&B===1)){A=this._next();return this.adaptor.dupNode(A)}A=this._next();return A},dup:function(A){return this.adaptor.dupTree(A)}});org.antlr.runtime.BaseRecognizer=function(A){this.state=A||new org.antlr.runtime.RecognizerSharedState()};org.antlr.lang.augmentObject(org.antlr.runtime.BaseRecognizer,{MEMO_RULE_FAILED:-2,MEMO_RULE_UNKNOWN:-1,INITIAL_FOLLOW_STACK_SIZE:100,MEMO_RULE_FAILED_I:-2,DEFAULT_TOKEN_CHANNEL:org.antlr.runtime.Token.DEFAULT_CHANNEL,HIDDEN:org.antlr.runtime.Token.HIDDEN_CHANNEL,NEXT_TOKEN_RULE_NAME:"nextToken"});org.antlr.runtime.BaseRecognizer.prototype={reset:function(){var B,A;if(!this.state){return }this.state._fsp=-1;this.state.errorRecovery=false;this.state.lastErrorIndex=-1;this.state.failed=false;this.state.syntaxErrors=0;this.state.backtracking=0;if(this.state.ruleMemo){for(B=0,A=this.state.ruleMemo.length;B<A;B++){this.state.ruleMemo[B]=null}}},match:function(B,D,A){var C=this.getCurrentInputSymbol(B);if(B.LA(1)===D){B.consume();this.state.errorRecovery=false;this.state.failed=false;return C}if(this.state.backtracking>0){this.state.failed=true;return C}C=this.recoverFromMismatchedToken(B,D,A);return C},matchAny:function(A){this.state.errorRecovery=false;this.state.failed=false;A.consume()},mismatchIsUnwantedToken:function(A,B){return A.LA(2)===B},mismatchIsMissingToken:function(C,A){if(!A){return false}if(A.member(org.antlr.runtime.Token.EOR_TOKEN_TYPE)){if(this.state._fsp>=0){A.remove(org.antlr.runtime.Token.EOR_TOKEN_TYPE)}var B=this.computeContextSensitiveRuleFOLLOW();A=A.or(this.viableTokensFollowingThisRule)}if(A.member(C.LA(1))||A.member(org.antlr.runtime.Token.EOR_TOKEN_TYPE)){return true}return false},mismatch:function(B,C,A){if(this.mismatchIsUnwantedToken(B,C)){throw new org.antlr.runtime.UnwantedTokenException(C,B)}else{if(this.mismatchIsMissingToken(B,A)){throw new org.antlr.runtime.MissingTokenException(C,B,null)}}throw new org.antlr.runtime.MismatchedTokenException(C,B)},reportError:function(A){if(this.state.errorRecovery){return }this.state.syntaxErrors++;this.state.errorRecovery=true;this.displayRecognitionError(this.getTokenNames(),A)},displayRecognitionError:function(A,B){var D=this.getErrorHeader(B),C=this.getErrorMessage(B,A);this.emitErrorMessage(D+" "+C)},getErrorHeader:function(A){if(!org.antlr.lang.isNumber(A.line)){A.line=0}return"line "+A.line+":"+A.charPositionInLine},emitErrorMessage:function(A){if(typeof (window)!="undefined"&&window.alert){alert(A)}else{print(A)}},getErrorMessage:function(E,D){var F=(E&&E.getMessage)?E.getMessage():null,A,C;if(E instanceof org.antlr.runtime.UnwantedTokenException){var B=E;C="<unknown>";if(B.expecting==org.antlr.runtime.Token.EOF){C="EOF"}else{C=D[B.expecting]}F="extraneous input "+this.getTokenErrorDisplay(B.getUnexpectedToken())+" expecting "+C}else{if(E instanceof org.antlr.runtime.MissingTokenException){A=E;C="<unknown>";if(A.expecting==org.antlr.runtime.Token.EOF){C="EOF"}else{C=D[A.expecting]}F="missing "+C+" at "+this.getTokenErrorDisplay(E.token)}else{if(E instanceof org.antlr.runtime.MismatchedTokenException){A=E;C="<unknown>";if(A.expecting==org.antlr.runtime.Token.EOF){C="EOF"}else{C=D[A.expecting]}F="mismatched input "+this.getTokenErrorDisplay(E.token)+" expecting "+C}else{if(E instanceof org.antlr.runtime.NoViableAltException){F="no viable alternative at input "+this.getTokenErrorDisplay(E.token)}else{if(E instanceof org.antlr.runtime.EarlyExitException){F="required (...)+ loop did not match anything at input "+this.getTokenErrorDisplay(E.token)}else{if(E instanceof org.antlr.runtime.MismatchedSetException){F="mismatched input "+this.getTokenErrorDisplay(E.token)+" expecting set "+E.expecting}else{if(E instanceof org.antlr.runtime.MismatchedNotSetException){F="mismatched input "+this.getTokenErrorDisplay(E.token)+" expecting set "+E.expecting}else{if(E instanceof org.antlr.runtime.FailedPredicateException){F="rule "+E.ruleName+" failed predicate: {"+E.predicateText+"}?"}}}}}}}}return F},getNumberOfSyntaxErrors:function(){return this.state.syntaxErrors},getTokenErrorDisplay:function(A){var B=A.getText();if(!org.antlr.lang.isValue(B)){if(A.getType()==org.antlr.runtime.Token.EOF){B="<EOF>"}else{B="<"+A.getType()+">"}}B=B.replace(/\n/g,"\\n");B=B.replace(/\r/g,"\\r");B=B.replace(/\t/g,"\\t");return"'"+B+"'"},recover:function(A,B){if(this.state.lastErrorIndex==A.index()){A.consume()}this.state.lastErrorIndex=A.index();var C=this.computeErrorRecoverySet();this.beginResync();this.consumeUntil(A,C);this.endResync()},beginResync:function(){},endResync:function(){},computeErrorRecoverySet:function(){return this.combineFollows(false)},computeContextSensitiveRuleFOLLOW:function(){return this.combineFollows(true)},combineFollows:function(C){var E=this.state._fsp,B,A,D=new org.antlr.runtime.BitSet();for(B=E;B>=0;B--){A=this.state.following[B];D.orInPlace(A);if(C){if(A.member(org.antlr.runtime.Token.EOR_TOKEN_TYPE)){if(B>0){D.remove(org.antlr.runtime.Token.EOR_TOKEN_TYPE)}}else{break}}}return D},recoverFromMismatchedToken:function(B,F,A){var E=null;if(this.mismatchIsUnwantedToken(B,F)){E=new org.antlr.runtime.UnwantedTokenException(F,B);this.beginResync();B.consume();this.endResync();this.reportError(E);var D=this.getCurrentInputSymbol(B);B.consume();return D}if(this.mismatchIsMissingToken(B,A)){var C=this.getMissingSymbol(B,E,F,A);E=new org.antlr.runtime.MissingTokenException(F,B,C);this.reportError(E);return C}E=new org.antlr.runtime.MismatchedTokenException(F,B);throw E},recoverFromMismatchedSet:function(B,C,A){if(this.mismatchIsMissingToken(B,A)){this.reportError(C);return this.getMissingSymbol(B,C,org.antlr.runtime.Token.INVALID_TOKEN_TYPE,A)}throw C},getCurrentInputSymbol:function(A){return null},getMissingSymbol:function(B,D,C,A){return null},consumeUntil:function(A,C){var B=A.LA(1);while(B!=org.antlr.runtime.Token.EOF&&!C.member(B)){A.consume();B=A.LA(1)}},pushFollow:function(A){if((this.state._fsp+1)>=this.state.following.length){var C=[];var B;for(B=this.state.following.length-1;B>=0;B--){C[B]=this.state.following[B]}this.state.following=C}this.state._fsp++;this.state.following[this.state._fsp]=A},getRuleInvocationStack:function(B,A){throw new Error("Not implemented.")},getBacktrackingLevel:function(){return this.state.backtracking},getTokenNames:function(){return null},getGrammarFileName:function(){return null},toStrings:function(C){if(!C){return null}var A=[];var B;for(B=0;B<C.length;B++){A.push(C[B].getText())}return A},getRuleMemoization:function(B,A){if(!this.state.ruleMemo[B]){this.state.ruleMemo[B]={}}var C=this.state.ruleMemo[B][A];if(!org.antlr.lang.isNumber(C)){return org.antlr.runtime.BaseRecognizer.MEMO_RULE_UNKNOWN}return C},alreadyParsedRule:function(B,C){var A=this.getRuleMemoization(C,B.index());if(A==org.antlr.runtime.BaseRecognizer.MEMO_RULE_UNKNOWN){return false}if(A==org.antlr.runtime.BaseRecognizer.MEMO_RULE_FAILED){this.state.failed=true}else{B.seek(A+1)}return true},memoize:function(C,D,B){var A=this.state.failed?org.antlr.runtime.BaseRecognizer.MEMO_RULE_FAILED:C.index()-1;if(!org.antlr.lang.isValue(this.state.ruleMemo)){throw new Error("!!!!!!!!! memo array is null for "+this.getGrammarFileName())}if(D>=this.state.ruleMemo.length){throw new Error("!!!!!!!!! memo size is "+this.state.ruleMemo.length+", but rule index is "+D)}if(org.antlr.lang.isValue(this.state.ruleMemo[D])){this.state.ruleMemo[D][B]=A}},getRuleMemoizationCacheSize:function(){var C=0,A;for(A=0;this.state.ruleMemo&&A<this.state.ruleMemo.length;A++){var B=this.state.ruleMemo[A];if(B){C+=B.length}}return C},traceIn:function(C,B,A){this.emitErrorMessage("enter "+C+" "+A);if(this.state.failed){this.emitErrorMessage(" failed="+this.failed)}if(this.state.backtracking>0){this.emitErrorMessage(" backtracking="+this.state.backtracking)}},traceOut:function(C,B,A){this.emitErrorMessage("exit "+C+" "+A);if(this.state.failed){this.emitErrorMessage(" failed="+this.state.failed)}if(this.state.backtracking>0){this.emitErrorMessage(" backtracking="+this.state.backtracking)}}};org.antlr.runtime.Lexer=function(A,B){if(B){org.antlr.runtime.Lexer.superclass.constructor.call(this,B)}if(A){this.input=A}};org.antlr.lang.extend(org.antlr.runtime.Lexer,org.antlr.runtime.BaseRecognizer,{reset:function(){org.antlr.runtime.Lexer.superclass.reset.call(this);if(org.antlr.lang.isValue(this.input)){this.input.seek(0)}if(!org.antlr.lang.isValue(this.state)){return }this.state.token=null;this.state.type=org.antlr.runtime.Token.INVALID_TOKEN_TYPE;this.state.channel=org.antlr.runtime.Token.DEFAULT_CHANNEL;this.state.tokenStartCharIndex=-1;this.state.tokenStartCharPositionInLine=-1;this.state.tokenStartLine=-1;this.state.text=null},nextToken:function(){while(true){this.state.token=null;this.state.channel=org.antlr.runtime.Token.DEFAULT_CHANNEL;this.state.tokenStartCharIndex=this.input.index();this.state.tokenStartCharPositionInLine=this.input.getCharPositionInLine();this.state.tokenStartLine=this.input.getLine();this.state.text=null;if(this.input.LA(1)===org.antlr.runtime.CharStream.EOF){return org.antlr.runtime.Token.EOF_TOKEN}try{this.mTokens();if(!org.antlr.lang.isValue(this.state.token)){this.emit()}else{if(this.state.token==org.antlr.runtime.Token.SKIP_TOKEN){continue}}return this.state.token}catch(A){if(A instanceof org.antlr.runtime.RecognitionException){this.reportError(A)}else{if(A instanceof org.antlr.runtime.NoViableAltException){this.reportError(A);this.recover(A)}else{throw A}}}}},skip:function(){this.state.token=org.antlr.runtime.Token.SKIP_TOKEN},setCharStream:function(A){this.input=null;this.reset();this.input=A},getCharStream:function(){return this.input},getSourceName:function(){return this.input.getSourceName()},emit:function(){if(arguments.length===0){var A=new org.antlr.runtime.CommonToken(this.input,this.state.type,this.state.channel,this.state.tokenStartCharIndex,this.getCharIndex()-1);A.setLine(this.state.tokenStartLine);A.setText(this.state.text);A.setCharPositionInLine(this.state.tokenStartCharPositionInLine);this.state.token=A;return A}else{this.state.token=arguments[0]}},match:function(C){var B=0,A;if(org.antlr.lang.isString(C)){while(B<C.length){if(this.input.LA(1)!=C.charAt(B)){if(this.state.backtracking>0){this.state.failed=true;return }A=new org.antlr.runtime.MismatchedTokenException(C.charAt(B),this.input);this.recover(A);throw A}B++;this.input.consume();this.state.failed=false}}else{if(org.antlr.lang.isNumber(C)){if(this.input.LA(1)!=C){if(this.state.backtracking>0){this.state.failed=true;return }A=new org.antlr.runtime.MismatchedTokenException(C,this.input);this.recover(A);throw A}this.input.consume();this.state.failed=false}}},matchAny:function(){this.input.consume()},matchRange:function(B,A){if(this.input.LA(1)<B||this.input.LA(1)>A){if(this.state.backtracking>0){this.state.failed=true;return }mre=new org.antlr.runtime.MismatchedRangeException(B,A,this.input);this.recover(mre);throw mre}this.input.consume();this.state.failed=false},getLine:function(){return this.input.getLine()},getCharPositionInLine:function(){return this.input.getCharPositionInLine()},getCharIndex:function(){return this.input.index()},getText:function(){if(org.antlr.lang.isString(this.state.text)){return this.state.text}return this.input.substring(this.state.tokenStartCharIndex,this.getCharIndex()-1)},setText:function(A){this.state.text=A},reportError:function(A){this.displayRecognitionError(this.getTokenNames(),A)},getErrorMessage:function(B,A){var C=null;if(B instanceof org.antlr.runtime.MismatchedTokenException){C="mismatched character "+this.getCharErrorDisplay(B.c)+" expecting "+this.getCharErrorDisplay(B.expecting)}else{if(B instanceof org.antlr.runtime.NoViableAltException){C="no viable alternative at character "+this.getCharErrorDisplay(B.c)}else{if(B instanceof org.antlr.runtime.EarlyExitException){C="required (...)+ loop did not match anything at character "+this.getCharErrorDisplay(B.c)}else{if(B instanceof org.antlr.runtime.MismatchedNotSetException){C="mismatched character "+this.getCharErrorDisplay(B.c)+" expecting set "+B.expecting}else{if(B instanceof org.antlr.runtime.MismatchedSetException){C="mismatched character "+this.getCharErrorDisplay(B.c)+" expecting set "+B.expecting}else{if(B instanceof org.antlr.runtime.MismatchedRangeException){C="mismatched character "+this.getCharErrorDisplay(B.c)+" expecting set "+this.getCharErrorDisplay(B.a)+".."+this.getCharErrorDisplay(B.b)}else{C=org.antlr.runtime.Lexer.superclass.getErrorMessage.call(this,B,A)}}}}}}return C},getCharErrorDisplay:function(B){var A=B;switch(A){case org.antlr.runtime.Token.EOF:A="<EOF>";break;case"\n":A="\\n";break;case"\t":A="\\t";break;case"\r":A="\\r";break}return"'"+A+"'"},recover:function(A){this.input.consume()},traceIn:function(C,B){var A=String.fromCharCode(this.input.LT(1))+" line="+this.getLine()+":"+this.getCharPositionInLine();org.antlr.runtime.Lexer.superclass.traceIn.call(this,C,B,A)},traceOut:function(C,B){var A=String.fromCharCode(this.input.LT(1))+" line="+this.getLine()+":"+this.getCharPositionInLine();org.antlr.runtime.Lexer.superclass.traceOut.call(this,C,B,A)}});org.antlr.runtime.ParserRuleReturnScope=function(){};org.antlr.runtime.ParserRuleReturnScope.prototype={getStart:function(){return this.start},getStop:function(){return this.stop}};org.antlr.runtime.tree.TreeRuleReturnScope=function(){};org.antlr.runtime.tree.TreeRuleReturnScope.prototype={getStart:function(){return this.start}};org.antlr.runtime.Parser=function(A,B){org.antlr.runtime.Parser.superclass.constructor.call(this,B);this.setTokenStream(A)};org.antlr.lang.extend(org.antlr.runtime.Parser,org.antlr.runtime.BaseRecognizer,{reset:function(){org.antlr.runtime.Parser.superclass.reset.call(this);if(org.antlr.lang.isValue(this.input)){this.input.seek(0)}},getCurrentInputSymbol:function(A){return A.LT(1)},getMissingSymbol:function(C,G,E,A){var B="<missing "+this.getTokenNames()[E]+">";var D=new org.antlr.runtime.CommonToken(E,B);var F=C.LT(1);var H;if(F.getType()===org.antlr.runtime.Token.EOF){H=F;F=C.LT(-1);if(!F){F=H}}D.line=F.getLine();D.charPositionInLine=F.getCharPositionInLine();D.channel=org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;return D},setTokenStream:function(A){this.input=null;this.reset();this.input=A},getTokenStream:function(){return this.input},getSourceName:function(){return this.input.getSourceName()},traceIn:function(B,A){org.antlr.runtime.Parser.superclass.traceIn.call(this,B,A,this.input.LT(1))},traceOut:function(B,A){org.antlr.runtime.Parser.superclass.traceOut.call(this,B,A,this.input.LT(1))}});org.antlr.runtime.DFA=function(){};org.antlr.runtime.DFA.prototype={predict:function(C){var F=C.mark(),D=0,B,E,A;try{while(true){B=this.special[D];if(B>=0){D=this.specialStateTransition(B,C);if(D===-1){this.noViableAlt(D,C);return 0}C.consume();continue}if(this.accept[D]>=1){return this.accept[D]}E=C.LA(1);if(E===org.antlr.runtime.Token.EOF){E=-1}else{if(org.antlr.lang.isString(E)){E=E.charCodeAt(0)}}if(E>=this.min[D]&&E<=this.max[D]){A=this.transition[D][E-this.min[D]];if(A<0){if(this.eot[D]>=0){D=this.eot[D];C.consume();continue}this.noViableAlt(D,C);return 0}D=A;C.consume();continue}if(this.eot[D]>=0){D=this.eot[D];C.consume();continue}if(E==org.antlr.runtime.Token.EOF&&this.eof[D]>=0){return this.accept[this.eof[D]]}this.noViableAlt(D,C);return 0}}finally{C.rewind(F)}},noViableAlt:function(C,A){if(this.recognizer.state.backtracking>0){this.recognizer.state.failed=true;return }var B=new org.antlr.runtime.NoViableAltException(this.getDescription(),this.decisionNumber,C,A);this.error(B);throw B},error:function(A){},specialStateTransition:function(B,A){return -1},getDescription:function(){return"n/a"}};org.antlr.lang.augmentObject(org.antlr.runtime.DFA,{unpackEncodedString:function(D){var C,F=[],E=0,G,A,B;for(C=0;C<D.length;C+=2){G=D.charCodeAt(C);A=D.charCodeAt(C+1);if(A===65535){A=-1}for(B=1;B<=G;B++){F[E++]=A}}return F},unpackEncodedStringToUnsignedChars:function(A){return org.antlr.runtime.DFA.unpackEncodedString(A)}});org.antlr.runtime.tree.TreeParser=function(A){org.antlr.runtime.tree.TreeParser.superclass.constructor.call(this,arguments[1]);this.setTreeNodeStream(A)};(function(){var A=org.antlr.runtime.tree.TreeParser;org.antlr.lang.augmentObject(A,{DOWN:org.antlr.runtime.Token.DOWN,UP:org.antlr.runtime.Token.UP});org.antlr.lang.extend(A,org.antlr.runtime.BaseRecognizer,{reset:function(){A.superclass.reset.call(this);if(this.input){this.input.seek(0)}},setTreeNodeStream:function(B){this.input=B},getTreeNodeStream:function(){return this.input},getSourceName:function(){return this.input.getSourceName()},getCurrentInputSymbol:function(B){return B.LT(1)},getMissingSymbol:function(D,F,E,B){var C="<missing "+this.getTokenNames()[E]+">";return new org.antlr.runtime.tree.CommonTree(new org.antlr.runtime.CommonToken(E,C))},matchAny:function(E){this.state.errorRecovery=false;this.state.failed=false;var B=this.input.LT(1);if(this.input.getTreeAdaptor().getChildCount(B)===0){this.input.consume();return }var D=0,C=this.input.getTreeAdaptor().getType(B);while(C!==org.antlr.runtime.Token.EOF&&!(C===A.UP&&D===0)){this.input.consume();B=this.input.LT(1);C=this.input.getTreeAdaptor().getType(B);if(C===A.DOWN){D++}else{if(C===A.UP){D--}}}this.input.consume()},mismatch:function(C,D,B){throw new org.antlr.runtime.MismatchedTreeNodeException(D,C)},getErrorHeader:function(B){return this.getGrammarFileName()+": node from "+(B.approximateLineInfo?"after ":"")+"line "+B.line+":"+B.charPositionInLine},getErrorMessage:function(C,B){var D;if(this instanceof A){D=C.input.getTreeAdaptor();C.token=D.getToken(C.node);if(!org.antlr.lang.isValue(C.token)){C.token=new org.antlr.runtime.CommonToken(D.getType(C.node),D.getText(C.node))}}return A.superclass.getErrorMessage.call(this,C,B)},traceIn:function(C,B){A.superclass.traceIn.call(this,C,B,this.input.LT(1))},traceOut:function(C,B){A.superclass.traceOut.call(this,C,B,this.input.LT(1))}})})();
diff --git a/extensions/noscript/chrome/content/noscript/clearClick.js b/extensions/noscript/chrome/content/noscript/clearClick.js
new file mode 100644
index 0000000..d699a47
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/clearClick.js
@@ -0,0 +1,112 @@
+var ClearClick = {
+ params: null,
+ canClose: true,
+ mustClose: false,
+
+ init: function() {
+ this.dialog = document.documentElement;
+ if (!(window.arguments && window.arguments.length)) this.dialog.cancelDialog();
+ this.params = window.arguments[0];
+ this.params.locked = true;
+ var url = this.url = this.params.url;
+
+ var img = this.params.img;
+
+ var preview = document.getElementById("trueImg");
+ preview.src = img.src;
+ preview.width = img.width;
+ preview.height = img.height;
+
+ preview = document.getElementById("fakeImg");
+ preview.src = img.altSrc;
+ preview.width = img.width;
+ preview.height = img.height;
+
+ if (url.length > 50) url = url.substring(0, 23) + "..." + url.slice(-23);
+ document.getElementById("hiddenContentURL").value = url;
+
+ var pref = noscriptUtil.service.getPref("clearClick");
+ Array.forEach(document.getElementById("clearClickOpts").getElementsByTagName("checkbox"), function(cbx) {
+ cbx.setAttribute("checked", !(pref & parseInt(cbx.getAttribute("value"))) ? "false" : "true");
+ });
+
+ },
+
+ browse: function() {
+ noscriptUtil.browse(this.url, null);
+ this.dialog.cancelDialog();
+ },
+
+ disclosure: function() {
+ noscriptUtil.browse("https://noscript.net/faq#clearclick", null);
+ this.dialog.cancelDialog();
+ },
+
+ end: function() {
+ if (!this.canClose) {
+ this.mustClose = true;
+ return;
+ }
+ this.params.locked = document.getElementById("keepLocked").checked;
+ var pref = 0;
+ Array.forEach(document.getElementById("clearClickOpts").getElementsByTagName("checkbox"), function(cbx) {
+ if (cbx.checked) pref = pref | parseInt(cbx.getAttribute("value"));
+ });
+ noscriptUtil.service.setPref("clearClick", pref);
+ },
+
+ swap: function(stack) {
+ stack.appendChild(stack.firstChild);
+ },
+
+ report: function() {
+ this.dialog.getButton("extra1").disabled = true;
+
+ var report = document.getElementById("report");
+ var reportId = document.getElementById("report-id");
+ var progress = document.getElementById("progress");
+
+ var xhr = new XMLHttpRequest();
+ xhr.addEventListener("readystatechange", function() {
+ switch(xhr.readyState) {
+ case 1:
+ case 2:
+ case 3:
+ ClearClick.canClose = false;
+ report.collapsed = false;
+ reportId.value = "";
+ progress.collapsed = false;
+ break;
+ case 4:
+ ClearClick.canClose = true;
+ progress.collapsed = true;
+ reportId.value = xhr.responseText.replace(/\s*OK\s*/g, '');
+ reportId.collapsed = false;
+ reportId.style.visibility = "visible";
+ if (ClearClick.mustClose) ClearClick.end();
+ }
+ }, false);
+
+ xhr.open("POST", "https://noscript.net/ws/clearclick/", true);
+
+ var p = this.params;
+ var data = {
+ url: p.url,
+ page_url: p.pageURL,
+ top_url: p.topURL,
+ x: p.pageX,
+ y: p.pageY,
+ zoom: p.zoom,
+ img1: p.img.src,
+ img2: p.img.altSrc,
+ version: noscriptUtil.service.VERSION
+ };
+ var post = [];
+ for(var k in data) {
+ post.push(k + "=" + escape(data[k]));
+ }
+ xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+ xhr.send(post.join("&"));
+ }
+
+} \ No newline at end of file
diff --git a/extensions/noscript/chrome/content/noscript/clearClick.xul b/extensions/noscript/chrome/content/noscript/clearClick.xul
new file mode 100644
index 0000000..1752fbc
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/clearClick.xul
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://noscript/skin/browser.css" type="text/css"?>
+<?xml-stylesheet href="chrome://noscript/skin/options.css" type="text/css"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://noscript/locale/noscript.dtd">
+<dialog id="clearClick"
+ title="&noscriptClearClickTitle;"
+ onload="ClearClick.init()"
+ ondialogaccept="ClearClick.end()"
+ ondialogdisclosure="ClearClick.disclosure()"
+ ondialogextra1="ClearClick.report()"
+
+
+ buttons="accept,extra1,disclosure"
+ buttonlabelextra1="&noscriptClearClickReport;"
+ buttonaccesskeyextra1="&noscriptClearClickReport.accesskey;"
+
+ spacerflex="1"
+ persist="screenX screenY"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/x-javascript" src="noscript.js" />
+ <script type="application/x-javascript" src="clearClick.js" />
+ <hbox style="width: 400px">
+ <vbox>
+ <image src="chrome://noscript/skin/icon32.png" width="32" height="32" />
+ </vbox>
+ <vbox flex="1">
+ <label class="header" value="&noscriptClearClickHeader;" />
+ <description style="white-space: normal;">&noscriptClearClickDescription;</description>
+ <hbox align="center" style="margin: 8px;">
+ <vbox align="center">
+ <stack id="imgs-stack" align="center"
+ onkeypress="if (event.which > 9) ClearClick.swap(this)"
+ onclick="ClearClick.swap(this)">
+ <image id="fakeImg" src="" width="350" height="200" style="border: 2px solid #800"/>
+ <image id="trueImg" src="" width="350" height="200" style="border: 2px solid #080"/>
+ </stack>
+ </vbox>
+ </hbox>
+ <label control="keepLocked" class="text-link" id="hiddenContentURL" onclick="ClearClick.browse()" value="" />
+ <checkbox id="keepLocked" label="&noscriptKeepLocked;" checked="true" />
+ <separator/>
+ <hbox id="clearClickOpts" align="center">
+ <label control="cc1" value="&noscriptClearClickOpt;"/>
+ <checkbox id="cc1" value="1" label="&noscriptUntrustedPagesAdj;"/>
+ <checkbox id="cc2" value="2" label="&noscriptTrustedPagesAdj;"/>
+ </hbox>
+ <hbox>
+ <label id="report" collapsed="true">&noscriptClearClickReportId;</label>
+ <textbox readonly="true" class="plain" id="report-id" value="" style="visibility: hidden" />
+ <progressmeter id="progress" mode="undetermined" collapsed="true" flex="1"/>
+ </hbox>
+
+ </vbox>
+ </hbox>
+</dialog> \ No newline at end of file
diff --git a/extensions/noscript/chrome/content/noscript/defer.jsm b/extensions/noscript/chrome/content/noscript/defer.jsm
new file mode 100644
index 0000000..539e945
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/defer.jsm
@@ -0,0 +1,17 @@
+'use strict';
+
+var EXPORTED_SYMBOLS = ["defer"];
+
+let { interfaces: Ci, classes: Cc } = Components;
+
+let currentThread = null;
+
+function defer(callback, milliseconds = 0) {
+ if (milliseconds > 0) {
+ let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback(callback, milliseconds, timer.TYPE_ONE_SHOT);
+ } else {
+ (currentThread || (currentThread = Cc["@mozilla.org/thread-manager;1"].getService().currentThread))
+ .dispatch({ run: callback }, Ci.nsIEventTarget.DISPATCH_NORMAL);
+ }
+}
diff --git a/extensions/noscript/chrome/content/noscript/e10sChild.js b/extensions/noscript/chrome/content/noscript/e10sChild.js
new file mode 100644
index 0000000..e94700d
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/e10sChild.js
@@ -0,0 +1,63 @@
+var EXPORTED_SYMBOLS = [];
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import(`chrome://noscript/content/importer.jsm`);
+
+Services.scriptloader.loadSubScript(NO_CACHE(`loader.js`), this);
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+
+
+(function () {
+ try {
+ INCLUDE("Main");
+ } catch (e) {
+ Cu.reportError(e);
+ }
+
+ IPC.child = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener, Ci.nsISupportsWeakReference]),
+ init: function() {
+ Services.cpmm.addWeakMessageListener(IPC_P_MSG.CALL, this);
+ Main.init();
+ },
+ dispose: function() {
+ Services.cpmm.removeWeakMessageListener(IPC_P_MSG.CALL, this);
+ Main.shutdown();
+ UNLOAD_ALL();
+ },
+
+ receiveMessage: function(m) {
+ if (IPC.receiveMessage(m)) {
+ return;
+ }
+ if (m.name === "NoScript:unload") {
+ this.dispose();
+ }
+ },
+
+ remote(objName, method, args) {
+ Services.cpmm.sendAsyncMessage(IPC_P_MSG.CALL, {objName, method, args});
+ },
+
+ callback(id, autoRemote = true) {
+ let cb = () => {
+ cb._executed = true;
+ };
+ cb._executed = false;
+ cb.remote = () => {
+ Services.cpmm.sendAsyncMessage(IPC_P_MSG.CALLBACK, {id, execute: cb._executed });
+ };
+ if (autoRemote) Thread.asap(cb.remote);
+ },
+
+ };
+
+ try {
+ Main.bootstrap();
+ IPC.child.init();
+ Services.cpmm.sendAsyncMessage(IPC_P_MSG.SERVICE_READY);
+ } catch (e) {
+ Components.utils.reportError(e);
+ }
+})();
diff --git a/extensions/noscript/chrome/content/noscript/e10sIPC.js b/extensions/noscript/chrome/content/noscript/e10sIPC.js
new file mode 100644
index 0000000..a2716c6
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/e10sIPC.js
@@ -0,0 +1,68 @@
+var IPC_MSG = {
+ SYNC: "NoScript:syncUI",
+ NOTIFY_META: "NoScript:notifyMetaRefresh",
+ CLEARCLICK_WARNING: "NoScript:clearClickWarning",
+},
+IPC_P_MSG = {
+ SERVICE_READY: "NoScript:ServiceReady",
+ LOAD_SURROGATE: "NoScript:loadSurrogate",
+ CALL: "NoScript:remoteCall",
+ RESUME: "NoScript:resume",
+ GET_PREF: "NoScript:getPref",
+ GET_SNAPSHOT: "NoScript:getSnapshot",
+ CALLBACK: "NoScript:callback",
+}
+
+var IPC = {
+ logger: null,
+ log(...args) {
+ if (this.logger) {
+ args[0] = `[${this.parent ? 'P' : 'C'}] ${args[0]}`;
+ this.logger(...args);
+ }
+ },
+ registry: null,
+ autoSync(obj, objName, methods) {
+ if (!this.registry) this.registry = new Map();
+ this.registry.set(objName, {
+ reference: obj,
+ methods: new Set(methods),
+ });
+
+ for (let m of methods) {
+ let method = m; // hack needed in Fx < 50
+ if (!(method in obj)) {
+ ns.log(`method ${method} not found in ${objName}\n`);
+ }
+ let func = obj[method];
+ if (func._autoSynced) continue;
+ (obj[method] = (...args) => {
+ let stack = Components.stack;
+ let caller = stack.caller;
+ if (caller.name !== "call" || stack.filename !== caller.filename) {
+ let process = IPC.parent || IPC.child;
+ process.remote(objName, method, args);
+ }
+ return func.apply(obj, args);
+ })._autoSynced = true;
+ }
+ return true;
+ },
+ call(objName, method, args) {
+ let {reference, methods} = this.registry.get(objName);
+ if (methods.has(method)) {
+ reference[method].apply(reference, args);
+ }
+ },
+
+ receiveMessage(m) {
+ if (this.logger) this.log(`Received message ${m.name} - ${JSON.stringify(m.data)}`);
+ switch(m.name) {
+ case IPC_P_MSG.CALL:
+ let { objName, method, args } = m.data;
+ IPC.call(objName, method, args);
+ return true;
+ }
+ return false;
+ },
+};
diff --git a/extensions/noscript/chrome/content/noscript/e10sParent.js b/extensions/noscript/chrome/content/noscript/e10sParent.js
new file mode 100644
index 0000000..a3d92aa
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/e10sParent.js
@@ -0,0 +1,101 @@
+IPC.parent = {
+ FRAME_SCRIPT: NO_CACHE("frameScript.js"),
+ PROCESS_SCRIPT: NO_CACHE("e10sProcessScript.js"),
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener, Ci.nsISupportsWeakReference]),
+ init() {
+ let globalMM = Services.mm;
+ for (let m of Object.keys(IPC_MSG)) {
+ globalMM.addWeakMessageListener(IPC_MSG[m], this);
+ }
+ let processMM = Services.ppmm;
+ for (let m of Object.keys(IPC_P_MSG)) {
+ processMM.addWeakMessageListener(IPC_P_MSG[m], this);
+ }
+ processMM.loadProcessScript(this.PROCESS_SCRIPT, true);
+ globalMM.loadFrameScript(this.FRAME_SCRIPT, true);
+ },
+ dispose() {
+ let globalMM = Services.mm;
+ for (let m of Object.keys(IPC_MSG)) {
+ globalMM.removeWeakMessageListener(IPC_MSG[m], this);
+ }
+ let processMM = Services.ppmm;
+ for (let m of Object.keys(IPC_P_MSG)) {
+ processMM.removeWeakMessageListener(IPC_P_MSG[m], this);
+ }
+ globalMM.removeDelayedFrameScript(this.FRAME_SCRIPT);
+ globalMM.broadcastAsyncMessage("NoScript:unload");
+ processMM.removeDelayedProcessScript(this.PROCESS_SCRIPT);
+ processMM.broadcastAsyncMessage("NoScript:unload");
+ },
+
+
+ receiveMessage(m) {
+ ns.onContentInit();
+ this.receiveMessage = this._receiveMessageReal;
+ return this.receiveMessage(m);
+ },
+ _receiveMessageReal(m) {
+ if (IPC.receiveMessage(m)) {
+ return;
+ }
+ switch(m.name) {
+ case IPC_MSG.SYNC:
+ ns.setExpando(m.target, "sites", m.data);
+ ns.syncUI(m.target);
+ return;
+ case IPC_MSG.NOTIFY_META:
+ let browser = m.target;
+ info.browser = browser;
+ browser.defaultView.noscriptOverlay.notifyMetaRefresh(info);
+ return;
+ case IPC_MSG.CLEARCLICK_WARNING:
+ return ClearClickHandler.prototype.showWarningParent(m.target.ownerDocument.defaultView, m.data).locked;
+ case IPC_P_MSG.CALLBACK:
+ let {id, execute} = m.data;
+ this._handleCallback(id, execute);
+ return;
+ case IPC_P_MSG.LOAD_SURROGATE:
+ return ScriptSurrogate.loadReplacementFile(ScriptSurrogate.getReplacement(m.data));
+ case IPC_P_MSG.RESUME:
+ return IOUtil.resumeParentChannel(m.data.id, m.data.abort);
+ case IPC_P_MSG.GET_PREF:
+ let {method, name} = m.data;
+ if (method in Services.prefs && method.startsWith("get")) {
+ try {
+ return Services.prefs[method](name);
+ } catch (e) {
+ Cu.reportError(e);
+ }
+ }
+ return null;
+ case IPC_P_MSG.GET_SNAPSHOT:
+ return ns.getSnapshot();
+ }
+ },
+
+ remote(objName, method, args) {
+ Services.ppmm.broadcastAsyncMessage(IPC_P_MSG.CALL, {objName, method, args});
+ },
+
+ _callbacks: new Map(),
+ _callbackId: 0,
+ callback(f) {
+ this._callbacks.set(++this._callbackId, f);
+ return this._callbackId;
+ },
+ _handleCallback(id, execute) {
+ let callback = this._callbacks.get(id);
+ if (callback) this._callbacks.delete(id);
+ if (execute) {
+ try {
+ callback();
+ } catch (e) {
+ Cu.reportError(e);
+ }
+ }
+ },
+};
+
+IPC.parent.init();
+
diff --git a/extensions/noscript/chrome/content/noscript/e10sProcessScript.js b/extensions/noscript/chrome/content/noscript/e10sProcessScript.js
new file mode 100644
index 0000000..d070694
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/e10sProcessScript.js
@@ -0,0 +1,8 @@
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
+ Components.utils.import(`chrome://noscript/content/importer.jsm`);
+ Services.scriptloader.loadSubScript(NO_CACHE(`e10sChild.js`), {});
+} else {
+ // nothing to do exclusively in the parent process yet...
+}
diff --git a/extensions/noscript/chrome/content/noscript/frameScript.js b/extensions/noscript/chrome/content/noscript/frameScript.js
new file mode 100644
index 0000000..808ce33
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/frameScript.js
@@ -0,0 +1,3 @@
+Components.utils.import("chrome://noscript/content/importer.jsm");
+IMPORT_FOR(this)("FrameScript");
+new FrameScript(this);
diff --git a/extensions/noscript/chrome/content/noscript/html5_events b/extensions/noscript/chrome/content/noscript/html5_events
new file mode 100644
index 0000000..1ee6251
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/html5_events
@@ -0,0 +1,98 @@
+#!/usr/bin/perl
+use strict;
+
+require LWP::UserAgent;
+use LWP::Simple;
+use RegExp::List;
+use File::stat;
+use File::Basename;
+use List::MoreUtils qw(uniq);
+
+my $HTML5_URL = "https://hg.mozilla.org/mozilla-central/raw-file/tip/parser/html/nsHtml5AtomList.h";
+my $GECKO_URL = "https://hg.mozilla.org/mozilla-central/raw-file/tip/dom/base/nsGkAtomList.h";
+
+my $SOURCE_FILE = dirname($0) . '/InjectionChecker.js';
+
+sub create_re
+{
+ my $cache = "/tmp/html5_events.re";
+ my $sb = stat($cache);
+
+ if ($sb && time() - $sb->mtime < 86400)
+ {
+ open IN, "<$cache";
+ my @content = <IN>;
+ close IN;
+ return $content[0];
+ }
+
+ sub fetch_url
+ {
+ my $url = shift(@_);
+ my $ua = LWP::UserAgent->new;
+ $ua->agent('Mozilla/5.0');
+ $ua->ssl_opts('verify_hostname' => 0);
+ my $res = $ua->get($url);
+ if ($res->is_success)
+ {
+ return $res->decoded_content;
+ }
+ else
+ {
+ my $err = $res->content;
+ my $ca_file = $ua->ssl_opts('SSL_ca_file');
+ die ("Could not fetch $url: $err\n$ca_file");
+ }
+ }
+
+
+ my $content = # fetch_url($HTML5_URL) .
+ fetch_url($GECKO_URL);
+
+ $content = join("\n", grep(/^(?:HTML5|GK)_ATOM.*"on\w+"/, split(/[\n\r]/, $content)));
+
+ $content =~ s/.*"(on\w+)".*/$1 /g;
+ $content =~ s/\s+/ /g;
+ $content =~ s/^\s+|\s+$//g;
+
+ my $l = Regexp::List->new;
+ my $re = $l->list2re(uniq(split(' ', $content)));
+ $re =~ s/\(\?[-^]\w+:(.*)\)/$1/;
+ open (OUT, ">$cache");
+ print OUT $re;
+ close OUT;
+ $re;
+}
+
+sub patch
+{
+ my $src = shift;
+ my $dst = "$src.tmp";
+ my $re = create_re();
+ my $must_replace = 0;
+ print "Patching $src...\n";
+ open IN, "<$src" or die ("Can't open $src!");
+ open OUT, ">$dst" or die ("Can't open $dst!");
+
+ while (<IN>)
+ {
+ my $line = $_;
+ $must_replace = $line ne $_ if s/^(\s*const IC_EVENT_PATTERN\s*=\s*")([^"]+)/$1$re/;
+
+ print OUT $_;
+ }
+ close IN;
+ close OUT;
+
+ if ($must_replace) {
+ rename $dst, $src;
+ print "Patched.\n";
+ }
+ else
+ {
+ unlink $dst;
+ print "Nothing to do.\n";
+ }
+}
+
+patch($SOURCE_FILE);
diff --git a/extensions/noscript/chrome/content/noscript/iaUI.js b/extensions/noscript/chrome/content/noscript/iaUI.js
new file mode 100644
index 0000000..a3db58f
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/iaUI.js
@@ -0,0 +1,204 @@
+var $ = function(id) { return document.getElementById(id); }
+var $$ = function(tag) { return document.getElementsByTagName(tag); }
+
+function UIUtils(serv) {
+ this.serv = serv;
+}
+UIUtils.prototype = {
+ tabselPrefName: "options.tabSelectedIndexes",
+ resumeTabSelections: function() {
+ var info = window.arguments && window.arguments[0];
+ var indexes = info && info.tabselIndexes ||
+ this.serv.getPref(this.tabselPrefName, "").split(/\s*,\s*/);
+ // select tabs from external param
+
+ var tabs = $$("tabs");
+ var tcount = Math.min(tabs.length, indexes.length);
+ var self = this;
+ var listener = function(ev) { self.persistTabSelections(); }
+ for(var t = tabs.length; t-- > 0;) {
+ try {
+ tabs[t].selectedIndex = parseInt(indexes[t]) || 0;
+ } catch(e) {}
+ tabs[t].addEventListener("select", listener, false);
+ }
+ this.persistTabSelections();
+
+ if (info && info.callback) {
+ window.setTimeout(info.callback, 0);
+ }
+ },
+
+ persistTabSelections: function() {
+ var tabs = $$("tabbox");
+ var ss = [];
+ for(var tcount = 0; tcount < tabs.length; tcount++) {
+ ss.push(tabs[tcount].selectedIndex);
+ }
+ this.serv.setPref(this.tabselPrefName, ss.join(","));
+ },
+
+ visitCheckboxes: function(callback) {
+ const rxOpt=/^(inv|moz|)opt-(.*)/;
+ var j, checkbox, match;
+ const opts = $$("checkbox");
+ for(j = opts.length; j-- > 0;) {
+ checkbox = opts[j];
+ if((match = checkbox.id.match(rxOpt))) {
+ callback(match[2], match[1] == "inv", checkbox, match[1] == "moz");
+ }
+ }
+ },
+
+ visitTextboxes: function(callback) {
+ const rxOpt=/^opt-(.*)/;
+ var j, box, match;
+ const opts = $$("textbox");
+ for(j = opts.length; j-- > 0;) {
+ box = opts[j];
+ if((match = box.id.match(rxOpt))) {
+ callback(match[1], box);
+ }
+ }
+ },
+
+ syncGroup: function(caption) {
+ var b = !caption.checked;
+ var node = caption.parentNode;
+ while((node = node.nextSibling)) {
+ node.disabled = b;
+ }
+ },
+
+ moveButtonsDown: function() {
+ var ref = document.documentElement.getButton("extra2");
+ Array.slice(arguments, 0).forEach(function(s) {
+ var b;
+ if (s) {
+ b = $(s);
+ b.className = ref.className;
+ } else {
+ b = document.createElement("spacer");
+ b.setAttribute("flex", "1");
+ }
+ ref.parentNode.insertBefore(b, ref);
+ b.hidden = false;
+ });
+ }
+};
+
+
+function ConditionalGroup(serv, prefName, def) {
+ this.serv = serv;
+ this.prefName = prefName;
+ this.cbx = $("cbx-" + prefName);
+ this.sel = $("sel-" + prefName);
+ var value = this.serv.getPref(prefName) || 0;
+ this.defaultIndex = typeof(def) == "number" ? def - 1 : 0;
+ this.cbx.checked = !!value;
+ this.sel.selectedIndex = value ? value - 1: this.defaultIndex;
+ var self = this;
+ this.cbx.addEventListener("command", function(ev) { self.changed() }, false);
+ this.changed();
+}
+
+ConditionalGroup.changed = function(cbx) {
+ cbx.conditionalGroup.changed();
+}
+
+ConditionalGroup.prototype = {
+ changed: function() {
+ this.sel.disabled = !this.cbx.checked;
+ if(this.cbx.checked && this.sel.selectedIndex < 0)
+ this.sel.selectedIndex = this.defaultIndex;
+ },
+ getValue: function() {
+ return this.cbx.checked && this.sel.selectedIndex + 1 || 0;
+ },
+ persist: function() {
+ this.serv.setPref(this.prefName, this.getValue());
+ }
+};
+
+function SoundChooser(id, title, serv, def) {
+ this.id = id;
+ this.title = title;
+ this.serv = serv;
+ this.def = def;
+}
+
+SoundChooser.prototype = {
+ choose: function(btn) {
+ try {
+ const cc=Components.classes;
+ const ci=Components.interfaces;
+ const fp = cc["@mozilla.org/filepicker;1"].createInstance(ci.nsIFilePicker);
+
+ fp.init(window, this.title, ci.nsIFilePicker.modeOpen);
+ fp.appendFilter(this.serv.getString("audio.samples"),"*.wav");
+ fp.filterIndex = 0;
+ let done = ret => {
+ if (ret == ci.nsIFilePicker.returnOK || ret == ci.nsIFilePicker.returnReplace) {
+ this.setSample(fp.fileURL.spec);
+ this.play();
+ }
+ };
+ if (fp.show) done(fp.show);
+ else fp.open({done});
+ } catch(ex) {
+ Components.utils.import("resource://gre/modules/Services.jsm");
+ Services.prompt.alert(window, this.title, ex.toString());
+ }
+ },
+ setSample: function(url) {
+ $(this.id).value = url || this.def;
+ },
+ getSample: function() {
+ return $(this.id).value;
+ },
+ play: function() {
+ this.serv.playSound(this.getSample(), true);
+ }
+};
+
+function RegExpController(prefix, parseMethod, value) {
+ this.parse = parseMethod || this.parse;
+ this.regexp = $(prefix + "-regexp");
+ this.sample = $(prefix + "-sample");
+ var listener = function(ev) { arguments.callee.binding.feedback(); };
+ listener.binding = this;
+ this.regexp.addEventListener("input", listener, false);
+ this.sample.addEventListener("input", listener, false);
+ this.regexp.value = value;
+ this.feedback();
+}
+
+RegExpController.prototype = {
+ parse: function(s) { return new RegExp(s, "g"); },
+ validate: function() {
+ const textbox = this.regexp;
+ try {
+ const rx = this.parse(textbox.value);
+ if(rx) {
+ textbox.className = "";
+ return rx;
+ }
+ } catch(e) {}
+ textbox.className = "noscript-error";
+ return null;
+ },
+ feedback: function() {
+ const rx = this.validate();
+ const sample = this.sample;
+ if(rx && rx.test(sample.value)) {
+ sample.className = "";
+ } else {
+ sample.className = "noscript-error";
+ }
+ return rx;
+ },
+ getValue: function(valid) {
+ if(valid && !this.validate()) return null;
+ return this.regexp.value;
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/importer.jsm b/extensions/noscript/chrome/content/noscript/importer.jsm
new file mode 100644
index 0000000..131bae4
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/importer.jsm
@@ -0,0 +1,30 @@
+var EXPORTED_SYMBOLS = ["NO_CACHE", "IMPORT_FOR", "UNLOAD", "UNLOAD_ALL", "BASE_URL"];
+
+let { utils: Cu } = Components;
+
+let BASE_URL = "chrome://noscript/content/";
+let toURL = name => `${name}.jsm`;
+
+let _NO_CACHE_KEY = Date.now().toString(32).concat(Math.random().toString(32).substring(2));
+
+function NO_CACHE(url) {
+ return `${BASE_URL}${url}?${_NO_CACHE_KEY}`;
+}
+
+let _MODULES = new Set();
+
+function IMPORT_FOR(scope) {
+ return name => {
+ let url = NO_CACHE(toURL(name));
+ _MODULES.add(url);
+ return Cu.import(url, scope);
+ };
+}
+
+function UNLOAD(name) {
+ Cu.unload(NO_CACHE(toURL(name)));
+}
+function UNLOAD_ALL() {
+ for (let m of _MODULES) Cu.unload(m);
+ UNLOAD("importer");
+}
diff --git a/extensions/noscript/chrome/content/noscript/loader.js b/extensions/noscript/chrome/content/noscript/loader.js
new file mode 100644
index 0000000..5995556
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/loader.js
@@ -0,0 +1,73 @@
+// const TIME0 = Date.now();
+
+var { interfaces: Ci, classes: Cc, utils: Cu, results: Cr } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import(`chrome://noscript/content/importer.jsm`);
+var IMPORT = IMPORT_FOR(this);
+
+var IOS = Services.io;
+var OS = Services.obs;
+var LOADER = Services.scriptloader;
+
+
+var _INCLUDED = new Set();
+
+var INCLUDE = function (...objectNames) {
+ for (let objectName of objectNames) {
+ if (!(_INCLUDED.has(objectName))) {
+ _INCLUDED.add(objectName);
+ // let t = Date.now();
+ LOADER.loadSubScript(NO_CACHE(`${objectName}.js`), this);
+ // dump((t - TIME0) + " - loaded " + objectName + " in " + (Date.now() - t) + "\n")
+ }
+ }
+};
+
+function LAZY_INCLUDE(...objectNames) {
+ for (let objectName of objectNames) {
+ if (!(_INCLUDED.has(objectName))) {
+ let key = objectName; // hack needed in Fx < 50
+ this.__defineGetter__(key, function() {
+ delete this[key];
+ // dump(objectName + " kickstarted at " + (new Error().stack));
+ INCLUDE(key);
+ return this[key];
+ });
+ }
+ }
+}
+
+function INCLUDE_MIXIN(target, ...objectNames) {
+ INCLUDE(...objectNames);
+ return MIXIN(target, ...objectNames.map(objectName => this[objectName]));
+}
+
+function MIXIN(target, ...objects) {
+ for (let o of objects) {
+ let object = o; // hack needed in Fx < 50
+ Object.defineProperties(target, Object.keys(object).reduce((descriptors, key) => {
+ descriptors[key] = Object.getOwnPropertyDescriptor(object, key);
+ return descriptors;
+ }, {}));
+ }
+ return target;
+}
+
+var COMPAT = {
+ setStringPref(branch, name, value) {
+ if (branch.setStringPref) {
+ branch.setStringPref(name, value);
+ } else {
+ let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
+ str.data = value;
+ branch.setComplexValue(name, Ci.nsISupportsString, str);
+ }
+ },
+
+ getStringPref(branch, name, defValue) {
+ return branch.getStringPref ? branch.getStringPref(name, defValue)
+ : branch.getComplexValue(name, Ci.nsISupportsString).data || defValue;
+ }
+};
diff --git a/extensions/noscript/chrome/content/noscript/noscript.js b/extensions/noscript/chrome/content/noscript/noscript.js
new file mode 100644
index 0000000..7c30dec
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/noscript.js
@@ -0,0 +1,193 @@
+window.noscriptUtil = {
+ chromeBase: "chrome://noscript/content/",
+ chromeName: "noscript",
+ getService(callback) {
+ let service;
+ try {
+ service = Components.classes["@maone.net/noscript-service;1"].getService().wrappedJSObject;
+ if (callback) callback(service);
+ } catch(ex) {
+ Cu.reportError(ex);
+ if (callback) {
+ window.setTimeout(() => callback(this.getService()), 100);
+ } else {
+ throw ex;
+ }
+ }
+ return service;
+ },
+ get service() {
+ delete this.service;
+ return (this.service = this.getService());
+ },
+
+ confirm: function(msg, persistPref, title = "NoScript") {
+ return this.service.confirm(msg, persistPref, title, window);
+ },
+
+ getString: function(key, parms) {
+ return this.service.getString(key, parms);
+ }
+,
+ openOptionsDialog: function(params) {
+ let odRef = this.service.optionsDialogRef;
+ let od;
+ try {
+ od = odRef && odRef.get();
+ if (od && !od.closed) {
+ od.focus();
+ return;
+ }
+ } catch (e) {}
+ window.openDialog(
+ this.chromeBase + this.chromeName + "Options.xul",
+ this.chromeName + "Options",
+ "chrome, dialog=no, centerscreen, resizable=no, alwaysraised=no",
+ params);
+ },
+
+ openXssOptions: function() {
+ this.openOptionsDialog({tabselIndexes: [5, 2]});
+ },
+ openABEOptions: function(info) {
+ this.openOptionsDialog({
+ tabselIndexes: [5, 4],
+ callback: info ? function() { this.abeOpts.select(info.ruleset); } : null
+ });
+ },
+ openEFOptions: function(filterName) {
+ if (filterName) {
+ if ("getAttribute" in filterName) filterName = filterName.getAttribute("statustext");
+ this.service.externalFilters.lastFilterName = filterName;
+ }
+ this.openOptionsDialog({tabselIndexes: [5, 5]});
+ }
+,
+ openAboutDialog: function(params) {
+ window.open(
+ this.chromeBase + "about.xul",
+ this.chromeName + "About",
+ "chrome,dialog,centerscreen");
+ }
+,
+ openConsole: function() {
+ if ("HUDService" in window && HUDService.getBrowserConsole && HUDService.toggleBrowserConsole) {
+ let bc = HUDService.getBrowserConsole();
+ function showJS(bc) { bc.setFilterState("jslog", true); }
+ if (bc) {
+ showJS(bc);
+ let w = bc.chromeWindow;
+ if (w.windowState === w.STATE_MINIMIZED) {
+ w.restore();
+ }
+ w.focus();
+ }
+ else HUDService.toggleBrowserConsole().then(showJS);
+
+ } else if ("toErrorConsole" in window) {
+ toErrorConsole();
+ }
+ else if ("toJavaScriptConsole" in window) {
+ toJavaScriptConsole();
+ } else {
+ window.openDialog("chrome://global/content/console.xul", "", "chrome,all,dialog=no");
+ }
+ },
+
+ openFaq: function(which) {
+ this.browse("https://noscript.net/faq#" + which);
+ },
+
+ openHelp: function(section) {
+ this.browse("https://noscript.net/help/" + section);
+ },
+
+ openDonate: function(src) {
+ this.browse("https://secure.informaction.com/donate/?id=noscript&src=" + src);
+ },
+
+ openInfo: function(about) {
+ const ns = this.service;
+
+ let url = ns.getPref("siteInfoProvider");
+ if (!url) return false;
+
+ let domain = ns.getSite(about);
+ if (!domain) return false;
+
+ if (domain.indexOf('@') > -1) domain = domain.split('@')[1]; // Blocked objects entries
+ if (domain.indexOf(':') > -1) domain = ns.getDomain(domain) || domain;
+ if (!domain) return false;
+
+ let ace;
+ try {
+ ace = Cc["@mozilla.org/network/idn-service;1"]
+ .getService(Ci.nsIIDNService).convertUTF8toACE(domain);
+ } catch(e) {
+ ace = '';
+ }
+
+ url = url.replace(/%utf8%/g, encodeURI(domain))
+ .replace(/%ace%/g, encodeURI(ace));
+
+ if (this.confirm(
+ this.getString("siteInfo.confirm", [domain, ns.getSite(url) || "?", url]),
+ "confirmSiteInfo", "NoScript"
+ )) {
+ let currentTab = window.gBrowser && gBrowser.selectedTab;
+ let w = this.browse(url);
+ if ("noscriptOverlay" in window) {
+ let et = "DOMContentLoaded";
+ let eh = function(ev) {
+ let d = ev.target;
+ if (d.URL !== url) return;
+ let button = d.getElementById("allow-button");
+ if (!button) return;
+
+ let ns = noscriptOverlay.ns;
+ let enabled = ns.isJSEnabled(domain);
+
+ button.firstChild.textContent = noscriptOverlay.getString((enabled ? "forbidLocal" : "allowLocal"), [domain]);
+ button.style.display = "";
+ button.className = enabled ? "forbid" : "allow";
+
+ function complete(enable) {
+ noscriptOverlay.safeAllow(domain, enable, false, ns.RELOAD_ALL);
+ d.defaultView.close();
+ if (currentTab) gBrowser.selectedTab = currentTab;
+ }
+
+ button.addEventListener("click", (e) => complete(!enabled), false);
+
+ if (!(enabled || ns.isUntrusted(domain))) {
+ button = d.getElementById("distrust-button");
+ if (!button) return;
+ button.style.display = "";
+ button.firstChild.textContent = noscriptOverlay.getString("distrust", [domain]);
+ button.addEventListener("click", function(e) {
+ ns.setUntrusted(domain, true);
+ complete(false);
+ }, false);
+ }
+ };
+ w.addEventListener(et, eh, true);
+
+ w.setTimeout(() => w.removeEventListener(et, eh, true), 20000);
+ }
+ return true;
+ }
+
+ return false;
+ },
+
+ browse: function(url, features) {
+ var w = this.service.dom.mostRecentBrowserWindow;
+ if(w && !w.closed && w.gBrowser) {
+ w.gBrowser.selectedTab = w.gBrowser.addTab(url);
+ } else {
+ window.open(url, "_blank", features || null).focus();
+ }
+ return w;
+ }
+
+};
diff --git a/extensions/noscript/chrome/content/noscript/noscript.xbl b/extensions/noscript/chrome/content/noscript/noscript.xbl
new file mode 100644
index 0000000..51361b0
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/noscript.xbl
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<bindings id="noscriptBindings"
+ xmlns="http://www.mozilla.org/xbl"
+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:xbl="http://www.mozilla.org/xbl">
+
+ <binding id="nop"></binding>
+ <binding id="scrollable-popup"
+ extends="chrome://global/content/bindings/popup.xml#popup-base">
+
+ <content>
+ <xul:arrowscrollbox clicktoscroll="true"
+ class="popup-internal-box" flex="1" orient="vertical">
+ <children/>
+ </xul:arrowscrollbox>
+ </content>
+ </binding>
+</bindings>
diff --git a/extensions/noscript/chrome/content/noscript/noscriptBM.js b/extensions/noscript/chrome/content/noscript/noscriptBM.js
new file mode 100644
index 0000000..3ba480c
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/noscriptBM.js
@@ -0,0 +1,127 @@
+window.noscriptBM = {
+
+ openUILinkIn: function(url, ...args) {
+ var callback = () => openUILinkIn._noscriptBMSaved(url, ...args);
+
+ if(!(window.gURLBar && gURLBar.value))
+ return callback();
+
+ var shortcut = gURLBar.value;
+ var jsrx = /^\s*(?:data|javascript):/i;
+ var isJS = jsrx.test(url);
+ var ns = noscriptUtil.service;
+
+
+ if (isJS) {
+ let allowJS = ns.getPref("allowURLBarJS", true);
+ let isShortcut = ("originalShortcut" in gURLBar) && gURLBar.originalShortcut !== shortcut;
+ if (allowJS || isShortcut || !/\bhandleCommand@/.test(new Error().stack)) {
+ window.setTimeout(function() { // if we don't defer, errors are not logged in the console...
+ if (!ns.executeJSURL(url, callback, !isShortcut))
+ callback();
+ }, 0);
+ } else {
+ ns.prompter.alert(window, "NoScript",
+ "javascript: and data: URIs typed or pasted in the address bar are disabled to prevent social engineering attacks.\nDevelopers can enable them for testing purposes by toggling the \"noscript.allowURLBarJS\" preference.");
+ }
+ return;
+ }
+
+ return callback();
+ },
+
+ patchPlacesMethods: function(pu) {
+ let ns = noscriptUtil.service;
+ if (pu.__ns === ns) return; // already patched
+ pu.__ns = ns;
+ if (!pu.__originalCheckURLSecurity) {
+ pu.__originalCheckURLSecurity = pu.checkURLSecurity;
+ }
+ pu.checkURLSecurity = ns.placesCheckURLSecurity;
+
+ ns.onDisposal(() => {
+ if ("__originalCheckURLSecurity" in pu) {
+ pu.checkURLSecurity = pu.__originalCheckURLSecurity;
+ delete pu.__originalCheckURLSecurity;
+ }
+ delete pu.__ns;
+ });
+
+ },
+
+ onLoad: function(ev) {
+ ev.currentTarget.removeEventListener("load", arguments.callee, false);
+ if(!noscriptUtil.service) return;
+ window.addEventListener("unload", noscriptBM.dispose, false);
+ noscriptBM.init();
+ },
+
+ _inited: false,
+ init: function() {
+ // patch URLBar for keyword-triggered bookmarklets:
+ // we do it early, in case user has a bookmarklet startup page
+ if (noscriptBM._inited) return;
+ noscriptBM._inited = true;
+ if (!window.openUILinkIn) return;
+ let original = window.openUILinkIn._noscriptBMSaved;
+ this.openUILinkIn._noscriptBMSaved = original || window.openUILinkIn;
+ window.openUILinkIn = this.openUILinkIn;
+ noscriptBM.onDisposal(() => {
+ window.openUILinkIn = window.openUILinkIn._noscriptBMSaved;
+ });
+
+ // delay bookmark stuff
+ window.setTimeout(noscriptBM.delayedInit, 50);
+ },
+
+ delayedInit: function() {
+ for (let f of ["getShortcutOrURIAndPostData" /* Fx >= 25 */, "getShortcutOrURI"]) {
+ if (f in window) {
+ let getShortcut = window[f];
+ if (getShortcut._noscriptBM) return;
+
+ let replacement = function(aURL) {
+ if ("gURLBar" in window && window.gURLBar) {
+ window.gURLBar.originalShortcut = aURL;
+ }
+ return getShortcut.apply(window, arguments);
+ };
+ replacement._noscriptBM = true;
+
+ window[f] = replacement;
+ noscriptBM.onDisposal(() => {
+ window[f] = getShortcut;
+ });
+ break;
+ }
+ }
+
+ // Places stuff, from most recent to oldest
+ var pu = window.PlacesUIUtils || window.PlacesUtils || false;
+ if (typeof(pu) == "object") {
+ noscriptBM.placesUtils = pu; // hold a reference even if in Fx 4 it's a module
+ noscriptBM.patchPlacesMethods(pu);
+ }
+ },
+
+ _disposalTasks: [],
+ onDisposal(t) {
+ this._disposalTasks.push(t);
+ },
+ dispose() {
+ window.removeEventListener("unload", noscriptBM.dispose, false);
+ let ns = noscriptUtil.service;
+ let tasks = noscriptBM._disposalTasks;
+ for (let t of tasks) {
+ try {
+ if (ns.consoleDump) ns.dump(`Running noscriptBM disposal task ${uneval(t)}`);
+ t();
+ } catch (e) {
+ Components.utils.reportError(e);
+ }
+ }
+ delete window.noscriptBM;
+ }
+};
+
+
diff --git a/extensions/noscript/chrome/content/noscript/noscriptBMOverlay.xul b/extensions/noscript/chrome/content/noscript/noscriptBMOverlay.xul
new file mode 100644
index 0000000..866328d
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/noscriptBMOverlay.xul
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE overlay>
+
+<overlay id="noscriptBMOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/x-javascript" src="noscript.js" />
+ <script type="application/x-javascript" src="noscriptBM.js"/>
+ <script type="application/x-javascript">window.addEventListener("load", noscriptBM.onLoad, false)</script>
+</overlay>
diff --git a/extensions/noscript/chrome/content/noscript/noscriptOptions.js b/extensions/noscript/chrome/content/noscript/noscriptOptions.js
new file mode 100644
index 0000000..f9b3ca4
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/noscriptOptions.js
@@ -0,0 +1,755 @@
+// Cc, Ci, Cu should be already defined by tree-copy.js
+
+var ns = noscriptUtil.service;
+
+var nsopt = {
+
+
+ dom2: /^(?:http[s]?|file):\/\/([^\.\?\/#,;:\\\@]+(:?\.[^\.\?\/#,;:\\\@]+$|$))/,
+ utils: null,
+ whitelistURLs: [],
+ init: function() {
+
+ if(ns.uninstalling) { // this should never happen!
+ window.close();
+ return;
+ }
+
+ ns.optionsDialogRef = Components.utils.getWeakReference(window);
+
+ this.utils = new UIUtils(ns);
+ this.utils.resumeTabSelections();
+
+ abeOpts.init();
+
+ var locked = ns.locked;
+ for (var widget of ["urlText","urlListDisplay", "jsglobal", "addButton", "removeButton", "importButton", "exportButton"]) {
+ this[widget] = $(widget);
+ if(locked) this[widget].disabled = true;
+ }
+ // forbid <a ping>
+ var pingCbx = $("mozopt-browser.send_pings");
+ if(pingCbx.getAttribute("label").indexOf("Allow ") == 0) {
+ pingCbx.setAttribute("label", noscriptUtil.getString("allowLocal", ["<a ping...>"]));
+ $("opt-noping")
+ .setAttribute("label", noscriptUtil.getString("forbidLocal", ["<a ping...>"]));
+ }
+
+ this.trustedSites = ns.jsPolicySites.clone();
+ this.untrustedSites = ns.untrustedSites.clone();
+ this.tempSites = ns.tempSites.clone();
+ this.gTempSites = ns.gTempSites.clone();
+
+ this.urlListDisplay.boxObject.QueryInterface(Ci.nsITreeBoxObject);
+ this.populateUrlList();
+
+ this.jsglobal.checked = ns.jsEnabled;
+
+ this.utils.visitCheckboxes(function(prefName, inverse, checkbox, mozilla) {
+ try {
+ var val = mozilla ? ns.prefService.getBoolPref(prefName) : ns.getPref(prefName);
+ checkbox.setAttribute("checked", inverse ? !val : val);
+ if(ns.prefService.prefIsLocked(mozilla ? prefName : "noscript." + prefName)) {
+ checkbox.setAttribute("disabled", true);
+ }
+ } catch(ex) {}
+ }
+ );
+
+ this.utils.visitTextboxes(function(prefName, box) {
+ box.value = ns.getPref(prefName);
+ });
+
+ $("opt-showPermanent").setAttribute("label", noscriptUtil.getString("allowLocal", ["[...]"]));
+ $("opt-showTemp").setAttribute("label", noscriptUtil.getString("allowTemp", ["[...]"]));
+ $("opt-showDistrust").setAttribute("label", noscriptUtil.getString("distrust", ["[...]"]));
+ $("opt-showGlobal").setAttribute("label", noscriptUtil.getString("allowGlobal"));
+
+ var notifyHideLabels = noscriptUtil.getString("notifyHide").split("%S");
+ $("opt-notify.hide").setAttribute("label", notifyHideLabels[0]);
+ $("notifyDelayLabel").setAttribute("value", notifyHideLabels[1]);
+ $("notifyDelay").value = ns.getPref("notify.hideDelay", 5);
+
+ this.soundChooser.setSample(ns.getPref("sound.block"));
+
+ this.autoAllowGroup = new ConditionalGroup(ns, "autoAllow", 1);
+ this.toggleGroup = new ConditionalGroup(ns, "toolbarToggle", 3);
+
+ var val = ns.getPref("allowHttpsOnly", 0);
+ $("sel-allowHttpsOnly").selectedIndex = (val < 0 || val > 2) ? 0 : val;
+
+ var shortcut = ns.getPref("keys.toggle");
+ if(shortcut) {
+ shortcut = shortcut.replace(/VK_([^\.]*).*/g, "$1").replace(/\s+/g, '+').replace(/_/g, ' ');
+ var shortcutLabel = $("toolbarToggle-shortcut");
+ shortcutLabel.value = "(" + shortcut + ")";
+ shortcutLabel.removeAttribute("hidden");
+ }
+
+ this.utils.syncGroup($("opt-secureCookies"));
+
+ this.xssEx = new RegExpController(
+ "xssEx",
+ ns.rxParsers.multi,
+ ns.getPref("filterXExceptions"));
+
+ // hide incompatible options
+ let browserWin = ns.dom.mostRecentBrowserWindow;
+
+ if (browserWin) {
+ if (!browserWin.document.getElementById("noscript-statusIcon"))
+ $("opt-statusIcon").setAttribute("hidden", "true");
+
+ if(browserWin.noscriptOverlay && !browserWin.noscriptOverlay.getNotificationBox())
+ $("fx-notifications").setAttribute("hidden", "true");
+ }
+
+ ["clearClick"].forEach(function(c) {
+ var pref = ns.getPref(c);
+ Array.forEach($(c + "Opts").getElementsByTagName("checkbox"), function(cbx) {
+ cbx.setAttribute("checked", !(pref & parseInt(cbx.getAttribute("value"))) ? "false" : "true");
+ });
+ });
+
+
+
+ $("opt-allowClipboard").setAttribute("collapsed", "true");
+
+ this.initExtraButtons();
+
+ this.addButton.setAttribute("enabled", "false");
+ this.removeButton.setAttribute("enabled", "false");
+
+ this.toggleHoverUI();
+
+
+
+ window.sizeToContent();
+ },
+
+ dispose: function() {
+ abeOpts.dispose();
+ },
+
+ initExtraButtons: function() {
+ this.utils.moveButtonsDown("donateButton", "", "importConfButton", "exportConfButton");
+ },
+
+
+ donate: function() {
+ noscriptUtil.openDonate("options");
+ },
+
+ importConf: function() {
+ this.chooseFile(
+ this.buttonToTitle("importConfButton"),
+ "Open",
+ function(f) {
+ ns.restoreConf(ns.readFile(f)) && nsopt.reload();
+ }
+ );
+ },
+ exportConf: function() {
+ this.save();
+ this.chooseFile(
+ this.buttonToTitle("exportConfButton"),
+ "Save",
+ function(f) {
+ ns.writeFile(f, ns.serializeConf(true));
+ }
+ );
+ },
+
+ reset: function() {
+
+ if(!ns.prompter.confirm(window,
+ ns.getString("reset.title"),
+ ns.getString("reset.warning"))
+ ) return;
+
+ ns.resetDefaults();
+ this.reload();
+ },
+
+ reload: function() {
+ this.utils.persistTabSelections();
+ var op = top.opener;
+ if(op && op.noscriptUtil) {
+ op.setTimeout(function() {
+ op.noscriptUtil.openOptionsDialog();
+ }, 10);
+ }
+ window.close();
+ },
+
+ save: function() {
+ this.utils.visitCheckboxes(
+ function(prefName, inverse, checkbox, mozilla) {
+ if(checkbox.getAttribute("collapsed")!="true") {
+ const checked = checkbox.getAttribute("checked") == "true";
+ const requestedVal = inverse ? !checked : checked;
+
+ if(mozilla) {
+ try {
+ ns.prefService.setBoolPref(prefName, requestedVal);
+ } catch(ex) {}
+ return;
+ }
+
+ const prevVal = ns.getPref(prefName);
+ if(requestedVal != prevVal) {
+ ns.setPref(prefName, requestedVal);
+ }
+ }
+ }
+ );
+
+
+ this.utils.visitTextboxes(function(prefName, box) {
+ if (box.value != ns.getPref(prefName)) {
+ ns.setPref(prefName, box.value);
+ }
+ });
+
+ ["clearClick"].forEach(function(c) {
+ var pref = 0;
+ Array.forEach($(c + "Opts").getElementsByTagName("checkbox"), function(cbx) {
+ if (cbx.checked) pref = pref | parseInt(cbx.getAttribute("value"));
+ });
+ ns.setPref(c, pref);
+ });
+
+
+ ns.setPref("notify.hideDelay", parseInt($("notifyDelay").value) ||
+ ns.getPref("notify.hideDelay", 5));
+
+ ns.setPref("sound.block", this.soundChooser.getSample());
+
+ this.autoAllowGroup.persist();
+
+ if (!(ns.getPref("hoverUI.excludeToggling") && $("opt-hoverUI").checked)) {
+ this.toggleGroup.persist();
+ }
+
+ ns.setPref("allowHttpsOnly", $("sel-allowHttpsOnly").selectedIndex);
+
+ var exVal = this.xssEx.getValue();
+ if(this.xssEx.validate() || !/\S/.test(exVal))
+ ns.setPref("filterXExceptions", exVal);
+
+ if (this.tempRevoked) {
+ ns.eraseTemp();
+ }
+
+ var global = this.jsglobal.getAttribute("checked") == "true";
+ var untrustedSites = this.untrustedSites;
+ var trustedSites = this.trustedSites;
+ var tempSites = this.tempSites;
+ var gTempSites = this.gTempSites;
+
+ ns.safeCapsOp(function(ns) {
+ if(ns.untrustedSites.sitesString != untrustedSites.sitesString
+ || ns.jsPolicySites.sitesString != trustedSites.sitesString
+ || ns.tempSites.sitesString != tempSites.sitesString
+ || ns.gTempSites.sitesString != gTempSites.sitesString) {
+ ns.untrustedSites.sitesString = untrustedSites.sitesString;
+ ns.persistUntrusted();
+ ns.tempSites.sitesString = tempSites.sitesString
+ ns.gTempSites.sitesString = gTempSites.sitesString
+ ns.setJSEnabled(trustedSites.sitesList, true, true);
+ }
+ ns.jsEnabled = global;
+ });
+ return true;
+ },
+
+ urlListChanged: function(dontUpdate) {
+ const selectedItems = noscriptTreeCc.getSelectedItems(this.urlListDisplay, this.whitelistURLs);
+ var removeDisabled = true;
+ for(var j = selectedItems.length; j-- > 0;) {
+ if(!selectedItems[j].mandatory) {
+ removeDisabled = false;
+ break;
+ }
+ }
+ this.removeButton.setAttribute("disabled", removeDisabled);
+ $("revokeButton")
+ .setAttribute("disabled", this.tempRevoked ||
+ !(this.tempSites.sitesString || this.gTempSites.sitesString || ns.objectWhitelistLen));
+ if (!dontUpdate) nsWhitelistTreeView.updateTree();
+ this.urlChanged();
+ },
+
+ openInfo: function(ev) {
+ if (ev.button === 1) {
+ setTimeout(function() {
+ const selectedItems = noscriptTreeCc.getSelectedItems(nsopt.urlListDisplay, nsopt.whitelistURLs);
+ const domains = [];
+ for (let j = selectedItems.length; j-- > 0;) {
+ let site = selectedItems[j].value;
+ let d = site.indexOf(":/") > 0 ? ns.getDomain(site) : site;
+ if (d && domains.indexOf(d) === -1) domains.push(d);
+ }
+ domains.forEach(noscriptUtil.openInfo, noscriptUtil);
+ }, 0); // delayed to let middle-click autoselect the underlying item
+ }
+ },
+
+ copyUrlListSel: function() {
+ noscriptTreeCc.doCopy(this.urlListDisplay, "", " ");
+ },
+
+ urlChanged: function() {
+ var url = this.urlText.value;
+ if(url.match(/\s/)) url = this.urlText.value = url.replace(/\s/g,'');
+ var addEnabled = url.length > 0 && (url = ns.getSite(url)) ;
+ if(addEnabled) {
+ var match = url.match(this.dom2);
+ if(match) url = match[1];
+ url = this.trustedSites.matches(url);
+ if(!(addEnabled = !url)) {
+ this.ensureVisible(url);
+ }
+ }
+ this.addButton.setAttribute("disabled", !addEnabled);
+ },
+
+ notifyHideDelay: {
+ onInput: function(txt) {
+ if(/\D/.test(txt.value)) txt.value = txt.value.replace(/\D/, "");
+ },
+ onChange: function(txt) {
+ txt.value = parseInt(txt.value) || ns.getPref("notify.hideDelay", 5);
+ }
+ },
+
+ ensureVisible: function(site) {
+ for(var j = nsWhitelistTreeView.rowCount; j-- > 0;) {
+ if(nsWhitelistTreeView.getCellText(j) == site) {
+ this.urlListDisplay.boxObject.ensureRowIsVisible(j);
+ }
+ }
+ },
+
+ populateUrlList: function() {
+ const policy = this.trustedSites;
+ const sites = this.trustedSites.sitesList;
+ this.whitelistURLs = [];
+ const dom2 = this.dom2;
+ var site, item;
+ var match, k, len;
+ var tempSites = this.gTempSites.clone();
+ tempSites.add(this.tempSites.sitesList);
+ var tempMap = this.tempSites.sitesMap;
+ for(let j = 0, len = sites.length; j < len; j++) {
+ site = sites[j];
+ // skip protocol + 2nd level domain URLs
+ if((match = site.match(dom2)) && policy.matches(item = match[1]))
+ continue;
+
+ item = {value:site};
+ if(ns.isMandatory(site)) {
+ item.mandatory = true;
+ }
+ item.temp = site in tempMap;
+ this.whitelistURLs.push(item);
+ }
+ this.urlListDeselectAll();
+ this.urlListChanged();
+ },
+
+ allow: function() {
+ const site = ns.getSite(this.urlText.value);
+ this.trustedSites.add(site);
+ this.tempSites.remove(site, true, true); // see noscriptService#eraseTemp()
+ this.gTempSites.remove(site, true, true);
+
+ this.untrustedSites.remove(site, false, !ns.mustCascadeTrust(site, false));
+ this.populateUrlList();
+ this.ensureVisible(site);
+ this.addButton.setAttribute("disabled", "true");
+ },
+
+ remove: function() {
+ const ul = this.urlListDisplay;
+ const selectedItems = noscriptTreeCc.getSelectedItems(ul, this.whitelistURLs);
+ var visIdx = ul.boxObject.getFirstVisibleRow();
+ var lastIdx = visIdx + ul.boxObject.getPageLength();
+
+
+
+
+ var removed = [];
+ for(var j = selectedItems.length; j-- > 0;) {
+ if(!ns.isMandatory(site = selectedItems[j].value)) {
+ removed.push(site);
+ }
+ }
+ if (!removed.length) return;
+
+ this.trustedSites.remove(removed, true); // keepUp
+ this.tempSites.remove(removed, true, true); // see noscriptService#eraseTemp()
+ this.gTempSites.remove(removed, true, true);
+
+ this.populateUrlList();
+
+ },
+
+ urlListDeselectAll: function() {
+ this.urlListDisplay.view.selection.clearSelection();
+ },
+
+ tempRevoked: false,
+ revokeTemp: function() {
+ this.trustedSites.remove(this.tempSites.sitesList, true, true);
+ this.trustedSites.remove(this.gTempSites.sitesList, true, true);
+ this.untrustedSites.add(this.gTempSites.sitesList);
+ this.trustedSites.add(ns.mandatorySites.sitesList);
+ this.tempSites.sitesString = "";
+ this.gTempSites.sitesString = "";
+ this.tempRevoked = true;
+ this.populateUrlList();
+ },
+
+ _soundChooser: null,
+ get soundChooser() {
+ return this._soundChooser ||
+ (this._soundChooser =
+ new SoundChooser(
+ "sampleURL",
+ this.buttonToTitle("sampleChooseButton"),
+ ns,
+ "chrome://noscript/skin/block.wav"
+ ));
+ },
+
+
+ chooseFile: function(title, mode, callback) {
+ const IFP = Ci.nsIFilePicker;
+ const fp = Cc["@mozilla.org/filepicker;1"].createInstance(IFP);
+
+ fp.init(window, title, IFP["mode" + mode]);
+
+ try {
+ fp.displayDirectory = ns.prefs.getComplexValue("exportDir", Ci.nsILocalFile);
+ } catch (e) {
+ fp.displayDirectory = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIDirectoryServiceProvider)
+ .getFile("Home", {});
+ }
+ fp.defaultExtension = "txt";
+ let done = ret => {
+ if(ret == IFP.returnOK ||
+ ret == IFP.returnReplace) {
+ callback.call(nsopt, fp.file);
+ }
+ };
+ if (fp.show) done(fp.show());
+ else fp.open({done});
+ },
+
+
+ importExport: function(op) {
+ this.chooseFile(
+ this.buttonToTitle(op + "Button"),
+ op == "import" ? "Open" : "Save",
+ this[op + "List"]
+ );
+ },
+
+ importList: function(file) {
+ var all = ns.readFile(file).replace(/\s+/g, "\n");
+ if (/[,\{]/.test(all)) {
+ ns.log("Wrong format");
+ return null;
+ }
+ let untrustedPos = all.indexOf("[UNTRUSTED]");
+ if(untrustedPos < 0) {
+ this.trustedSites.sitesString += "\n" + all;
+ } else {
+ this.trustedSites.sitesString += "\n" + all.substring(0, untrustedPos);
+ this.untrustedSites.sitesString += all.substring(all.indexOf("\n", untrustedPos + 2));
+ }
+ this.untrustedSites.remove(this.trustedSites.sitesList, false, true);
+ this.populateUrlList();
+ return null;
+ },
+
+ exportList: function(file) {
+ var list = ns.getPermanentSites(this.trustedSites, this.tempSites);
+ list.remove(ns.mandatorySites.sitesList, true, true);
+ ns.writeFile(file, list.sitesList.join("\n") +
+ "\n[UNTRUSTED]\n" +
+ this.untrustedSites.sitesList.join("\n")
+ );
+ return null;
+ },
+
+ buttonToTitle: function(btid) {
+ return "NoScript - " + $(btid).getAttribute("label");
+ },
+
+ toggleHoverUI: function(cbx) {
+ if (ns.getPref("hoverUI.excludeToggling")) {
+ let cbx = $("cbx-toolbarToggle");
+ if ($("opt-hoverUI").checked) {
+ if (!cbx.disabled) {
+ this._savedToolbarToggleStatus = cbx.checked;
+ cbx.disabled = true;
+ cbx.checked = false;
+ this.toggleGroup.changed();
+ }
+ } else {
+ if (cbx.disabled) {
+ cbx.disabled = false;
+ cbx.checked = this._savedToolbarToggleStatus;
+ }
+ }
+ }
+ }
+
+}
+
+var ABE = ns.ABE;
+
+var abeOpts = {
+ selectedRS: null,
+ _map: {__proto__: null},
+ errors: false,
+ QueryInterface: ns.wan.QueryInterface, // dirty hack, we share the same observer ifaces
+
+ init: function() {
+ this.list = $("abeRulesets-list");
+ this.populate();
+
+ this.updateWAN(ns.wan.ip);
+ const OS = ns.os;
+ OS.addObserver(this, ns.wan.IP_CHANGE_TOPIC, true);
+ OS.addObserver(this, ABE.RULES_CHANGED_TOPIC, true);
+ },
+
+ dispose: function() {
+ const OS = ns.os;
+ OS.removeObserver(this, ns.wan.IP_CHANGE_TOPIC);
+ OS.removeObserver(this, ABE.RULES_CHANGED_TOPIC);
+ },
+
+ observe: function(subject, topic, data) {
+ if (topic === ns.wan.IP_CHANGE_TOPIC) this.updateWAN(data);
+ else if (topic === ABE.RULES_CHANGED_TOPIC) {
+ this.populate();
+ this.errors = false;
+ }
+ },
+
+ updateWAN: function(ip) {
+ $("opt-ABE.wanIpAsLocal").label = ns.getString("ABE.wanIpAsLocal", [ip || "???"]);
+ },
+
+ reset: function() {
+ ABE.resetDefaults();
+ },
+ input: function() {
+ abeOpts.dirty = abeOpts.list.selectedItem;
+ },
+ changed: function(i) {
+ let current = i || this.list.selectedItem;
+
+ if (current && this.dirty) {
+
+ let name = current.value;
+ let source = $("abeRuleset-text-container").selectedPanel.value;
+ let ruleset = ABE.createRuleset(name, source);
+ if (ruleset.errors && this.dirty) {
+ this.dirty = null;
+ let p = ns.prompter;
+ if (p.confirmEx(window,
+ ns.getString("ABE.syntaxError"),
+ ruleset.errors.join("\n"),
+ p.BUTTON_TITLE_SAVE * p.BUTTON_POS_0 +
+ p.BUTTON_TITLE_DONT_SAVE * p.BUTTON_POS_1 +
+ p.BUTTON_POS_1_DEFAULT,
+ null, null, null, null, {}) === 1
+ ) {
+ this.sync();
+ return;
+ }
+ }
+ this.dirty = null;
+ ABE.storeRuleset(name, source);
+ }
+ },
+
+ _populating: false,
+ populate: function() {
+ if (this._populating) return;
+ this._populating = true;
+ this.errors = false;
+ this.dirty = null;
+ try {
+ const map = {__proto__: null};
+ var l = this.list;
+ for(var j = l.getRowCount(); j-- > 0; l.removeItemAt(j)) {
+ try {
+ let rc = $("abeRuleset-text-container");
+ rc.removeChild(rc.lastChild);
+ }
+ catch (e) { /* no textboxes present to remove, ignore */ }
+ }
+ var rulesets = ABE.rulesets;
+ var selItem = null;
+ if (rulesets) {
+ var sel = this.selectedRS && this.selectedRS.name || "USER";
+ this.selectedRS = null;
+ var i, name;
+ for (var rs of rulesets) {
+ name = rs.name;
+ map[name] = rs;
+ i = l.appendItem(name, name);
+ if (rs.disabled) i.setAttribute("disabled", "true");
+ if (sel == name) selItem = i;
+ if (rs.errors) {
+ i.className = "noscript-error";
+ this.errors = rs.errors;
+ }
+ let textbox = document.createElement("textbox");
+ let textboxAttributes = {
+ "flex":"5",
+ "multiline":"true",
+ "wrap":"off",
+ "onchange":"abeOpts.changed()",
+ "oninput":"abeOpts.input(this)",
+ "value":rs.source
+ };
+ for (let a in textboxAttributes) { textbox.setAttribute(a, textboxAttributes[a]); }
+ $("abeRuleset-text-container").appendChild(textbox);
+ }
+ }
+ this._map = map;
+ l.selectedItem = selItem;
+ this.sync();
+ } finally {
+ this._populating = false;
+ }
+ },
+
+ selected: function(i) {
+ if (this.dirty) {
+ let selIndex = this.list.selectedIndex;
+ this.changed(this.dirty);
+ this.list.selectedIndex = selIndex;
+ }
+ if (!this._populating) this.sync();
+ this.dirty = null;
+ },
+
+ select: function(rs) {
+ var name = rs && rs.name || rs;
+ if (!name) return;
+ var l = this.list;
+ if (l.selectedItem && l.selectedItem.value == name) return;
+
+ for(var j = l.getRowCount(), i; j-- > 0;) {
+ i = l.getItemAtIndex(j);
+ if (i.value == name) {
+ l.selectedItem = i;
+ break;
+ }
+ }
+ },
+
+ sync: function() {
+ var selItem = this.list.selectedItem;
+
+ var rs = null;
+ if (selItem) {
+ this.selectedRS = rs = this._map[selItem.value];
+ } else {
+ this.selectedRS = null;
+ }
+
+ $("abeEnable-button").disabled = ! ($("abeDisable-button").disabled = !rs || rs.disabled);
+ $("abeRefresh-button").disabled = this.list.getRowCount() == 0;
+ $("abeRuleset-text-container").setAttribute("selectedIndex", this.list.selectedIndex);
+
+ var text = $("abeRuleset-text-container").selectedPanel;
+ text.className = selItem && selItem.className || '';
+ text.disabled = !selItem || selItem.disabled;
+ text.value = rs && rs.source;
+
+ text = $("abeRuleset-errors");
+ if (rs && rs.errors) {
+ this.ShowHideABEError(false);
+ text.value = rs.errors.join("\n");
+ }
+ else {
+ this.ShowHideABEError(true);
+ text.value = "";
+ }
+ },
+
+ refresh: function() {
+ ABE.refresh();
+ },
+
+ ShowHideABEError: function(hidden) {
+ for (let n of document.getElementsByClassName("abe-error-element")) {
+ n.hidden = hidden;
+ }
+ },
+
+ toggle: function(enabled) {
+ var selItem = this.list.selectedItem;
+ var rs = this.selectedRS;
+ if (!(rs && selItem && rs.name == selItem.value)) return;
+ if ((rs.disabled = !enabled)) {
+ selItem.setAttribute("disabled", "true");
+ } else {
+ selItem.removeAttribute("disabled");
+ }
+ ns.setPref("ABE.disabledRulesetNames", ABE.disabledRulesetNames);
+ this.sync();
+ }
+
+}
+
+var nsWhitelistTreeView = {
+ rowCount: nsopt.whitelistURLs.length,
+ getCellText: function(r, c) { return nsopt.whitelistURLs[r].value; },
+ setTree: function(treebox){ this.treebox = treebox; },
+ isContainer: function(row){ return false; },
+ isSeparator: function(row){ return false; },
+ isSorted: function(){ return true; },
+ getLevel: function(row){ return 0; },
+ getImageSrc: function(row,col){ return null; },
+ getRowProperties: function(row,props) {
+ // ??? need to set multicol manually for some reason
+ if (props) {
+ let aserv=Cc["@mozilla.org/atom-service;1"].getService(Ci.nsIAtomService);
+ props.AppendElement(aserv.getAtom("multicol"));
+ }
+ else { return "multicol" }
+ },
+ getCellProperties: function(row,col,props) {
+ var psl = [];
+ if (nsopt.whitelistURLs[row].temp) psl.push("temp");
+ if (nsopt.whitelistURLs[row].mandatory) psl.push("mandatory");
+ if (psl.length == 0) return;
+ if (props) {
+ let aserv=Cc["@mozilla.org/atom-service;1"].getService(Ci.nsIAtomService);
+ for (let s of psl) props.AppendElement(aserv.getAtom(s));
+ }
+ else { return psl.join(" ") }
+ },
+ getColumnProperties: function(colid,col,props){},
+ cycleHeader: function(col){},
+
+ // Custom properties and methods
+ updateTree: function() {
+ var r = nsopt.urlListDisplay.boxObject.getFirstVisibleRow();
+ nsWhitelistTreeView.rowCount = nsopt.whitelistURLs.length;
+ $("urlListDisplay").view = nsWhitelistTreeView;
+ nsopt.urlListDisplay.boxObject.scrollToRow(r);
+ },
+};
+
diff --git a/extensions/noscript/chrome/content/noscript/noscriptOptions.xul b/extensions/noscript/chrome/content/noscript/noscriptOptions.xul
new file mode 100644
index 0000000..3a53470
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/noscriptOptions.xul
@@ -0,0 +1,469 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://noscript/skin/browser.css" type="text/css"?>
+<?xml-stylesheet href="chrome://noscript/skin/options.css" type="text/css"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://noscript/locale/noscript.dtd">
+<dialog id="noscriptOptions"
+ onload="nsopt.init()"
+ onunload="nsopt.dispose()"
+ ondialogaccept="return nsopt.save()"
+
+ title="&noscriptOptionsLong;"
+ buttons="extra2,accept,cancel"
+
+ buttonlabelextra2="&noscriptReset;"
+ buttonaccesskeyextra2="&noscriptReset.accesskey;"
+ ondialogextra2="nsopt.reset()"
+
+ ondialoghelp="noscriptUtil.openHelp('options')"
+
+ spacerflex="1"
+ persist="screenX screenY"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/x-javascript" src="noscript.js" />
+ <script type="application/x-javascript" src="iaUI.js" />
+ <script type="application/x-javascript" src="tree-copy.js" />
+ <script type="application/x-javascript" src="noscriptOptions.js" />
+
+ <vbox style="width: &noscriptOptionsWidth;">
+ <tabbox id="nsopt-tabsMain">
+ <tabs>
+
+ <tab label="&noscriptGeneral;" id="nsopt-tabGeneral"/>
+ <tab label="&noscriptWhitelist;" id="nsopt-tabWhitelist"/>
+ <tab label="&noscriptEmbeddings;" id="nsopt-tabEmbeddings"/>
+ <tab label="&noscriptAppearance;" id="nsopt-tabAppearance"/>
+ <tab label="&noscriptNotifications;" id="nsopt-tabNotifications"/>
+ <tab label="&noscriptAdvanced;" id="nsopt-tabAdvanced"/>
+
+ </tabs>
+ <tabpanels>
+
+ <tabpanel><!-- General -->
+
+ <vbox flex="1">
+
+ <groupbox class="ia-indent">
+ <caption><checkbox id="cbx-autoAllow" label="&noscriptAutoAllowTopLevel;"/></caption>
+ <radiogroup id="sel-autoAllow">
+ <radio label="&noscriptFullAddr;" value="1" selected="true"/>
+ <radio label="&noscriptFullDom;" value="2"/>
+ <radio label="&noscriptBaseDom;" value="3"/>
+ </radiogroup>
+ </groupbox>
+ <checkbox id="opt-hoverUI" label="&noscript.hoverUI;" oncommand="nsopt.toggleHoverUI()" />
+ <groupbox id="toolbarToggleGroup" class="ia-indent">
+ <caption orient="vertical">
+ <checkbox id="cbx-toolbarToggle" label="&noscriptToolbarToggle;"/>
+ <label control="sel-toolbarToggle" id="toolbarToggle-shortcut" class="ia-indent" hidden="true"/>
+ </caption>
+
+ <radiogroup id="sel-toolbarToggle">
+ <radio label="&noscriptFullAddr;" value="1"/>
+ <radio label="&noscriptFullDom;" value="2"/>
+ <radio label="&noscriptBaseDom;" value="3" selected="true"/>
+ </radiogroup>
+ </groupbox>
+
+
+ <checkbox id="opt-autoReload" label="&noscriptAutoReload;" />
+ <vbox class="ia-indent">
+ <checkbox id="invopt-autoReload.allTabs" label="&noscriptAutoReload.currentTab;" />
+ </vbox>
+ <separator class="thin"/>
+ <checkbox id="opt-allowBookmarks" label="&noscriptAllowViaBookmarks;" />
+
+ <spacer flex="1" />
+ <button id="importConfButton" label="&noscriptImport;" hidden="true" oncommand="nsopt.importConf()" />
+ <button id="exportConfButton" label="&noscriptExport;" hidden="true" oncommand="nsopt.exportConf()" />
+ <button id="donateButton" label="&noscriptDonate;" accesskey="&noscriptDonate.accesskey;" hidden="true" oncommand="nsopt.donate();" />
+ </vbox>
+ </tabpanel><!-- END General -->
+
+ <tabpanel><!-- Whitelist -->
+ <vbox flex="1">
+ <description style="white-space: normal; width: 33em" id="permissionsText">&noscriptPermissionsText;</description>
+ <separator class="thin"/>
+ <label control="urlText" value="&noscriptWebAddress;"/>
+ <hbox align="center">
+ <textbox id="urlText" flex="1" oninput="nsopt.urlChanged()"/>
+ <button disabled="false" id="addButton" label="&noscriptAllow;"
+ accesskey="&noscriptAllow.accesskey;"
+ oncommand="nsopt.allow()"/>
+ </hbox>
+
+ <tree id="urlListDisplay"
+ onselect="nsopt.urlListChanged(true)"
+ onkeyup="if (event.keyCode == event.DOM_VK_DELETE) nsopt.remove();"
+ onkeydown="if(event.ctrlKey || event.metaKey){if (event.keyCode === event.DOM_VK_A) { noscriptTreeCc.selectAll($('urlListDisplay')); }else if (event.keyCode === event.DOM_VK_C){nsopt.copyUrlListSel(); }}return false;"
+ onclick="if(event.button === 1){nsopt.openInfo(event);}else if (event.button === 2){nsopt.copyUrlListSel()}"
+ hidecolumnpicker="true"
+ seltype="multiple"
+ flex="1"
+ multicol="true"
+ >
+ <treecols>
+ <treecol label="foo" flex="1" />
+ </treecols>
+ <treechildren />
+ </tree>
+ <separator class="thin"/>
+ <hbox>
+ <button id="removeButton" disabled="true" label="&noscriptRemoveSelected;" oncommand="nsopt.remove()"/>
+ <button id="revokeButton" disabled="true" label="&noscriptRevokeTemp;" accesskey="&noscriptRevokeTemp.accesskey;" oncommand="nsopt.revokeTemp()"/>
+ <spacer flex="1" />
+ <button id="importButton" label="&noscriptImport;" accesskey="&noscriptImport.accesskey;"
+ oncommand="nsopt.importExport('import')"/>
+ <button id="exportButton" label="&noscriptExport;" accesskey="&noscriptExport.accesskey;"
+ oncommand="nsopt.importExport('export')"/>
+ </hbox>
+ <checkbox id="jsglobal" label="&noscriptGloballyEnabled;" />
+ </vbox>
+ </tabpanel><!-- END Whitelist -->
+
+ <tabpanel><!-- Embeddings -->
+ <vbox flex="1">
+ <label class="header" value="&noscriptAdditionalRestrictions;" />
+ <hbox><description style="white-space: normal">&noscriptReloadWarn;</description></hbox>
+ <separator class="thin" />
+ <hbox class="flexible-cbx">
+ <vbox>
+ <checkbox id="opt-forbidJava" label="&noscriptForbidJava;" />
+ <checkbox id="opt-forbidFlash" label="&noscriptForbidFlash;" />
+ <checkbox id="opt-forbidSilverlight" label="&noscriptForbidSilverlight;" />
+ <checkbox id="opt-forbidPlugins" label="&noscriptForbidPlugins;" />
+ </vbox>
+ <vbox flex="1">
+ <checkbox id="opt-forbidMedia" label="&noscriptForbidMedia;" />
+ <checkbox id="opt-forbidIFrames" label="&noscriptForbidIFrames;" />
+ <checkbox id="opt-forbidFrames" label="&noscriptForbidFrames;" />
+ <checkbox id="opt-forbidFonts" label="&noscriptForbidFonts;" />
+ </vbox>
+ </hbox>
+ <separator class="thin" />
+ <checkbox id="opt-contentBlocker" label="&noscriptContentBlocker;" class="header" />
+ <checkbox id="opt-alwaysBlockUntrustedContent" label="&noscriptAlwaysBlockUntrustedContent;" />
+
+ <separator class="thin" />
+ <checkbox id="opt-forbidWebGL" label="&noscriptForbidWebGL;" />
+ <separator class="thin" />
+ <checkbox id="opt-showPlaceholder" label="&noscriptShowPlaceholder;" />
+ <checkbox id="invopt-showUntrustedPlaceholder" label="&noscriptNoUntrustedPlaceholder;" />
+ <checkbox id="opt-confirmUnblock" label="&noscriptConfirmUnblock;" />
+ <checkbox id="opt-collapseObject" label="&noscriptCollapseBlockedObjects;" />
+
+ <hbox>
+
+ <spacer flex="1" />
+ </hbox>
+ </vbox>
+ </tabpanel>
+
+ <tabpanel><!-- Appearance -->
+ <vbox flex="1">
+
+ <label class="header" value="&noscriptShow;"/>
+
+ <checkbox id="opt-statusIcon" label="&noscriptStatusIcon;" />
+ <checkbox id="opt-statusLabel" label="&noscriptStatusLabel;" />
+ <checkbox id="opt-ctxMenu" label="&noscriptCtxMenu;" />
+
+ <separator />
+ <hbox>
+ <vbox flex="1">
+ <checkbox id="opt-showPermanent" label="Allow [...]" />
+ <checkbox id="opt-showTemp" label="&noscriptTempCmd;" />
+ <checkbox id="opt-showDistrust" label="Mark [...] as untrusted" />
+ </vbox>
+ <vbox flex="1">
+ <checkbox id="opt-showBaseDomain" label="&noscriptBaseDom;" />
+ <checkbox id="opt-showDomain" label="&noscriptFullDom;" />
+ <checkbox id="opt-showAddress" label="&noscriptFullAddr;" />
+ </vbox>
+ </hbox>
+ <separator />
+ <hbox>
+ <vbox flex="1">
+ <checkbox id="opt-showGlobal" label="Allow Globally" />
+ <checkbox id="opt-showAbout" label="&noscriptAbout;" />
+ <checkbox id="opt-showUntrusted" label="&noscriptUntrusted;" />
+ <checkbox id="opt-showBlockedObjects" label="&noscriptBlockedObjects;" />
+ <checkbox id="opt-showRecentlyBlocked" label="&noscriptRecentBlocked;" />
+ </vbox>
+ <vbox flex="1">
+ <checkbox id="opt-showAllowPage" label="&noscriptAllowPage;" />
+ <checkbox id="opt-showTempAllowPage" label="&noscriptTempAllowPage;" />
+ <checkbox id="opt-showTempToPerm" label="&noscriptTempToPerm;" />
+ <checkbox id="opt-showRevokeTemp" label="&noscriptRevokeTemp;" />
+ <checkbox id="opt-showVolatilePrivatePermissionsToggle" label="&noscriptPermanentInPrivate;" />
+ </vbox>
+ </hbox>
+
+ </vbox>
+ </tabpanel><!-- END Appearance -->
+
+ <tabpanel><!-- Notifications -->
+ <vbox flex="1">
+ <vbox id="fx-notifications">
+ <vbox id="notifyOpts">
+ <checkbox id="opt-notify" label="&noscriptNotify;" />
+ <vbox class="ia-indent">
+ <checkbox id="opt-notify.bottom" label="&noscriptNotify.bottom;" />
+ <hbox align="baseline">
+ <checkbox id="opt-notify.hide" label="Hide after" />
+ <textbox id="notifyDelay" type="number" min="1" max="60"
+ oninput="nsopt.notifyHideDelay.onInput(this)"
+ onchange="nsopt.notifyHideDelay.onChange(this)"
+ maxlength="2" size="2" />
+ <label control="notifyDelay" id="notifyDelayLabel" value="seconds" />
+ <spacer flex="1"/>
+ </hbox>
+ </vbox>
+ </vbox>
+ <separator class="thin" />
+ <hbox align="center">
+ <checkbox id="opt-xss.notify" label="&noscriptXss;" /><!-- TODO: accesskey -->
+ <label class="text-link" style="font-weight: bold" value="?"
+ onclick="noscriptUtil.openFaq('xss')"
+ tooltiptext="&noscriptXssFaq;" />
+ </hbox>
+
+
+ <checkbox id="opt-forbidMetaRefresh.notify" label="&noscriptNotifyMeta;" accesskey="&noscriptNotifyMeta.accesskey;"/>
+
+ <checkbox id="opt-ABE.notify" label="&ABE;"/><!-- TODO: accesskey -->
+ </vbox>
+
+ <checkbox id="opt-clearClick.prompt" label="&noscriptClearClickTitle;"/>
+
+ <groupbox class="ia-indent">
+ <caption><checkbox id="opt-sound" label="&noscriptSound;" /></caption>
+
+ <hbox>
+ <textbox id="sampleURL" readonly="true" flex="1" />
+ <button id="sampleChooseButton" label="&noscriptSound.choose;"
+ accesskey="&noscriptSound.choose.accesskey;"
+ oncommand="nsopt.soundChooser.choose()" />
+ </hbox>
+ <hbox align="right">
+ <spacer flex="1" />
+ <button label="&noscriptSound.play;" accesskey="&noscriptSound.play.accesskey;"
+ oncommand="nsopt.soundChooser.play()" />
+ <button label="&noscriptSound.reset;" accesskey="&noscriptSound.reset.accesskey;"
+ oncommand="nsopt.soundChooser.setSample(null)" />
+ </hbox>
+
+ </groupbox>
+
+ <checkbox id="opt-firstRunRedirection" label="&noscriptShowReleaseNotes;"/>
+ </vbox>
+ </tabpanel><!-- END Notifications -->
+
+ <tabpanel><!-- Advanced -->
+ <vbox flex="1">
+ <hbox><description style="white-space: normal">&noscriptReloadWarn;</description></hbox>
+ <tabbox id="nsopt-tabsAdvanced" flex="1">
+ <tabs>
+ <tab class="noscript-no" label=" &noscriptUntrusted; " id="nsopt-tabUntrusted" tooltiptext="&noscriptAdditionalRestrictions;"/>
+ <tab class="noscript-yes" label=" &noscriptTrusted; " id="nsopt-tabTrusted" tooltiptext="&noscriptAdditionalPermissions;"/>
+ <tab class="noscript-xss" label=" &noscriptXss; " id="nsopt-tabXss"/>
+ <tab class="noscript-https" label=" &noscriptHttps; " id="nsopt-tabHttps"/>
+ <tab class="noscript-abe" label="&ABE;" id="nsopt-tabABE"/>
+ <tab class="noscript-clearclick" label="ClearClick" id="nsopt-tabClearClick"/>
+ </tabs>
+ <tabpanels flex="1">
+ <tabpanel>
+ <vbox flex="1">
+ <label class="header" value="&noscriptAdditionalRestrictions;" />
+
+ <checkbox id="opt-forbidBookmarklets" label="&noscriptForbidBookmarklets;" />
+ <checkbox id="opt-noping" label="&noscriptForbidPing;" />
+ <separator class="thin"/>
+ <checkbox id="opt-nselNever" label="&noscriptNselNever;" />
+ <checkbox id="opt-forbidMetaRefresh" label="&noscriptForbidMetaRefresh;" />
+ <checkbox id="opt-forbidXSLT" label="&noscriptForbidXSLT;" />
+ <separator class="thin"/>
+ <checkbox id="opt-fixLinks" label="&noscriptFixLinks;" />
+
+ <separator class="thin"/>
+ <checkbox id="opt-restrictSubdocScripting" label="&noscriptRestrictSubdocScripting;" />
+
+ <separator />
+ <label class="text-link header"
+ onclick="document.getElementById('nsopt-tabsMain').selectedTab = document.getElementById('nsopt-tabEmbeddings')"
+ value="&noscriptEmbeddings;" />
+ </vbox>
+ </tabpanel><!-- END additional restrictions -->
+
+ <tabpanel><!-- Additional Permissions -->
+ <vbox flex="1">
+ <label class="header" value="&noscriptAdditionalPermissions;" />
+
+ <checkbox id="opt-nselForce" label="&noscriptNselForce;" />
+ <checkbox id="mozopt-browser.send_pings" label="&noscriptAllowPing;" />
+
+ <separator class="thin" />
+ <checkbox id="opt-allowClipboard" label="&noscriptAllowClipboard;" />
+ <checkbox id="opt-allowLocalLinks" label="&noscriptAllowLocalLinks;" />
+
+ <separator class="thin" />
+ <checkbox id="opt-cascadePermissions" label="&noscriptCascadePermissions;" />
+ </vbox>
+ </tabpanel><!-- END Additional Permissions -->
+
+
+ <tabpanel><!-- XSS -->
+ <vbox flex="1">
+ <label class="text-link header"
+ onclick="noscriptUtil.openFaq('xss')" value="&noscriptXssFaq;"
+ accesskey="&noscriptXssFaq.accesskey;"
+ />
+ <checkbox id="opt-filterXGet" label="&noscriptOptFilterXGet;" />
+ <checkbox id="opt-filterXPost" label="&noscriptOptFilterXPost;" />
+ <separator class="thin" />
+ <label control="xssEx-regexp" class="header" value="&noscriptXssExceptions;" />
+ <description control="xssEx-regexp" style="white-space: normal">&noscriptXssExceptions.description;</description>
+ <textbox id="xssEx-regexp" multiline="true" flex="1" />
+ <hbox align="center">
+ <label control="xssEx-sample" value="&noscriptMatchSample;" />
+ <textbox id="xssEx-sample" flex="1" value="https://www.google.com/search?q=test" />
+ </hbox>
+ </vbox>
+ </tabpanel>
+
+ <tabpanel><!-- HTTPS -->
+ <vbox flex="1">
+ <label class="text-link header"
+ accesskey="&noscriptHttpsFaq.accesskey;"
+ onclick="noscriptUtil.openFaq('https')"
+ value="&noscriptHttpsFaq;"/>
+
+ <tabbox id="nsopt-tabsHttps" flex="1">
+ <tabs>
+ <tab label=" &noscriptHttps.behavior; " id="nsopt-tabHttpsBehavior" />
+ <tab label=" &noscriptHttps.cookies; " id="nsopt-tabHttpsCookies"/>
+ <tab label=" &noscriptPermissions; " id="nsopt-tabHttpsPermissions"/>
+
+ </tabs>
+
+ <tabpanels flex="1">
+ <tabpanel>
+ <vbox flex="1">
+
+ <description control="opt-httpsForced" style="white-space: normal">&noscriptHttpsForced;</description>
+ <textbox id="opt-httpsForced" multiline="true" flex="1" />
+ <description control="opt-httpsForcedExceptions" style="white-space: normal">&noscriptHttpsForcedExceptions;</description>
+ <textbox id="opt-httpsForcedExceptions" multiline="true" flex="1" />
+ </vbox>
+ </tabpanel>
+ <tabpanel>
+ <vbox flex="1">
+ <groupbox flex="1">
+ <caption><checkbox id="opt-secureCookies" label="&noscriptSecureCookies;" oncommand="nsopt.utils.syncGroup(this)" /></caption>
+ <description control="opt-secureCookiesForced" style="white-space: normal">&noscriptSecureCookiesForced;</description>
+ <textbox id="opt-secureCookiesForced" multiline="true" flex="1" />
+
+ <description control="opt-secureCookiesExceptions" style="white-space: normal">&noscriptSecureCookiesExceptions;</description>
+ <textbox id="opt-secureCookiesExceptions" multiline="true" flex="1" />
+ </groupbox>
+ </vbox>
+ </tabpanel>
+ <tabpanel>
+ <vbox flex="1">
+ <description control="sel-allowHttpsOnly" style="white-space: normal">&noscriptHttps.description;</description>
+ <menulist id="sel-allowHttpsOnly">
+ <menupopup id="mp-allowHttpsOnly">
+ <menuitem label="&noscriptHttps.never;" value="0" selected="true" />
+ <menuitem label="&noscriptHttps.proxy;" value="1"/>
+ <menuitem label="&noscriptHttps.always;" value="3"/>
+ </menupopup>
+ </menulist>
+ <spacer flex="1" />
+ <checkbox id="opt-globalHttpsWhitelist" label="&noscriptGlobalHttpsWhitelist;" />
+ <spacer flex="1" />
+ </vbox>
+ </tabpanel>
+ </tabpanels>
+ </tabbox>
+ </vbox>
+ </tabpanel>
+ <tabpanel><!-- ABE -->
+ <vbox flex="1">
+ <hbox>
+ <vbox>
+ <checkbox id="opt-ABE.enabled" label="&ABE.enabled.label;" />
+ <spacer flex="1" />
+ <checkbox id="opt-ABE.siteEnabled" label="&ABE.siteEnabled.label;" />
+ </vbox>
+ <vbox pack="end">
+ <spacer flex="1" />
+ <label class="text-link header"
+ accesskey="?"
+ onclick="noscriptUtil.openHelp('ABE')"
+ value="?"/>
+ <spacer flex="1" />
+ <checkbox id="opt-ABE.wanIpAsLocal" label="" />
+ </vbox>
+ </hbox>
+
+ <vbox >
+ <label control="abeRulesets-list" value="&ABE.rulesets.label;" />
+ <hbox flex="1">
+ <listbox id="abeRulesets-list"
+ onselect="abeOpts.selected(this)"
+ ondblclick="abeOpts.edit(this)"
+ flex="1"
+ width="50"
+ persist="width"
+ style="margin-right: 0"
+ >
+ <listitem label="SYSTEM" />
+ <listitem label="USER" />
+ </listbox>
+ <splitter style="background: transparent; margin: 0; border-width: 0" />
+ <vbox flex="5">
+ <deck id="abeRuleset-text-container" flex="5" style="margin-left: 0" />
+ <splitter style="background: transparent; margin: 0px; border-width: 0px" class="abe-error-element" />
+ <textbox id="abeRuleset-errors" class="noscript-error abe-error-element" style="width: 100%"
+ readonly="true" multiline="true" rows="2" hidden="true" value="" />
+ </vbox>
+ </hbox>
+
+ </vbox>
+ <hbox align="center">
+ <button id="abeRefresh-button" label="&ABE.refresh.label;" accesskey="&ABE.refresh.accesskey;" oncommand="abeOpts.refresh()" />
+ <spacer flex="2"/>
+ <button id="abeEnable-button" label="&ABE.enable.label;" accesskey="&ABE.enable.accesskey;" oncommand="abeOpts.toggle(true)" />
+ <button id="abeDisable-button" label="&ABE.disable.label;" accesskey="&ABE.disable.accesskey;" oncommand="abeOpts.toggle(false)" />
+ <spacer flex="3"/>
+ <button id="abeReset-button" label="&noscriptReset;" oncommand="abeOpts.reset()" />
+ </hbox>
+ </vbox>
+ </tabpanel><!-- End ABE -->
+
+ <tabpanel><!-- ClearClick -->
+ <vbox flex="1">
+
+ <label class="header" control="cc1" value="&noscriptClearClickOpt;" />
+ <vbox id="clearClickOpts">
+ <checkbox id="cc1" value="1" label="&noscriptUntrustedPagesAdj;"/>
+ <checkbox id="cc2" value="2" label="&noscriptTrustedPagesAdj;"/>
+ </vbox>
+ </vbox>
+
+ </tabpanel><!-- End ClearClick -->
+
+ </tabpanels>
+
+
+ </tabbox>
+ </vbox>
+ </tabpanel>
+
+ </tabpanels>
+ </tabbox>
+ </vbox>
+</dialog>
+
diff --git a/extensions/noscript/chrome/content/noscript/noscriptOverlay-noStatusBar.xul b/extensions/noscript/chrome/content/noscript/noscriptOverlay-noStatusBar.xul
new file mode 100644
index 0000000..a2b7df6
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/noscriptOverlay-noStatusBar.xul
@@ -0,0 +1,318 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay SYSTEM "chrome://noscript/locale/noscript.dtd">
+
+<?xml-stylesheet href="chrome://noscript/skin/browser.css" type="text/css"?>
+
+<overlay id="noscriptOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/x-javascript" src="noscript.js" />
+ <script type="application/x-javascript" src="noscriptOverlay.js"/>
+
+ <toolbarpalette id="BrowserToolbarPalette">
+ <toolbarbutton id="noscript-tbb"
+ buttonstyle="pictures"
+ class="toolbarbutton-1 noscript-no"
+ label="NoScript"
+ type="menu-button"
+ removable="true"
+ oncommand="noscriptOverlay.onUICommand(event)"
+ oncontextmenu="noscriptOverlay.onContextMenu(event);"
+ onmouseover="noscriptOverlay.onUIOver(event)"
+ onmousemove="noscriptOverlay.onUIMove(event)"
+ onmouseout="noscriptOverlay.onUIOut(event)"
+ onmouseup="noscriptOverlay.onUIUp(event)"
+ context="noscript-tbb-popup"
+ />
+
+ <toolbarbutton id="noscript-tbb-temp-page"
+ tooltiptext="&noscriptTempAllowPage;"
+ buttonstyle="pictures"
+ class="toolbarbutton-1 noscript-temp noscript-allow"
+ label="&noscriptTempAllowPage;"
+ oncommand="noscriptOverlay.allowPage()"
+ />
+ <toolbarbutton id="noscript-tbb-revoke-temp"
+ tooltiptext="&noscriptRevokeTemp;"
+ buttonstyle="pictures"
+ class="toolbarbutton-1 noscript-revoke-temp"
+ label="&noscriptRevokeTemp;"
+ oncommand="noscriptOverlay.revokeTemp()"
+ />
+ </toolbarpalette>
+
+ <popup id="contentAreaContextMenu">
+ <menu id="noscript-context-menu" class="menu-iconic" label="NoScript" >
+ <menupopup id="noscript-context-popup" onpopupshowing="noscriptOverlay.onMenuShowing(event, true)">
+ <menuseparator class="noscript-sep-insert" hidden="true" />
+ <menuseparator class="noscript-sep-stop-untrusted"/>
+ <!-- dynamically inserted #noscript-menu-untrusted -->
+
+ <menuseparator class="noscript-sep-global" />
+ <menuitem class="menuitem-iconic" />
+
+ <menuseparator />
+ <menuitem id="noscript-options-ctx-menuitem"
+ label="&noscriptOptions;"
+ accesskey="&noscriptOptions.accesskey;"
+ oncommand="noscriptUtil.openOptionsDialog()"
+ tooltiptext="&noscriptOptionsLong;"
+ class="menuitem-iconic noscript-options"
+ />
+ <menuitem id="noscript-about-ctx-menuitem"
+ label="&noscriptAbout;"
+ tooltiptext="&noscriptAbout;"
+ oncommand="noscriptUtil.openAboutDialog()"
+ class="menuitem-iconic noscript-about"
+ />
+ </menupopup>
+ </menu>
+ </popup>
+
+ <window id="main-window">
+ <popupset id="mainPopupSet"></popupset><!-- SeaMonkey compatibility -->
+ </window>
+
+
+
+ <popupset id="mainPopupSet">
+ <menupopup id="noscript-notify-popup" onpopupshowing="noscriptOverlay.onMenuShowing(event, true)">
+ <menuseparator />
+ <menuitem
+ id="noscript-options-menuitem"
+ label="&noscriptOptions;"
+ accesskey="&noscriptOptions.accesskey;"
+ oncommand="noscriptUtil.openOptionsDialog()"
+ tooltiptext="&noscriptOptionsLong;"
+ class="menuitem-iconic noscript-options"
+ />
+ <menuitem id="noscript-mi-opt-notify"
+ label="&noscriptNotify;"
+ oncommand="noscriptOverlay.toggleMenuOpt(this)"
+ type="checkbox" autocheck="true"
+ />
+ <menuitem id="noscript-mi-opt-notify.bottom"
+ label="&noscriptNotify.bottom;"
+ oncommand="noscriptOverlay.toggleMenuOpt(this)"
+ type="checkbox" autocheck="true"
+ />
+ <menuitem id="noscript-mi-opt-sound"
+ label="&noscriptSound;"
+ oncommand="noscriptOverlay.toggleMenuOpt(this)"
+ type="checkbox" autocheck="true"
+ />
+
+ <menuseparator class="noscript-sep-global" />
+ <menuitem class="menuitem-iconic" />
+
+ <menuitem id="noscript-mi-invopt-volatilePrivatePermissions"
+ label="&noscriptPermanentInPrivate;"
+ type="checkbox" autocheck="true"
+ oncommand="noscriptOverlay.toggleMenuOpt(this);noscriptOverlay._syncUINow()"
+ />
+ <menuitem id="noscript-revoke-temp-mi"
+ class="menuitem-iconic noscript-revoke-temp"
+ label="&noscriptRevokeTemp;" accesskey="&noscriptRevokeTemp.accesskey;"
+ oncommand="noscriptOverlay.revokeTemp()"
+ />
+ <menuitem id="noscript-allow-page-mi"
+ class="menuitem-iconic noscript-allow"
+ label="&noscriptAllowPage;" noaccesskey="&noscriptAllowPage.accesskey;"
+ oncommand="noscriptOverlay.allowPage(true)"
+ />
+ <menuitem id="noscript-temp-allow-page-mi"
+ class="menuitem-iconic noscript-temp noscript-allow"
+ label="&noscriptTempAllowPage;" noaccesskey="&noscriptTempAllowPage.accesskey;"
+ oncommand="noscriptOverlay.allowPage()"
+ />
+ <menuitem id="noscript-temp2perm-mi"
+ class="menuitem-iconic noscript-allow"
+ label="&noscriptTempToPerm;" accesskey="&noscriptTempToPerm.accesskey;"
+ oncommand="noscriptOverlay.tempToPerm()"
+ />
+
+ <menu id="noscript-xss-menu" class="menu-iconic noscript-xss"
+ onpopupshowing="event.stopPropagation()"
+ onpopuphidden="event.stopPropagation()"
+ label="&noscriptXss;">
+ <menupopup id="noscript-xss-menupopup"></menupopup>
+ </menu>
+
+
+ <menuseparator />
+ <menuseparator class="noscript-sep-untrusted"/>
+
+ <menu id="noscript-menu-blocked-objects" class="menu-iconic noscript-embed"
+ onpopupshowing="event.stopPropagation()"
+ onpopuphidden="event.stopPropagation()"
+ label="&noscriptBlockedObjects;">
+ <menupopup />
+ </menu>
+
+ <menu id="noscript-menu-recent-blocked" class="menu-iconic"
+ onpopupshowing="event.stopPropagation()"
+ onpopuphidden="event.stopPropagation()"
+ label="&noscriptRecentBlocked;">
+ <menupopup>
+ <menuitem id="noscript-mi-recent-blocked-reset"
+ label="&noscriptReset;"
+ class="menuitem-iconic"
+ accesskey="&noscriptReset.accesskey;"
+ oncommand="noscriptOverlay.ns.purgeRecent()"
+ />
+ </menupopup>
+ </menu>
+
+ <menu id="noscript-menu-untrusted" class="menu-iconic noscript-untrusted"
+ onpopupshowing="event.stopPropagation()"
+ onpopuphidden="event.stopPropagation()"
+ label="&noscriptUntrusted;">
+ <menupopup />
+ </menu>
+
+
+ <menuseparator class="noscript-sep-insert"/>
+ <menuseparator class="noscript-sep-stop" hidden="true" />
+ </menupopup>
+
+
+
+ <menupopup id="noscript-xss-popup" onpopupshowing="noscriptOverlay.prepareXssMenu(this)">
+ <menuitem id="noscript-mi-xss-console"
+ label="&noscriptShowConsole;"
+ class="menuitem-iconic noscript-console"
+ accesskey="&noscriptShowConsole.accesskey;"
+ oncommand="noscriptUtil.openConsole()"
+ />
+
+ <menuitem id="noscript-mi-xss-unsafe-reload"
+ class="menuitem-iconic noscript-unsafe-reload"
+ label="&noscriptUnsafeReload;"
+ accesskey="&noscriptUnsafeReload.accesskey;"
+ oncommand="noscriptOverlay.unsafeReload()"
+ />
+
+ <menuseparator />
+ <menuitem id="noscript-mi-xss-opt-xss.notify"
+ label="&noscriptNotifications;"
+ type="checkbox" autocheck="true"
+ oncommand="noscriptOverlay.toggleMenuOpt(this)"
+ />
+
+ <menuitem id="noscript-mi-xss-options"
+ label="&noscriptOptions;"
+ class="menuitem-iconic noscript-options"
+ accesskey="&noscriptOptions.accesskey;"
+ oncommand="noscriptUtil.openXssOptions()"
+ />
+
+ <menuseparator />
+ <menuitem id="noscript-mi-xss-faq"
+ label="&noscriptXssFaq;"
+ class="menuitem-iconic noscript-faq"
+ accesskey="&noscriptXssFaq.accesskey;"
+ oncommand="noscriptUtil.openFaq('xss')"
+ />
+ <menuitem id="noscript-abe-opts" class="menuitem-iconic noscript-abe"
+ style="display: none !important" />
+ </menupopup>
+
+
+ <menupopup id="noscript-sticky-ui"
+ onpopupshowing="noscriptOverlay.onMenuShowing(event)"
+ position="after_end"
+ >
+
+ <menuseparator class="noscript-sep-insert" hidden="true" />
+
+ <menuseparator class="noscript-sep-stop-untrusted"/>
+ <!-- dynamically inserted #noscript-menu-untrusted -->
+
+ <menuseparator class="noscript-sep-global" />
+ <menuitem class="menuitem-iconic" />
+ <menuseparator />
+ <menuitem id="noscript-options-fn-tbb-menuitem"
+ label="&noscriptOptions;"
+ accesskey="&noscriptOptions.accesskey;"
+ oncommand="noscriptUtil.openOptionsDialog()"
+ tooltiptext="&noscriptOptionsLong;"
+ class="menuitem-iconic noscript-options"
+ />
+
+ </menupopup>
+
+
+
+ <menupopup id="noscript-status-popup"
+ onpopupshowing="noscriptOverlay.onMenuShowing(event)"
+ >
+ <menuitem
+ label="&noscriptAbout;"
+ tooltiptext="&noscriptAbout;"
+ oncommand="noscriptUtil.openAboutDialog()"
+ class="menuitem-iconic noscript-about"
+ />
+
+ <menuitem
+ label="&noscriptOptions;"
+ accesskey="&noscriptOptions.accesskey;"
+ oncommand="noscriptUtil.openOptionsDialog()"
+ tooltiptext="&noscriptOptionsLong;"
+ class="menuitem-iconic noscript-options"
+ />
+
+ <menuseparator class="noscript-sep-global"/>
+ <menuitem class="menuitem-iconic" />
+
+ <menuseparator class="noscript-sep-untrusted"/>
+
+ <menuseparator class="noscript-sep-insert"/>
+ <menuseparator class="noscript-sep-stop" hidden="true" />
+ </menupopup>
+
+
+ </popupset>
+<toolbox id="navigator-toolbox">
+<statusbar id="status-bar">
+ <statusbarpanel id="noscript-statusLabel"
+ insertbefore="statusbar-updates"
+ hidden="true"
+ oncontextmenu="noscriptOverlay.onContextMenu(event)"
+ onclick="noscriptOverlay.openPopup(this.firstChild, this)"
+ >
+ <vbox flex="1" align="center" pack="center">
+ <label id="noscript-statusLabelValue"/>
+ </vbox>
+ </statusbarpanel>
+
+
+ <statusbarpanel id="noscript-statusIcon"
+ insertbefore="statusbar-updates"
+ class="statusbarpanel-menu-iconic noscript-no"
+ hidden="false"
+ oncontextmenu="noscriptOverlay.onContextMenu(event)"
+ onmouseup="noscriptOverlay.onUIUp(event)"
+ onmouseover="noscriptOverlay.onUIOver(event)"
+ onmousemove="noscriptOverlay.onUIMove(event)"
+ onmouseout="noscriptOverlay.onUIOut(event)"
+ />
+
+
+ <statusbarpanel id="noscript-statusXss" insertbefore="statusbar-updates"
+ class="statusbarpanel-menu-iconic noscript-xss"
+ hidden="true"
+ onclick="switch(event.button) { case 1: this.hidden = true; break; case 2: event.preventDefault(); this.firstChild.showPopup(); }"
+ >
+ <menupopup id="noscript-status-xss-popup" onpopupshowing="noscriptOverlay.prepareXssMenu(this, true)" />
+ </statusbarpanel>
+
+ <statusbarpanel id="noscript-statusRedirect" insertbefore="statusbar-updates"
+ class="statusbarpanel-iconic noscript-redirect"
+ hidden="true"
+ onclick="if(event.button == 1) this.hidden = true"
+ oncommand="noscriptOverlay.followMetaRefresh(event)"
+ />
+
+</statusbar>
+</toolbox>
+</overlay>
diff --git a/extensions/noscript/chrome/content/noscript/noscriptOverlay.js b/extensions/noscript/chrome/content/noscript/noscriptOverlay.js
new file mode 100644
index 0000000..80668f9
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/noscriptOverlay.js
@@ -0,0 +1,2685 @@
+window.noscriptOverlay = (function() {
+
+var $ = (id) => document.getElementById(id);
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+function domCleanup() {
+ for (let node of document.querySelectorAll(
+ `toolbarbutton[id^="noscript-tbb"],
+ #mainPopupSet>menupopup[id^="noscript-"],
+ #noscript-context-menu,
+ #status-bar>[id^="noscript-"]`
+ )) {
+ node.hidden = true;
+ if (node.parentNode) node.parentNode.removeChild(node);
+ }
+}
+return {
+
+ ns: noscriptUtil.service,
+
+ getString: (key, parms) => noscriptUtil.getString(key, parms),
+
+ toggleCurrentPage: function(forceLevel) {
+ const ns = this.ns;
+ var level = ns.getPref("toolbarToggle", 3) || forceLevel;
+ if (!level) return false;
+
+ const url = ns.getQuickSite(this.currentURL, level);
+ if (url)
+ this.safeAllow(url, !ns.isJSEnabled(url), ns.getPref("toggle.temp"));
+
+ return true;
+ },
+
+
+ getSites: function() {
+ return this.ns.getSites(this.currentBrowser);
+ },
+
+ openPopup: function(popup, anchor) {
+ popup.openPopup(anchor);
+ },
+ onContextMenu: function(ev) {
+ var parent = ev.currentTarget;
+ var popup = parent.firstChild;
+ if (!(popup && popup.openPopup)) return;
+ if (this.stickyUI) {
+ popup._context = true;
+ }
+ ev.preventDefault();
+ noscriptOverlay.openPopup(popup, parent);
+ },
+
+ onMenuShowing: function(ev, noSticky) {
+
+ var popup = ev.currentTarget;
+
+ if (popup != ev.originalTarget) return;
+
+ var stickyUI = this.stickyUI;
+
+ if (stickyUI) {
+ popup.setAttribute("sticky", !noSticky &&
+ (popup == stickyUI ||
+ !popup._context && this.useStickyUI));
+
+ popup._context = false;
+ } else {
+ popup.removeAttribute("sticky");
+ }
+
+ if (!popup.hasAttribute("onclick")) {
+ popup.setAttribute("onclick", "noscriptOverlay.onCommandClick(event)");
+ }
+
+ popup.addEventListener("popuphidden", noscriptOverlay.onMenuHidden, false);
+ popup.addEventListener("popupshown", noscriptOverlay.onMenuShown, false);
+
+ this.prepareMenu(popup);
+ },
+
+ onUIOver: function(ev) {
+ let parent = ev.currentTarget;
+ let popup = parent.firstChild || !this.initPopups() && parent.firstChild;
+
+ if (!(popup && popup.openPopup) ||
+ ("_hovering" in popup) && popup._hovering ||
+ !this.hoverUI)
+ return;
+
+ if (popup.state !== "open") {
+ popup._context = false;
+ popup._hovering = 1;
+ parent._lastMoved = 0;
+ const delayStop = this.ns.getPref("hoverUI.delayStop");
+ let delay = Math.max(this.ns.getPref("hoverUI.delayEnter"), delayStop);
+ if (delay > 0) {
+ window.setTimeout(function() {
+ if (!popup._hovering) return;
+ if (parent._lastMoved && (Date.now() - parent._lastMoved) > delayStop) {
+ noscriptOverlay.openPopup(popup, parent);
+ } else if (delayStop > 0) {
+ window.setTimeout(arguments.callee, delayStop);
+ }
+ }, delay);
+ } else {
+ this.openPopup(popup, parent);
+ }
+ } else {
+ popup._hovering = 2;
+ }
+ },
+
+ onUIMove: function(ev) {
+ let parent = ev.currentTarget;
+ let rect = parent.getBoundingClientRect();
+ let x = ev.clientX, y = ev.clientY;
+ parent._lastMoved =
+ (x > rect.left + 1 && x < rect.right - 1 &&
+ y > rect.top + 1 && y < rect.bottom - 1)
+ ? Date.now() : 0;
+ },
+
+ _uiOutTimeout: 0,
+ onUIOut: function(ev) {
+ let parent = ev.currentTarget;
+ let popup = parent.firstChild;
+
+ parent._lastMoved = 0;
+
+ if (!("_hovering" in popup && popup._hovering && popup._hovering !== -1))
+ return;
+
+ let related = ev.relatedTarget;
+ if (related) {
+ for (let node = related; node; node = node.parentNode)
+ if (node == parent) return;
+ }
+
+ if (this._uiOutTimeout) window.clearTimeout(this._uiOutTimeout);
+ this._uiOutTimeout = window.setTimeout(function() {
+ if (!popup._hovering) {
+ switch(popup.state) {
+ case "open":
+ case "showing":
+ popup.hidePopup();
+ if (popup.state !== "closed" &&
+ (!("nsIPopupBoxObject" in Ci) ||
+ popup.boxObject instanceof Ci.nsIPopupBoxObject))
+ popup.boxObject.hidePopup();
+ break;
+ }
+ }
+ },
+ this.ns.getPref("hoverUI.delayExit" +
+ (popup._hovering == 1
+ ? "1"
+ : "2"
+ ), 250)
+ );
+
+ ev.currentTarget.removeEventListener(ev.type, arguments.callee, false);
+ popup._hovering = 0;
+ },
+
+ onUICommand: function(ev) {
+ if (ev.currentTarget !== ev.target) return;
+
+ if (!(this.hoverUI && this.ns.getPref("hoverUI.excludeToggling")) &&
+ this.toggleCurrentPage())
+ ev.preventDefault();
+ },
+
+ onUIUp: function(ev) {
+ let tb = ev.currentTarget;
+ if (tb !== ev.target) return;
+
+ if (tb.id === "noscript-tbb" &&
+ (tb.type !== "menu-button" || ev.originalTarget.tagName == "xul:toolbarbutton") &&
+ ev.button === 0 &&
+ !(this.hoverUI && this.ns.getPref("hoverUI.excludeToggling")) &&
+ this.toggleCurrentPage()
+ ) {
+ // discriminate dropdown button from main click area
+ ev.preventDefault();
+ return;
+ }
+
+ if (ev.button === 1 && this.ns.getPref('middlemouse_temp_allow_main_site')) {
+ this.allowPage();
+ ev.preventDefault();
+ return;
+ }
+
+ let popup = tb.firstChild || !this.initPopups() && tb.firstChild;
+ if ("_hovering" in popup && popup._hovering === 1 || // reopen if still hovering the icon
+ this.hoverUI && !this.isOpenOrJustClosed(popup)) {
+ popup._hovering = -1;
+ if (ev.button !== 2) this.openPopup(popup, tb);
+ }
+ },
+
+
+ onCommandClick: function(ev) {
+ if (ev.button === 2) {
+ noscriptOverlay.copy(ev.target);
+ ev.preventDefault();
+ ev.stopPropagation();
+ return;
+ }
+
+ if (!(ev.button === 1 || ev.button === 0 && ev.shiftKey)) return;
+
+ if (noscriptUtil.openInfo(ev.target.getAttribute("statustext"))) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ ev.currentTarget.hidePopup();
+ }
+
+ },
+
+ onMenuShown: function(ev) {
+ let popup = ev.currentTarget;
+ popup.removeEventListener(ev.type, arguments.callee, false);
+ if (/^before_/.test(popup.position)) {
+ let scroller = popup.ownerDocument.getAnonymousElementByAttribute(popup, "class", "popup-internal-box");
+ scroller.scrollPosition = popup.scrollHeight; // scroll to bottom
+ }
+ },
+
+ _reloadDirty: false,
+
+ isOpenOrJustClosed: function(popup) {
+ return popup.state && popup.state == "open" ||
+ this._currentPopup == popup ||
+ (new Date() - (popup._lastClosed || 0)) < 300;
+ },
+
+ onMenuHidden: function(ev) {
+ var popup = ev.currentTarget;
+ if (ev.originalTarget != popup) return;
+
+ popup.removeEventListener(ev.type, arguments.callee, false);
+
+ if ("_hovering" in popup && popup._hovering !== 1)
+ popup._hovering = 0;
+
+ if (noscriptOverlay._reloadDirty && !noscriptOverlay.liveReload) {
+ let ns = noscriptOverlay.ns;
+ ns.savePrefs();
+ ns.reloadWhereNeeded();
+ }
+
+
+ if (popup.id === "noscript-tbb-popup") {
+ // take back our stuff
+ noscriptOverlay._currentPopup = null;
+ let sites = noscriptOverlay.getSites();
+ sites.pluginExtras = sites.pluginSites = [];
+ noscriptOverlay.prepareMenu($("noscript-status-popup"), sites);
+ }
+ popup._lastClosed = Date.now();
+ noscriptOverlay._reloadDirty = false;
+ noscriptOverlay._currentPopup = null;
+ },
+
+ prepareContextMenu: function(ev) {
+ var menu = $("noscript-context-menu");
+ if (this.ns.getPref("ctxMenu", true)) {
+ menu.removeAttribute("hidden");
+ } else {
+ menu.setAttribute("hidden", "true");
+ return;
+ }
+ this.updateStatusClass(menu);
+ }
+
+,
+ parseMenuOpt: function(node) {
+ let opt = node.id.match(/-((?:inv)?opt)-(.*)/);
+ return opt && { name: opt[2], inverse: opt[1][0] === 'i'};
+ }
+,
+ toggleMenuOpt: function(node) {
+ var val = node.getAttribute("checked") === "true";
+ var opt = this.parseMenuOpt(node);
+ if (opt) {
+ this.ns.setPref(opt.name, opt.inverse ? !val : val);
+ }
+ return val;
+ }
+,
+ prepareOptItems: function(popup) {
+ const notifications = this.getNotificationBox();
+ const opts = popup.getElementsByAttribute("type", "checkbox");
+ for (let j = opts.length; j-- > 0;) {
+ let node = opts[j];
+ let opt = this.parseMenuOpt(node);
+ if (opt) {
+ if ((!notifications) && node.id.indexOf("notification") - 1) {
+ node.setAttribute("hidden", "true");
+ } else {
+ let val = this.ns.getPref(opt.name);
+ if (opt.inverse) val = !val;
+ node.setAttribute("checked", val);
+ }
+ }
+ }
+ },
+
+
+ prepareXssMenu: function(popup, invert) {
+ this.prepareOptItems(this.populateXssMenu(popup, invert));
+ },
+ populateXssMenu: function(popup, invert) {
+ var ref = $("noscript-mi-xss-unsafe-reload");
+ var parent = ref.parentNode;
+ var inverse = parent.lastChild.id != "noscript-mi-xss-faq";
+ invert = inverse && !invert;
+ if (parent != popup) {
+ while (parent.firstChild) {
+ popup.appendChild(invert ? parent.lastChild : parent.firstChild);
+ }
+ } else if (invert) {
+ for (var p, n = parent.lastChild; n; n = p) {
+ p = n.previousSibling;
+ parent.appendChild(n);
+ }
+ }
+ return popup;
+ },
+
+
+
+ getSiteTooltip: function(enabled, full) {
+ const info = this.getString("siteInfo.tooltip");
+ const sep = "\n";
+ const no = this.getString("allowed.no");
+ const noFull = no + sep + info;
+ const yes = this.getString("allowed.yes");
+ const yesFull = yes + sep + info;
+ return (this.getSiteTooltip = (function(enabled, full) {
+ return enabled ? full && yesFull || yes : full && noFull || no;
+ }))(enabled, full);
+ },
+
+ getRevokeTooltip: function(tempSites) {
+ const ns = this.ns;
+ const sep = "\n\n";
+
+ // remove http/https/file CAPS hack entries
+ var tip = "<SCRIPT>: ";
+ if (tempSites) {
+ tempSites = this.ns.siteUtils.sanitizeString(tempSites.replace(/\b(?:https?|file):\/\//g, "")).split(/\s+/);
+ tip += tempSites.join(", ");
+ } else tip += "0";
+
+ var len = ns.objectWhitelistLen;
+ if (len) tip += sep + "<OBJECT>: " + len;
+
+ len = ns.clearClickHandler && ns.clearClickHandler.whitelistLen;
+ if (len) tip += sep + "ClearClick: " + len;
+
+ return tip;
+ },
+
+ isPrivate: function() {
+ try {
+ // Firefox 20+
+ Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
+ return PrivateBrowsingUtils.isWindowPrivate(window);
+
+ } catch(e) {
+
+ try {
+ return Cc["@mozilla.org/privatebrowsing;1"].
+ getService(Ci.nsIPrivateBrowsingService).
+ privateBrowsingEnabled;
+ } catch(e) {
+ Components.utils.reportError(e);
+ return false;
+ }
+ }
+
+ },
+
+ _popupsInitialized: false,
+ _initPopupsRecursion: false,
+
+ initPopups: function() {
+ if (this._initPopupsRecursion) return;
+
+ this._initPopupsRecursion = true;
+
+ try {
+
+ const sticky = this.stickyUI; // early init
+
+ const popup = $("noscript-status-popup");
+ if (!popup) return; // Fennec?
+
+ const install = !this._popupsInitialized;
+ this._popupsInitialized = true;
+
+ const tbb = $("noscript-tbb");
+ if (tbb) {
+ tbb.setAttribute("type", this.hoverUI ? "button" : this.ns.getPref("toolbarToggle") ? "menu-button" : "menu");
+ }
+
+ const buttons = [tbb, $("noscript-statusLabel")];
+
+ let statusIcon = $("noscript-statusIcon");
+
+ if ($("addon-bar")) {
+ // Fx 4 till Austrails
+ if (install && !("CustomizableUI" in window)) {
+ window.addEventListener("aftercustomization", function(ev) {
+ noscriptOverlay.initPopups();
+ }, false);
+ }
+ if (statusIcon) statusIcon.parentNode.removeChild(statusIcon);
+ } else {
+ // Fx 3.6.x or below
+ if (install) {
+ let btcd = window.BrowserToolboxCustomizeDone;
+ if (btcd) window.BrowserToolboxCustomizeDone = function(done) {
+ btcd(done);
+ if (done) noscriptOverlay.initPopups();
+ };
+ }
+
+ buttons.push(statusIcon);
+ }
+ // copy status bar menus
+ for (let button of buttons) {
+ if (!button) continue;
+ let localPopup = button.firstChild;
+ if (!(localPopup && /popup/.test(localPopup.tagName))) {
+ localPopup = popup.cloneNode(true);
+ localPopup.id = button.id + "-popup";
+ button.insertBefore(localPopup, button.firstChild);
+ if (!sticky) localPopup._context = true;
+ }
+ if (!this._mustReverse(localPopup)) {
+ localPopup.position = /(?:addon|status)/.test(button.parentNode.id)
+ ? "before_start" : "after_start";
+ }
+ }
+ } finally {
+ this._initPopupsRecursion = false;
+ }
+ },
+
+ copy: function(node) {
+ node = node || document.popupNode;
+ var txt = "";
+ const classRx = /\bnoscript-(allow|forbid)\b/;
+ if (!(classRx.test(node.className) && (txt = node.getAttribute("statustext")))) {
+ let parent = node.parentNode;
+ let nodes = parent.childNodes;
+ let untrusted = $("noscript-menu-untrusted");
+ if (untrusted.parentNode === parent) {
+ nodes = Array.slice(nodes).concat(Array.slice(untrusted.getElementsByClassName("noscript-allow")));
+ }
+ let sites = [];
+ for (let j = 0, len = nodes.length; j < len; j++) {
+ if (classRx.test(nodes[j].className)) {
+ let site = nodes[j].getAttribute("statustext");
+ if (site && sites.indexOf(site) === -1) {
+ sites.push(site);
+ }
+ }
+ }
+ const ns = noscriptOverlay.ns;
+ txt = sites.map(
+ (s) => (ns.isJSEnabled(s) ? "+" : ns.isUntrusted(s) ? "!" : "-") + s
+ ).join("\n");
+ }
+ if (txt) {
+ Cc["@mozilla.org/widget/clipboardhelper;1"]
+ .getService(Ci.nsIClipboardHelper)
+ .copyString(txt);
+ }
+ },
+
+ _currentPopup: null,
+ _mustReverse: function(popup) {
+ if (popup.id !== "noscript-tbb-popup") return false;
+ if (/\bnoscript-(?:about|options)\b/.test(popup.lastChild.className)) {
+ // already reversed: we need it straight to populate
+ this.reverse(popup);
+ }
+ let upper;
+ try {
+ upper = popup.parentNode.boxObject.screenY < screen.availHeight / 2;
+ } catch(e) {
+ upper = false;
+ }
+ popup.position = upper ? "after_start" : "before_start";
+ return upper;
+ },
+
+ prepareMenu: function(popup, sites) {
+ let mustReverse = this._mustReverse(popup);
+
+ const ns = this.ns;
+ const sticky = popup.getAttribute("sticky") == "true";
+
+ popup.removeAttribute("disabled");
+
+ if (!popup.hasAttribute("context")) {
+ popup.setAttribute("context", "noscript-menuContext");
+ }
+
+ if (this._currentPopup && this._currentPopup != popup) {
+ this._currentPopup.hidePopup();
+ }
+ this._currentPopup = popup;
+
+
+
+ var node;
+
+ const global = ns.jsEnabled;
+ const blockUntrusted = global && ns.alwaysBlockUntrustedContent;
+ const cascadePermissions = ns.cascadePermissions;
+ const globalHttps = ns.globalHttpsWhitelist;
+
+ var seps = { insert: null, stop: null, global: null, untrusted: null };
+ {
+ let allSeps = popup.getElementsByTagName("menuseparator");
+ for (let j = allSeps.length; j-- > 0;) {
+ let sepName = (node = allSeps[j]).className;
+ node.hidden = false;
+ for (let k in seps) {
+ if (sepName.indexOf("-" + k) > -1) {
+ seps[k] = node;
+ }
+ }
+ }
+ }
+
+ const miGlobal = seps.global.nextSibling;
+
+ if (global || ns.getPref("showGlobal")) {
+ miGlobal.hidden = seps.global.hidden = false;
+ miGlobal.setAttribute("label", this.getString((global ? "forbid" : "allow") + "Global"));
+ miGlobal.setAttribute("oncommand", "noscriptOverlay.menuCmd(event)");
+ miGlobal.setAttribute("tooltiptext", this.statusIcon.getAttribute("tooltiptext"));
+ miGlobal.setAttribute("class", "menuitem-iconic noscript-glb " + (global ? "noscript-forbid" : "noscript-allow"));
+ } else {
+ miGlobal.hidden = seps.global.hidden = true;
+ }
+
+ node = popup.getElementsByClassName("noscript-about")[0];
+ if (node) node.hidden = !ns.getPref("showAbout");
+
+ node = seps.global;
+ node.parentNode.insertBefore(
+ $("noscript-mi-invopt-volatilePrivatePermissions"), node
+ ).hidden = !(this.isPrivate() && ns.getPref("showVolatilePrivatePermissionsToggle"));
+
+
+ node = miGlobal.nextSibling;
+ const mainMenu = node.parentNode;
+ {
+ let tempMenuItem = $("noscript-revoke-temp-mi");
+ if (node != tempMenuItem) {
+ node = mainMenu.insertBefore(tempMenuItem, node);
+ }
+ let tempSites = ns.gTempSites.sitesString;
+ tempSites = tempSites && (tempSites + " " + ns.tempSites.sitesString).replace(/\s+$/g, '') || ns.tempSites.sitesString;
+ if ((tempSites || ns.objectWhitelistLen || ns.clearClickHandler && ns.clearClickHandler.whitelistLen) && ns.getPref("showRevokeTemp", true)) {
+ node.hidden = seps.global.hidden = false;
+ node.setAttribute("tooltiptext", this.getRevokeTooltip(tempSites));
+ } else {
+ node.hidden = true;
+ }
+ }
+
+ node = node.nextSibling;
+ let allowPageMenuItem = $("noscript-temp-allow-page-mi");
+ if (node !== allowPageMenuItem) {
+ mainMenu.insertBefore(allowPageMenuItem, node)
+ } else {
+ node = node.nextSibling;
+ }
+
+ let xssMenu = $("noscript-xss-menu");
+
+ if (xssMenu && node != xssMenu) {
+ mainMenu.insertBefore(xssMenu, node);
+ }
+ this.populateXssMenu(xssMenu.firstChild);
+ this.syncXssWidget(xssMenu);
+
+ this.prepareOptItems(popup);
+
+ var untrustedMenu = null,
+ recentMenu = null,
+ pluginsMenu = null;
+
+ if (seps.untrusted) {
+
+ pluginsMenu = $("noscript-menu-blocked-objects");
+ recentMenu = $("noscript-menu-recent-blocked");
+ untrustedMenu = $("noscript-menu-untrusted");
+ // cleanup untrustedCount display
+ untrustedMenu.setAttribute("label", untrustedMenu.getAttribute("label").replace(/ \(\d+\)$/, ""));
+
+ with (seps.untrusted) {
+ if ((extraNode = nextSibling) != pluginsMenu) {
+ for (node of [pluginsMenu, recentMenu, untrustedMenu]) {
+ parentNode.insertBefore(node, extraNode);
+ }
+ }
+ }
+
+ this.populateExternalFilters(pluginsMenu);
+
+ extraNode = $("noscript-mi-recent-blocked-reset"); // save reset command
+ // descend from menus to popups and clear children
+ for (node of [pluginsMenu = pluginsMenu.firstChild, recentMenu = recentMenu.firstChild, untrustedMenu = untrustedMenu.firstChild])
+ while(node.firstChild) node.removeChild(node.firstChild);
+
+ recentMenu.appendChild(extraNode);
+ }
+
+ node = seps.insert.nextSibling;
+
+ var remNode;
+ while (node && (node != seps.stop)) {
+ remNode = node;
+ node = node.nextSibling;
+ if (remNode != untrustedMenu && remNode != xssMenu)
+ mainMenu.removeChild(remNode);
+ }
+
+ sites = sites || this.getSites();
+ let all = sites.all;
+ const topSite = sites.topSite;
+ {
+ let topIdx = all.indexOf(topSite);
+ let topDown = !/-sep-stop\b/.test(mainMenu.lastChild.className);
+ if (topIdx > -1 && topIdx != (topDown ? all.length - 1 : 0)) {
+ all.splice(topIdx, 1);
+ if (topDown) all.push(topSite);
+ else all.unshift(topSite);
+ }
+ }
+
+ try {
+ this.populatePluginsMenu(mainMenu, pluginsMenu, sites.pluginExtras);
+ } catch(e) {
+ if(ns.consoleDump) ns.dump("Error populating plugins menu: " + e);
+ if (e) Components.utils.reportError(e);
+ }
+
+ const jsPSs = ns.jsPolicySites;
+ var site, enabled, isTop, lev;
+
+ var matchingSite;
+ var menuGroups, menuSites, menuSite, scount;
+ var domain, pos, baseLen;
+ var untrusted;
+ var cssClass;
+
+ const dupeChecker = {
+ sites: {},
+ check: function(s) { return (s in this.sites) || (this.sites[s] = false); }
+ };
+
+ const locked = ns.locked;
+ const addressOnly = locked;
+ const showAddress = addressOnly || ns.getPref("showAddress", false);;
+ const showDomain = !addressOnly && ns.getPref("showDomain", false);
+ const showBase = !addressOnly && ns.getPref("showBaseDomain", true);
+ const showUntrusted = ns.getPref("showUntrusted", true);
+ const showDistrust = ns.getPref("showDistrust", true);
+ const showNothing = !(showAddress || showDomain || showBase || showUntrusted);
+ let isPrivate = this.isPrivate();
+ let volatileOnly = isPrivate && ns.getPref("volatilePrivatePermissions");
+
+ let showPermanent = ns.getPref("showPermanent", true);
+ const showTemp = !locked && (ns.getPref("showTemp", true) || volatileOnly && showPermanent);
+ if (volatileOnly) showPermanent = false;
+
+ var parent = null, extraNode = null;
+ var untrustedCount = 0, unknownCount = 0, tempCount = 0;
+ const untrustedSites = ns.untrustedSites;
+ var externalJSBlocked = false;
+
+ const ignorePorts = ns.ignorePorts;
+ const portRx = /:\d+$/;
+
+ const hideUntrustedPlaceholder = !ns.showUntrustedPlaceholder;
+ var embedOnlySites = null;
+ if (ns.contentBlocker && !ns.alwaysShowObjectSources &&
+ sites.pluginSites.length) {
+ // add untrusted plugin sites if placeholders are not shown for untrusted sources
+ embedOnlySites = sites.pluginSites.filter(function(s) {
+ return all.indexOf(s) === -1;
+ });
+ all.push.apply(all, embedOnlySites);
+ }
+
+ menuGroups = [];
+ for (let j = 0; j < all.length; j++) {
+ site = all[j];
+
+ matchingSite = jsPSs.matches(site);
+ untrusted = untrustedSites.matches(site);
+ let hasPort = portRx.test(site);
+
+ isTop = site == topSite;
+
+ if (untrusted) {
+ matchingSite = null;
+ } else if (!matchingSite) {
+
+ if (ignorePorts && hasPort) {
+ matchingSite = jsPSs.matches(site.replace(portRx, ''));
+ if (matchingSite) {
+ site = matchingSite;
+ hasPort = false;
+ }
+ }
+
+ if (blockUntrusted)
+ matchingSite = site;
+ }
+
+
+ enabled = !!(matchingSite ||
+ globalHttps && ns.isGlobalHttps(content, site) && (matchingSite = site)
+ );
+
+ let showInMain = embedOnlySites
+ ? embedOnlySites.indexOf(site) === -1 || hideUntrustedPlaceholder && enabled : true;
+
+ externalJSBlocked = enabled && isTop && (sites.docJSBlocked || sites.cspBlocked);
+ if (externalJSBlocked) enabled = false;
+
+ if (enabled && !global || (matchingSite = untrusted)) {
+ if (ignorePorts && hasPort) {
+ site = jsPSs.matches(site.replace(portRx, ''));
+ if (site) matchingSite = site;
+ }
+ if (dupeChecker.check(matchingSite)) continue;
+ menuSites = [matchingSite];
+
+ } else {
+ domain = !ns.isForbiddenByHttpsStatus(site) && ns.getDomain(site);
+ let dp = ns.getPublicSuffix(domain);
+
+ if (dp == domain || // exclude TLDs
+ ns.isJSEnabled(domain) != enabled || // exclude ancestors with different permissions
+ hasPort && !ignorePorts // or any ancestor if this is a non-standard port
+ ) {
+ domain = null;
+ }
+
+
+ if (hasPort && ignorePorts) {
+ site = site.replace(portRx, '');
+ if (jsPSs.matches(site))
+ continue;
+ }
+
+ if (dupeChecker.check(site)) continue;
+
+ menuSites = (showAddress || showNothing || !domain) ? [site] : [];
+
+ if (domain && (showDomain || showBase)) {
+ baseLen = domain.length;
+ if (dp)
+ baseLen -= (domain.lastIndexOf(".", baseLen - dp.length - 2) + 1);
+ if (baseLen == domain.length) {
+ // IP or 2nd level domain
+ if (!dupeChecker.check(domain)) {
+ menuSites.push(domain);
+ }
+ } else {
+ dp = domain;
+ for (pos = 0; (pos = domain.indexOf('.', pos)) > 0; dp = domain.substring(++pos)) {
+ if (baseLen == dp.length) {
+ if (menuSites.length > 0 && !showBase) continue;
+ } else {
+ if (!showDomain) continue;
+ }
+ if (!dupeChecker.check(dp)) {
+ menuSites.push(dp);
+ }
+ if (baseLen == dp.length) break;
+ }
+ }
+ }
+ }
+ menuSites.isTop = isTop;
+ menuSites.showInMain = showInMain;
+ menuSites.enabled = enabled;
+ menuGroups.push(menuSites);
+ }
+
+
+ const untrustedFrag = showUntrusted ? document.createDocumentFragment() : null;
+ const mainFrag = document.createDocumentFragment();
+ const sep = document.createElement("menuseparator");
+
+ let mgCount = menuGroups.length;
+
+ var refMI = document.createElement("menuitem");
+ refMI.setAttribute("oncommand", "noscriptOverlay.menuCmd(event)");
+ if (sticky && (this.liveReload || mgCount > 1 || enabled)) {
+ refMI.setAttribute("closemenu", "none");
+ }
+
+ recentMenu.parentNode.hidden = true;
+ if (recentMenu && ns.getPref("showRecentlyBlocked")) {
+ let level = ns.getPref("recentlyBlockedLevel") || ns.preferredSiteLevel;
+ let max = ns.getPref("recentlyBlockedCount");
+ let dejaVu = [],
+ count = 0,
+ recent = sites.recentlyBlocked,
+ current = false;
+
+ let tooltip = this.getSiteTooltip(false, !!ns.getPref("siteInfoProvider"));
+
+ for (let j = recent.length; j-- > 0;) {
+
+ let r = recent[j];
+ let s = r.site;
+
+ if (!s || all.indexOf(s) > -1) continue;
+
+ let ghEnabled = globalHttps && ns.isGlobalHttps(content, s);
+ let jsEnabled = ghEnabled || ns.isJSEnabled(s);
+
+ if (jsEnabled && (!ns.contentBlocker || ns.isAllowedObject("!", "*", s)))
+ continue;
+
+ s = ns.getQuickSite(s, level);
+ if (dejaVu.indexOf(s) > -1)
+ continue;
+
+ dejaVu.push(s);
+
+ recentMenu.appendChild(sep.cloneNode(false));
+
+ let node = refMI.cloneNode(false);
+ let cssClass = "noscript-cmd menuitem-iconic noscript-allow-from";
+
+ node.setAttribute("tooltiptext", tooltip);
+ node.setAttribute("statustext", s);
+ if (locked || ns.isForbiddenByHttpsStatus(s)) node.setAttribute("disabled", "true");
+
+ if (r.origins.indexOf(topSite) > -1) {
+ cssClass += " noscript-toplevel";
+ current = true;
+ }
+
+ if (jsEnabled) {
+ cssClass += " noscript-embed";
+ } else {
+ node.setAttribute("class", cssClass);
+ node.setAttribute("label", ns.getString("allowFrom", [s]));
+ recentMenu.appendChild(node);
+ node = node.cloneNode(false);
+ }
+
+ node.setAttribute("class", cssClass + " noscript-temp");
+ node.setAttribute("label", ns.getString("allowTempFrom", [s]));
+ recentMenu.appendChild(node);
+
+ if (++count >= max) break;
+ }
+ if (count) {
+ let menuItem = recentMenu.parentNode;
+ menuItem.hidden = false;
+ ns.dom.toggleClass(menuItem, "noscript-toplevel", current);
+ }
+ }
+
+ if (mgCount > 0 && seps.stop.previousSibling.nodeName != "menuseparator")
+ mainFrag.appendChild(sep.cloneNode(false));
+
+ const fullTip = !!ns.getPref("siteInfoProvider");
+
+ while (mgCount-- > 0) {
+
+ menuSites = menuGroups[mgCount];
+ isTop = menuSites.isTop;
+ enabled = menuSites.enabled;
+
+ let showInMain = menuSites.showInMain;
+
+ if (untrustedFrag && untrustedFrag.firstChild) {
+ untrustedFrag.appendChild(sep.cloneNode(false));
+ }
+
+ scount = menuSites.length;
+ if (scount > 0 && mainFrag.lastChild && mainFrag.lastChild.tagName != "menuseparator")
+ mainFrag.appendChild(sep.cloneNode(false));
+
+ while (scount-- > 0) {
+ menuSite = menuSites[scount];
+ let ghEnabled = globalHttps && ns.isGlobalHttps(content, menuSite);
+
+ untrusted = !enabled && (blockUntrusted || ns.isUntrusted(menuSite));
+
+ let cascaded = cascadePermissions && !isTop;
+
+ if (untrusted) {
+ untrustedCount++;
+ showInMain = true;
+ }
+ else if (!enabled)
+ unknownCount++;
+
+ parent = showUntrusted && untrusted ? untrustedFrag : mainFrag;
+ if (!parent) continue;
+
+ domain = isTop && externalJSBlocked ? "[ " + menuSite + " ]" : menuSite;
+
+ node = refMI.cloneNode(false);
+ if (isTop) {
+ cssClass = "noscript-toplevel noscript-cmd";
+ // can we make it default here?
+ }
+ else cssClass = "noscript-cmd";
+
+
+ let blurred = false;
+ let disabled = locked || (enabled ? ns.isMandatory(menuSite) : blurred = externalJSBlocked || ns.isForbiddenByHttpsStatus(menuSite));
+ if (disabled) {
+ node.setAttribute("disabled", "true");
+ } else {
+ cssClass += " menuitem-iconic ";
+ if (enabled && ns.isTemp(menuSite)) {
+ cssClass += " noscript-temp";
+ tempCount++;
+ }
+ }
+
+
+ node.setAttribute("label", this.getString((enabled ? "forbidLocal" : "allowLocal"), [domain]));
+ node.setAttribute("statustext", menuSite);
+ node.setAttribute("tooltiptext", this.getSiteTooltip(enabled, fullTip));
+
+ node.setAttribute("class", cssClass + (enabled ? " noscript-forbid" : " noscript-allow"));
+
+ if ((showPermanent || enabled) && !((global || cascaded || ghEnabled) && enabled) &&
+ showInMain && !(cascaded && parent !== untrustedFrag))
+ parent.appendChild(node);
+
+ if (!disabled) {
+ if (showTemp && !(enabled || blurred || cascaded) && showInMain) {
+ extraNode = node.cloneNode(false);
+ extraNode.setAttribute("label", this.getString("allowTemp", [domain]));
+ extraNode.setAttribute("class", cssClass + " noscript-temp noscript-allow");
+ parent.appendChild(extraNode);
+ }
+ if (((showUntrusted && untrustedMenu || showDistrust) &&
+ (cascaded || ghEnabled || !(domain in jsPSs.sitesMap)) ||
+ blockUntrusted && (showUntrusted || showDistrust)
+ ) && !untrusted) {
+ parent = (showUntrusted && !blockUntrusted ? untrustedFrag : mainFrag);
+
+ extraNode = refMI.cloneNode(false);
+ extraNode.setAttribute("label", this.getString("distrust", [menuSite]));
+ extraNode.setAttribute("statustext", menuSite);
+ extraNode.setAttribute("class", cssClass + " noscript-distrust");
+ extraNode.setAttribute("tooltiptext", node.getAttribute("tooltiptext"));
+ parent.appendChild(extraNode);
+ }
+ }
+ }
+ }
+ if (untrustedFrag && untrustedFrag.firstChild) {
+ if (untrustedCount > 0)
+ with (untrustedMenu.parentNode)
+ setAttribute("label", getAttribute("label") +
+ " (" + untrustedCount + ")"); // see above for cleanup
+
+ untrustedMenu.appendChild(untrustedFrag);
+ }
+
+ mainMenu.insertBefore(mainFrag, seps.stop);
+
+ // temp allow all this page
+ if (!(allowPageMenuItem.hidden = !(unknownCount && ns.getPref("showTempAllowPage", true)))) {
+ let allowable = this.allowPage(false, true, sites);
+ if (allowable.length) allowPageMenuItem.setAttribute("tooltiptext", allowable.join(", "));
+ else allowPageMenuItem.hidden = true;
+ }
+
+
+ // allow all this page
+ node = $("noscript-allow-page-mi");
+ if (node.nextSibling !== allowPageMenuItem) {
+ allowPageMenuItem.parentNode.insertBefore(node, allowPageMenuItem);
+ }
+ if (!(node.hidden = volatileOnly || unknownCount == 0 || !ns.getPref("showAllowPage", true))) {
+ let allowable = this.allowPage(true, true, sites);
+ if (allowable.length) node.setAttribute("tooltiptext", allowable.join(", "));
+ else node.hidden = true;
+ }
+
+ // "allow page" accelerators
+ {
+ let accel = ns.getPref("menuAccelerators");
+ for (let el of [node, allowPageMenuItem])
+ if (accel)
+ el.setAttribute("accesskey", el.getAttribute("noaccesskey"));
+ else
+ el.removeAttribute("acesskey");
+ }
+
+ // make permanent
+ node = $("noscript-temp2perm-mi");
+ if (allowPageMenuItem.nextSibling != node) {
+ allowPageMenuItem.parentNode.insertBefore(node, allowPageMenuItem.nextSibling);
+ }
+ if (!(node.hidden = volatileOnly || tempCount == 0 || !ns.getPref("showTempToPerm"))) {
+ node.setAttribute("tooltiptext", this.tempToPerm(true, sites).join(", "));
+ }
+
+ this.normalizeMenu(untrustedMenu, true);
+ this.normalizeMenu(mainMenu, false);
+
+ if (mustReverse) this.reverse(popup);
+ window.setTimeout(() => site = sites.pluginExtras = sites.pluginSites = null, 0);
+ },
+
+ reverse: function(m) {
+ var a = [];
+ var mi;
+ while((mi = m.lastChild)) {
+ a.push(m.removeChild(mi));
+ }
+ for (mi of a) {
+ m.appendChild(mi);
+ }
+ },
+
+
+
+ populateExternalFilters: function(anchor) {
+ const ns = this.ns;
+ const externalFilters = ns.externalFilters;
+
+ var parent = anchor.parentNode;
+ Array.slice(parent.getElementsByClassName("noscript-ef"), 0)
+ .forEach(function(node) { parent.removeChild(node); });
+
+ if (!(externalFilters.enabled && ns.getPref("showExternalFilters"))) return;
+
+ var menus = {};
+ var domains = [];
+ var filterNames = [];
+ var info = externalFilters.getFiltersInfo(content);
+ var f, menu, domain, whitelisted, item;
+
+ for (var url in info) {
+ domain = ns.getBaseDomain(ns.getDomain(url));
+ if (domains.indexOf(domain) !== -1) continue;
+ domains.push(domain);
+
+ f = info[url];
+ if (f.name in menus) {
+ menu = menus[f.name];
+ } else {
+ menu = menus[f.name] = { active: false, filter: f, items: [] };
+ filterNames.push(f.name);
+ }
+
+ item = { domain: domain };
+
+ whitelisted = f.whitelist && f.whitelist.test("https://" + domain);
+
+ item.disabled = whitelisted &&
+ !f.isDomainException(domain); // we cannot reliably un-whitelist custom rules
+
+ if ((item.active = !whitelisted)) menu.active = true;
+
+ menu.items.push(item);
+ }
+
+ if (!domains.length) return;
+
+ filterNames.sort();
+
+ var df = document.createDocumentFragment();
+ var node;
+ for (var filterName of filterNames) {
+ menu = menus[filterName];
+ menu.items.sort(function(a, b) { return a.domain > b.domain ? 1 : a.domain < b.domain ? -1 : 0; })
+ node = df.appendChild(document.createElement("menu"));
+ node.setAttribute("label", filterName);
+ node.setAttribute("class", "menu-iconic noscript-ef" + (menu.active ? '' : ' inactive'));
+
+ parent = node.appendChild(document.createElement("menupopup"));
+ parent.__ef__ = menu.filter;
+ for (item of menu.items) {
+ node = parent.appendChild(document.createElement("menuitem"));
+ node.setAttribute("label", ns.getString("ef.activate", [item.domain]));
+ node.setAttribute("type", "checkbox");
+ node.setAttribute("statustext", item.domain);
+ node.setAttribute("oncommand", "noscriptOverlay.onFilterSwitch(event)");
+ if (item.active)
+ node.setAttribute("checked", "true");
+ if (item.disabled)
+ node.setAttribute("disabled", "true");
+ }
+
+ }
+
+ anchor.parentNode.insertBefore(df, anchor);
+ },
+
+ onFilterSwitch: function(ev) {
+ const ns = this.ns;
+ var node = ev.target;
+ var enabled = node.getAttribute("checked") == "true";
+ var f = node.parentNode.__ef__;
+ if (!f) return;
+ var domain = node.getAttribute("statustext");
+ ns.switchExternalFilter(f.name, domain, enabled);
+ },
+
+ onMenuHiddenWithPlugins: function(ev) {
+ if (ev.currentTarget != ev.target) return;
+ ev.currentTarget.removeEventListener(ev.type, arguments.callee, false);
+ noscriptOverlay.menuPluginExtras =
+ noscriptOverlay.menuPluginSites = null;
+ },
+ populatePluginsMenu: function(mainMenu, menu, extras) {
+ if (!menu) return;
+
+ menu.parentNode.hidden = true;
+ const ns = this.ns;
+
+ if (!(extras && ns.getPref("showBlockedObjects")))
+ return;
+
+ var pluginExtras = [],
+ seen = [];
+ var i = 0;
+ for (let egroup of extras) {
+ for (let j = egroup.length; j-- > 0;) {
+ let e = egroup[j];
+
+ if (ns.isAllowedObject(e.url, e.mime, e.site, e.originSite)
+ // TODO: e10s removal check
+ /*
+ && !(e.placeholder && e.placeholder.parentNode) ||
+ typeof(e) !== "object" || (e.tag && !e.placeholder)
+ */
+ )
+ continue;
+
+ let key = e.mime + "@" + ns.objectKey(e.url, e.originSite);
+ if (seen.indexOf(key) > -1) continue;
+
+ seen.push(key);
+
+ let node = document.createElement("menuitem");
+
+ e.label = e.label || ((/<I?FRAME>/.test(e.tag) ? e.tag : ns.mimeEssentials(e.mime)) + "@" + ns.urlEssentials(e.url));
+ e.title = e.title || e.label.split("@")[0] + "@" + e.url + "\n(" + e.originSite + ")";
+
+ node.setAttribute("label", this.getString("allowTemp", [e.label]));
+ node.setAttribute("tooltiptext", e.title);
+ node.setAttribute("oncommand", "noscriptOverlay.allowObject(" + i + ")");
+ node.setAttribute("class", "menuitem-iconic noscript-cmd noscript-temp noscript-allow");
+ node.style.listStyleImage = ns.cssMimeIcon(e.mime, 16);
+ menu.appendChild(node);
+ pluginExtras[i++] = e;
+ }
+ }
+
+ if (pluginExtras.length) {
+ mainMenu.addEventListener("popuphidden", this.onMenuHiddenWithPlugins, false);
+ noscriptOverlay.menuPluginExtras = pluginExtras;
+ let pluginSites = {};
+ seen = [];
+ for (let e of pluginExtras) {
+ if(!(e.site && e.mime) || ns.isAllowedObject(e.site, e.mime, e.site, e.originSite))
+ continue;
+
+ let objectKey = ns.objectKey(e.site, e.originSite);
+ let key = e.mime + "@" + objectKey;
+ if (seen.indexOf(key) !== -1) continue;
+
+ if (!(e.site in pluginSites)) {
+ pluginSites[e.site] = [{mime: "*", site: e.site}];
+ }
+
+ if (seen.indexOf(objectKey) === -1) {
+ pluginSites[e.site].push({mime: "*", site: e.site, originSite: e.originSite});
+ seen.push(objectKey);
+ }
+
+ pluginSites[e.site].push(e, {mime: e.mime, site: e.site});
+ seen.push(key);
+ }
+ if (seen.length) {
+ noscriptOverlay.menuPluginSites = [];
+ i = 0;
+ for (let site in pluginSites) {
+ menu.appendChild(document.createElement("menuseparator"));
+ for (let e of pluginSites[site]) {
+ let where = e.site;
+ if (e.originSite) where += " (" + e.originSite + ")";
+ let mime = e.mime;
+
+ let node = document.createElement("menuitem");
+ node.setAttribute("label", this.getString("allowTemp", [ns.mimeEssentials(mime) + "@" + where]));
+ node.setAttribute("tooltiptext", mime + "@" + where);
+ node.setAttribute("oncommand", "noscriptOverlay.allowObjectSite(" + i + ")");
+ node.setAttribute("class", "menuitem-iconic noscript-temp noscript-cmd noscript-allow");
+ if(mime != "*")
+ node.style.listStyleImage = node.style.listStyleImage = ns.cssMimeIcon(mime, 16);
+
+ menu.appendChild(node);
+ noscriptOverlay.menuPluginSites[i++] = e;
+ }
+ }
+ }
+ menu.parentNode.hidden = false;
+ }
+ },
+
+ allowPage: function(permanent, justTell, sites) {
+ const ns = this.ns;
+ sites = sites || this.getSites();
+ const unknown = [];
+ const level = ns.getPref("allowPageLevel", 0) || ns.preferredSiteLevel;
+ const trusted = ns.jsPolicySites;
+ const tempToPerm = permanent === -1;
+
+ const topSite = sites.topSite;
+ const cascade = topSite && ns.cascadePermissions;
+ let all = sites.all;
+
+ for (let j = all.length; j-- > 0;) {
+ let site = all[j];
+ if (cascade && topSite !== site) continue;
+ if (tempToPerm) {
+ site = trusted.matches(site);
+ if (!(site && ns.isTemp(site)) || ns.isUntrusted(site)) continue;
+ } else {
+ site = ns.getQuickSite(site, level);
+ if (ns.isJSEnabled(site) || ns.isUntrusted(site)) continue;
+ }
+ unknown.push(site);
+ }
+ if (!justTell) {
+ if (unknown.length) {
+ var browser = this.currentBrowser;
+ ns.setExpando(browser, "allowPageURL", this.currentURL);
+ this.safeAllow(unknown, true, !permanent);
+ }
+ }
+ return unknown;
+ },
+
+ tempToPerm: function(justTell, sites) {
+ return this.allowPage(-1, justTell, sites);
+ },
+
+ allowObject: function(i) {
+ if(this.menuPluginExtras && this.menuPluginExtras[i]) {
+ var e = this.menuPluginExtras[i];
+ if (this.ns.confirmEnableObject(window, e)) {
+ this.allowObjectURL(e.url, e.mime, e.originSite);
+ }
+ }
+ },
+
+ allowObjectSite: function(i) {
+ if(this.menuPluginSites && this.menuPluginSites[i]) {
+ this.allowObjectURL(this.menuPluginSites[i].site, this.menuPluginSites[i].mime, this.menuPluginSites[i].originSite);
+ }
+ },
+ allowObjectURL: function(url, mime, originSite) {
+ this.ns.allowObject(url, mime, originSite);
+ this.ns.reloadAllowedObjects(this.currentBrowser, mime);
+ },
+
+ normalizeMenu: function(menu, hideParentIfEmpty) {
+ if (!menu) return;
+ var prev = null;
+ var wasSep = true;
+ var haveMenu = false;
+ for (var i = menu.firstChild; i; i = i.nextSibling) {
+ if (!i.hidden) {
+ let isSep = i.nodeName == "menuseparator";
+ if (isSep && wasSep) {
+ i.hidden = true;
+ } else {
+ haveMenu = haveMenu || !isSep;
+ prev = i;
+ wasSep = isSep;
+ }
+ }
+ }
+
+ if (prev && wasSep) {
+ prev.hidden = true;
+ }
+ if (hideParentIfEmpty && menu.parentNode) {
+ menu.parentNode.hidden = !haveMenu;
+ }
+ }
+,
+ getBrowserDoc: function(browser) {
+ return browser && browser.contentWindow && browser.contentWindow.document || null;
+ }
+,
+ revokeTemp: function() {
+ this.ns.safeCapsOp(function(ns) {
+ ns.eraseTemp();
+ noscriptOverlay.syncUI();
+ }, this.ns.getPref("autoReload.allTabsOnPageAction", true) ? this.ns.RELOAD_ALL : this.ns.RELOAD_CURRENT);
+ }
+,
+ menuCmd: function(event) {
+ if (event.shiftKey) return; // site info
+ const ns = this.ns;
+ const menuItem = event.target;
+ var site = null;
+ var reloadPolicy = ns.RELOAD_ALL;
+ var cl = menuItem.getAttribute("class") || "";
+ var cmd = cl.match(/-(forbid|allow|distrust)\b/);
+ if (!(cmd && (cmd = cmd[1]))) return;
+ var enabled = cmd == "allow";
+ var temp = /-temp\b/.test(cl);
+ if (/-glb\b/.test(cl)) {
+ // global allow/forbid
+ if (enabled && ns.getPref("globalwarning", true) &&
+ !Services.prompt.confirm(window, this.getString("global.warning.title"),
+ this.getString("global.warning.text"))
+ ) return;
+ } else {
+ // local allow/forbid
+ site = menuItem.getAttribute("statustext");
+ if (!site) return;
+
+ if (cmd == "distrust") {
+ ns.setUntrusted(site, true);
+ }
+
+ if (menuItem.getAttribute("closemenu") === "none") {
+ menuItem.removeAttribute("statustext"); // prevent double-firing
+ // sticky UI feedback
+ if (this._currentPopup) {
+ this._currentPopup.setAttribute("disabled", "true");
+ }
+ this._reloadDirty = true;
+ reloadPolicy = this.liveReload ? ns.RELOAD_CURRENT : ns.RELOAD_NO;
+ }
+
+ if (enabled && /\ballow-from\b/.test(cl)) {
+
+ ns.allowObject(site, "*");
+ if (ns.isJSEnabled(site)) return;
+ reloadPolicy = ns.RELOAD_NO;
+ }
+
+ }
+ this.safeAllow(site, enabled, temp, reloadPolicy);
+ },
+
+ safeAllow: function(site, enabled, temp, reloadPolicy) {
+ let ns = noscriptOverlay.ns;
+ let allowTemp = enabled && temp;
+ window.clearInterval(noscriptOverlay._savePrefsTimeout);
+ let op = ns => {
+ if (site) {
+ ns.setTemp(site, allowTemp);
+ ns.setJSEnabled(site, enabled, false, ns.mustCascadeTrust(site, temp));
+ } else {
+ ns.jsEnabled = enabled;
+ }
+ noscriptOverlay._syncUINow();
+ };
+ if (reloadPolicy === ns.RELOAD_NO) {
+ op(ns);
+ } else {
+ ns.safeCapsOp(op, reloadPolicy, allowTemp);
+ }
+ },
+
+ _savePrefsTimeout: 0,
+ savePrefs: function(now) {
+ if (now) {
+ noscriptOverlay.ns.savePrefs();
+ return;
+ }
+
+ if (this._savePrefsTimeout) {
+ window.clearTimeout(this._savePrefsTimeout);
+ }
+ window.setTimeout(arguments.callee, 5000, true);
+ },
+
+
+ get statusIcon() {
+ var statusIcon = $("noscript-statusIcon") || $("noscript-tbb");
+ if (!statusIcon) {
+ return this._fakeIcon || (this._fakeIcon = document.createElement("toolbar-button")); // ugly hack for Firefox 57
+ }
+ delete this.statusIcon;
+ return (this.statusIcon = statusIcon);
+ },
+
+ getIcon: function(node) {
+ if (typeof(node) != "object") node = $(node);
+ return node.ownerDocument.defaultView.getComputedStyle(node, null)
+ .listStyleImage.replace(/.*url\s*\(\s*"?([^"\s\)]*).*/g, '$1');
+ },
+
+ getStatusClass: function(lev, inactive, currentClass) {
+ return "noscript-" + (inactive ? "inactive-" : "") + lev;
+ },
+ updateStatusClass: function(node, className) {
+ if (!className) className = this.statusIcon.className.replace(/.*(\bnoscript-\S*(?:yes|no|glb|prt|emb|yu|untrusted)).*/, "$1");
+ node.className = (node.className.replace(/\bnoscript-\S*(?:yes|no|glb|prt|emb|yu|untrusted)\b/g, "") + " " + className).replace(/\s{2,}/g, " ");
+ }
+,
+ _syncTimeout: 0,
+ syncUI(forceReal = false) {
+ if (forceReal) { // we entirely skip on startup...
+ this.syncUI = this._syncUIReal;
+ this.syncUI();
+ }
+ },
+ _syncUIReal: function(browser) {
+ if (!browser) browser = this.currentBrowser;
+ // ... and cap to 400ms
+ if (this._syncTimeout) return;
+ this._syncTimeout = window.setTimeout(() => {
+ this._syncTimeout = 0;
+ if (this.currentBrowser === browser &&
+ typeof noscriptOverlay !== "undefined" && this === noscriptOverlay) {
+ this._syncUINow();
+ }
+ }, 400);
+ },
+
+
+ syncXssWidget: function(widget) {
+ if (!widget) widget = $("noscript-statusXss");
+ if (!widget) return;
+
+ const ns = this.ns;
+ var unsafeRequest = ns.requestWatchdog.getUnsafeRequest(this.currentBrowser);
+ if (unsafeRequest && !unsafeRequest.issued) {
+ widget.removeAttribute("hidden");
+ widget.setAttribute("tooltiptext", "XSS [" +
+ ns.getSite(unsafeRequest.origin) + "]->[" +
+ ns.getSite(unsafeRequest.URI.spec) + "]");
+ return;
+ }
+ widget.setAttribute("hidden", "true");
+ },
+
+ syncRedirectWidget: function() {
+ var widget = $("noscript-statusRedirect");
+ if (!widget) return;
+ var info = this.getMetaRefreshInfo();
+ if (!info) {
+ widget.setAttribute("hidden", true);
+ return;
+ }
+ widget.removeAttribute("hidden");
+ widget.setAttribute("tooltiptext",
+ this.getString("metaRefresh.notify.follow") + " [" + info.uri + "]");
+ },
+
+ get stickyUI() {
+ var ui = $("noscript-sticky-ui");
+ if (ui == null) return null;
+ delete this.stickyUI;
+ if (!ui.openPopup) {
+ ui = null;
+ } else {
+ ui.hidden = false;
+ }
+ return this.stickyUI = ui;
+ },
+
+ get useStickyUI() {
+ return this.ns.getPref("stickyUI");
+ },
+
+ hoverUI: true,
+
+ showUI: function(toggle) {
+ var popup = null;
+
+ var useSticky = this.stickyUI && this.ns.getPref("stickyUI.onKeyboard");
+
+ popup = (useSticky && (popup = this.stickyUI)) ||
+ $("noscript-status-popup");
+ if (!this.isOpenOrJustClosed(popup)) {
+ popup._context = !useSticky;
+ popup.showPopup(null, -1, -1, "context", null, null);
+ } else if (toggle) {
+ popup.hidePopup();
+ }
+ }
+
+,
+ get notificationPos() {
+ return this.notifyBottom ? "bottom" : "top";
+ },
+ get altNotificationPos() {
+ return this.notificationPos == "top" ? "bottom" : "top";
+ }
+,
+ getNotificationBox: function(pos, browser) {
+ // this won't get any notification for Fennec, which is good.
+
+ var gb = getBrowser();
+
+ if (!(gb && gb.getNotificationBox)) return null; // SeaMonkey, Fennec...
+
+ browser = browser || gb.selectedBrowser;
+ if (!pos) pos = this.notificationPos;
+
+ var nb = gb.getNotificationBox(browser);
+
+ if (nb)
+ this.patchNotificationBox(nb, pos);
+
+ return nb;
+ },
+
+ patchNotificationBox: function(nb, pos) {
+ if (nb._noscriptPatched) return;
+
+ nb._noscriptPatched = true;
+
+ nb.__defineGetter__("_closedNotification", function() {
+ var cn = this.__ns__closedNotification;
+ return (cn && cn.parentNode ? cn : null);
+ });
+
+ nb.__defineSetter__("_closedNotification", function(cn) {
+ this.__ns__closedNotification = cn;
+ });
+
+ nb._dom_ = {};
+ const METHODS = this.notificationBoxPatch;
+ for (let m in METHODS) {
+ nb._dom_[m] = nb[m];
+ nb[m] = METHODS[m];
+ }
+
+ var stacks = nb.getElementsByTagName("stack");
+ var stack = null;
+ for (var j = stacks.length; j-- > 0;) {
+ if (stacks[j].getAttribute("class") == "noscript-bottom-notify") {
+ stack = stacks[j];
+ break;
+ }
+ }
+ if (!stack) {
+ stack = nb.ownerDocument.createElement("stack");
+ stack.setAttribute("class", "noscript-bottom-notify");
+ nb.appendChild(stack);
+ nb.appendChild = function(node) {
+ this.__proto__.appendChild.call(this, node);
+ this.__proto__.appendChild.call(this, stack);
+ }
+ nb._showNotification = function(notification, slideIn, skipAnim) {
+ if (!slideIn) stack.removeAttribute("height");
+ this.__proto__._showNotification.apply(this, arguments);
+ }
+ }
+ nb._noscriptBottomStack_ = stack;
+ },
+
+ notificationBoxPatch: {
+ insertBefore: function(n, ref) {
+ if (n.localName == "notification" &&
+ n.getAttribute("value") == "noscript"
+ && noscriptOverlay.notificationPos == "bottom") {
+ const stack = this._noscriptBottomStack_;
+
+ stack.insertBefore(n, null);
+ var hbox = n.ownerDocument.getAnonymousElementByAttribute(
+ n, "class", "notification-inner outset");
+ if (hbox) {
+ var style = hbox.ownerDocument.defaultView.getComputedStyle(hbox, null);
+ var borderProps = ['color', 'style', 'width'];
+ var cssProp, jsProp, tmpVal;
+ for (var p = borderProps.length; p-- > 0;) {
+ cssProp = borderProps[p];
+ jsProp = cssProp[0].toUpperCase() + cssProp.substring(1);
+ tmpVal = style.getPropertyValue("border-bottom-" + cssProp);
+ hbox.style["borderBottom" + jsProp] = style.getPropertyValue("border-top-" + cssProp);
+ hbox.style["borderTop" + jsProp] = tmpVal;
+ }
+ }
+ return n;
+ }
+ if(ref && ref.parentNode != this) {
+ var priority = ref.priority;
+ ref = null;
+ var notifications = this.allNotifications;
+ var j = notifications.length;
+ while (j-- > 0) {
+ if ((ref = notifications[j]).priority < priority && ref.parentNode == this)
+ break;
+ }
+ if(j < 0) ref = null;
+ }
+ return this._dom_.insertBefore.apply(this, [n, ref]);
+ },
+ removeChild: function(n) {
+ return (n.parentNode == this) ? this._dom_.removeChild.apply(this, arguments) : n.parentNode && n.parentNode.removeChild(n);
+ }
+ },
+
+ getNsNotification: function(widget) {
+ if (widget == null) return null;
+ if (widget.localName == "notificationbox") return widget.getNotificationWithValue("noscript");
+ return this.isNsNotification(widget) && widget || null;
+ },
+ isNsNotification: function(widget) {
+ return widget && widget.getAttribute("value") == "noscript" || widget.popup == "noscript-notify-popup";
+ },
+
+
+ notificationShow: function(label, icon, canAppend) {
+ var box = this.getNotificationBox();
+ if (box == null) return false;
+
+ var pos = this.notificationPos;
+
+ const gb = getBrowser();
+ const browser = gb.selectedBrowser;
+
+ const popup = "noscript-notify-popup";
+
+ var widget = this.getNsNotification(box);
+ if (widget) {
+ if (widget.localName == "notification") {
+ widget.label = label;
+ widget.image = icon;
+ } else {
+ widget.text = label;
+ widget.image = icon;
+ if (canAppend) widget.removeAttribute("hidden");
+ }
+
+ } else {
+
+ if (!canAppend) return false;
+
+ var buttonLabel, buttonAccesskey;
+
+ const refWidget = $("noscript-options-menuitem");
+ buttonLabel = refWidget.getAttribute("label");
+ buttonAccesskey = refWidget.getAttribute("accesskey");
+
+ widget = box.appendNotification(label, "noscript", icon, box.PRIORITY_WARNING_MEDIUM,
+ [ {label: buttonLabel, accessKey: buttonAccesskey, popup: popup} ]);
+ }
+ if (!widget) return false;
+
+ const delay = this.notifyHide && this.notifyHideDelay || 0;
+ if (delay) {
+ if (this.notifyHideTimeout) window.clearTimeout(this.notifyHideTimeout);
+ this.notifyHideTimeout = window.setTimeout(
+ function() {
+ if (browser == gb.selectedBrowser) {
+ if ($(popup) == noscriptOverlay._currentPopup) {
+ noscriptOverlay.notifyHideTimeout = window.setTimeout(arguments.callee, 1000);
+ return;
+ }
+ noscriptOverlay.notificationHide(browser);
+ }
+ },
+ 1000 * delay);
+ }
+ return true;
+ },
+
+ getAltNotificationBox: function(browser, value, canAppend) {
+
+ const box = (("Browser" in window) && Browser.getNotificationBox)
+ ? Browser.getNotificationBox()
+ : this.getNotificationBox(this.altNotificationPos, browser);
+ if (canAppend || (box &&
+ box.getNotificationWithValue &&
+ box.getNotificationWithValue(value))) return null;
+ return box;
+ },
+
+ notifyXSSOnLoad: function(requestInfo) {
+ requestInfo.browser.addEventListener("DOMContentLoaded", function(ev) {
+ requestInfo.browser.removeEventListener(ev.type, arguments.callee, false);
+ if (requestInfo.unsafeRequest && requestInfo.unsafeRequest.issued) return;
+ noscriptOverlay.notifyXSS(requestInfo);
+ }, false);
+ },
+
+ notifyXSS: function(requestInfo) {
+ const notificationValue = "noscript-xss-notification";
+ const box = this.getAltNotificationBox(requestInfo.browser, notificationValue);
+ if (!box) return;
+
+ var origin = this.ns.getSite(requestInfo.unsafeRequest.origin);
+ origin = (origin && "[" + origin + "]") || this.getString("untrustedOrigin");
+ var label = this.getString("xss.notify.generic", [origin]);
+ var icon = this.getIcon("noscript-statusXss");
+
+ const refWidget = $("noscript-options-menuitem");
+ var buttonLabel = refWidget.getAttribute("label");
+ var buttonAccesskey = refWidget.getAttribute("accesskey");
+ var popup = $("noscript-xss-popup");
+ if ("Browser" in window) popup.className = "noscript-menu";
+
+ box.appendNotification(
+ label,
+ notificationValue,
+ icon,
+ box.PRIORITY_WARNING_HIGH,
+ [{
+ label: buttonLabel,
+ accessKey: buttonAccesskey,
+ popup: popup.id
+ }]
+ );
+ },
+
+ notifyMetaRefresh: function(info) {
+ var browser = info.browser;
+ if (!browser) return;
+
+ const notificationValue = "noscript-metaRefresh-notification";
+ const box = this.getAltNotificationBox(browser, notificationValue);
+ var notification = null;
+
+ if (box && this.ns.getPref("forbidMetaRefresh.notify", true)) {
+ var urlForLabel = info.uri;
+ if (urlForLabel.length > 30) urlForLabel = urlForLabel.substring(0, 30) + "...";
+ var label = this.getString("metaRefresh.notify", [urlForLabel, info.timeout])
+ var icon = this.getIcon("noscript-statusRedirect");
+
+ notification = box.appendNotification(
+ label,
+ notificationValue,
+ icon,
+ box.PRIORITY_INFO_HIGH,
+ [{
+ label: this.getString("metaRefresh.notify.follow"),
+ accessKey: this.getString("metaRefresh.notify.follow.accessKey"),
+ callback: function(notification, buttonInfo) {
+ noscriptOverlay.ns.doFollowMetaRefresh(info);
+ }
+ }]
+ );
+
+ browser.addEventListener("beforeunload", function(ev) {
+ if (ev.originalTarget === info.document || ev.originalTarget === browser) {
+ browser.removeEventListener(ev.type, arguments.callee, false);
+ if (notification && notification == box.currentNotification) {
+ box.removeCurrentNotification();
+ } else {
+ noscriptOverlay.ns.doBlockMetaRefresh(info);
+ }
+ info = browser = null;
+ }
+ }, false);
+ }
+
+ this.setMetaRefreshInfo(info, browser);
+ },
+
+ setMetaRefreshInfo: function(value, browser) {
+ return this.ns.setExpando(browser || this.currentBrowser, "metaRefreshInfo", value);
+ },
+ getMetaRefreshInfo: function(browser) {
+ return this.ns.getExpando(browser || this.currentBrowser, "metaRefreshInfo");
+ },
+ followMetaRefresh: function(event) {
+ this.ns.doFollowMetaRefresh(this.getMetaRefreshInfo(), event.shiftKey);
+ },
+
+ get supportsNotifications() {
+ delete this.supportsNotification;
+ return this.supportsNotification = !!document.getElementsByTagName("notificationbox").length;
+ },
+
+ notifyABE: function(info) {
+ var browser = info.browser;
+
+ const notificationValue = "noscript-abe-notification";
+ const box = this.getAltNotificationBox(browser, notificationValue);
+
+ var label = this.ns.Strings.wrap(this.getString("ABE.notify", [info.request, info.lastRule.destinations, info.lastPredicate]));
+
+ if (!(box && box.appendNotification)) {
+ if (!this.supportsNotifications && this.ns.getPref("ABE.legacyPrompt")) {
+ let prompter = Services.prompt;
+ if (prompter.confirmEx(
+ window,
+ "NoScript - Application Boundary Enforcer",
+ label,
+ prompter.BUTTON_POS_0 * prompter.BUTTON_TITLE_IS_STRING |
+ prompter.BUTTON_POS_1 * prompter.BUTTON_TITLE_OK,
+ this.getString("notify.options").replace(this.getString("notify.accessKey"), "&$&"),
+ "", "", null, { value: false }
+ ) == 0) noscriptUtil.openABEOptions(info);
+ }
+ return false;
+ }
+ var notification = null;
+
+
+ var icon = this.getIcon("noscript-abe-opts");
+
+ notification = box.appendNotification(
+ label,
+ notificationValue,
+ icon,
+ box.PRIORITY_WARNING_HIGH,
+ [
+ this.fennec
+ ? {
+ label: this.getString("disable", ["ABE"]),
+ accessKey: this.getString("disable.accessKey"),
+ callback: function(notification, buttonInfo) {
+ noscriptOverlay.ns.setPref("ABE.enabled", false);
+ }
+ }
+ : {
+ label: this.getString("notify.options"),
+ accessKey: this.getString("notify.accessKey"),
+ callback: function(notification, buttonInfo) {
+ noscriptUtil.openABEOptions(info);
+ }
+ }]
+ );
+ browser.addEventListener("beforeunload", function(ev) {
+ if (ev.originalTarget == info.document || ev.originalTarget == browser) {
+ browser.removeEventListener(ev.type, arguments.callee, false);
+ if (notification && notification == box.currentNotification) {
+ box.removeCurrentNotification();
+ }
+ info = browser = notification = null;
+ }
+ }, false);
+
+ return true;
+ },
+
+
+ unsafeReload: function() {
+ const browser = this.currentBrowser;
+ const ns = this.ns;
+ const rw = ns.requestWatchdog;
+ let unsafeRequest = rw.getUnsafeRequest(browser);
+ let removeNotification = () => getBrowser().getNotificationBox(browser).removeAllNotifications(true);
+ if (!unsafeRequest) {
+ removeNotification();
+ return;
+ }
+
+ let method = (unsafeRequest.postData ? "POST" : "GET");
+ var msg = noscriptUtil.getString("unsafeReload.warning",
+ [ method,
+ ns.siteUtils.crop(unsafeRequest.URI.spec),
+ ns.siteUtils.crop(unsafeRequest.origin || unsafeRequest.referrer && unsafeRequest.referrer.spec || '?')
+ ]);
+ msg += noscriptUtil.getString("confirm");
+ if (noscriptUtil.confirm(msg, "confirmUnsafeReload")) {
+ try {
+ getBrowser().getNotificationBox(browser).removeAllNotifications(true);
+ } catch(e) {}
+ rw.unsafeReload(browser, true);
+ }
+ },
+
+ notificationHide: function(browser) { // Modified by Higmmer
+ var box = this.getNotificationBox(null, browser);
+ var widget = this.getNsNotification(box); // Modified by Higmmer
+ if (widget) {
+ if (box._timer) clearTimeout(box._timer);
+ widget.parentNode.removeAttribute("height");
+ if (widget.close) {
+ if (box.currentNotification == widget) {
+ box.currentNotification = null;
+ }
+ widget.close();
+ box.style.width = "";
+ window.setTimeout(function() {
+ box.style.width = "100%"
+ window.setTimeout(function() {
+ box.style.width = "";
+ }, 10);
+ }, 10);
+ } else {
+ widget.setAttribute("hidden", "true");
+ }
+ return true;
+ }
+ return false;
+ },
+
+ get _oldStylePartial() {
+ delete this._oldStylePartial;
+ return this._oldStylePartial = this.ns.getPref("oldStylePartial", false);
+ },
+
+ _syncUINow: function() {
+
+ if (this._syncTimeout) {
+ window.clearTimeout(this._syncTimeout);
+ this._syncTimeout = 0;
+ }
+
+ const ns = this.ns;
+ const global = ns.jsEnabled;
+ const cascadePermissions = ns.cascadePermissions;
+ const globalHttps = ns.globalHttpsWhitelist;
+ const jsPSs = ns.jsPolicySites;
+ const untrustedSites = ns.untrustedSites;
+
+
+ this.syncRedirectWidget();
+
+ const sites = this.getSites();
+
+ const oldStylePartial = this._oldStylePartial;
+
+ if (this._currentPopup && this._currentPopup.getAttribute("sticky") == "true" && this._currentPopup.state == "open") {
+ this.prepareMenu(this._currentPopup, sites);
+ }
+
+ var lev;
+ var totalScripts = sites.scriptCount;
+ var totalPlugins = sites.pluginCount;
+ var totalAnnoyances = totalScripts + totalPlugins;
+ var notificationNeeded = false;
+
+ var allowedSites = [];
+ var activeSites = sites.pluginSites.concat(sites.docSites);
+ var allowed = 0;
+ var untrusted = 0;
+ var active = 0;
+ var blockedObjects = 0;
+ var total = 0;
+
+ var topTrusted = false;
+ var topUntrusted = false;
+
+ let win = content;
+
+ if (global && !ns.alwaysBlockUntrustedContent) {
+ lev = "glb";
+ } else {
+
+ let pes = sites.pluginExtras;
+ if (pes) {
+ for (let j = pes.length; j-- > 0;) {
+ let pe = pes[j];
+ for (let k = pe.length; k-- > 0;) {
+ let e = pe[k];
+
+ if (e &&
+ // TODO: e10s removal check
+ /*
+ (e.placeholder && (e.placeholder.parentNode || !ns.isAllowedObject(e.url, e.mime, e.site, e.originSite))
+ || e.document)
+ */
+ !ns.isAllowedObject(e.url, e.mime, e.site, e.originSite)
+ ) blockedObjects++;
+ }
+ }
+ }
+ let all = sites.all;
+ let s = all.length;
+ total = s + blockedObjects;
+ while (s-- > 0) {
+ let url = all[s];
+ let isUntrusted = untrustedSites.matches(url);
+ let site = !isUntrusted && (global || globalHttps && ns.isGlobalHttps(win, url) ? url : jsPSs.matches(url));
+
+ if (url == sites.topSite) {
+ if (site && (!ns.httpStarted || !(sites.docJSBlocked || sites.cspBlocked))) topTrusted = true;
+ else {
+ site = null;
+ if (isUntrusted) topUntrusted = true;
+ }
+ }
+
+ if (site) {
+ if (oldStylePartial || activeSites.indexOf(url) > -1) active++;
+ if (ns.isMandatory(site) || allowedSites.indexOf(site) > -1) {
+ total--;
+ } else {
+ allowedSites.push(site);
+ }
+ } else {
+ if (isUntrusted) untrusted++;
+ else if(!notificationNeeded && url != "about:blank") {
+ notificationNeeded = true;
+ }
+ }
+ }
+
+ if (!untrusted && sites.pluginSites.some(untrustedSites.matches, untrustedSites)) {
+ untrusted = 1;
+ }
+
+ allowed = allowedSites.length;
+ lev = (allowed === total && all.length > 0 && !untrusted) ? (global ? "glb" : "yes")
+ : (allowed === 0 || active === 0) ? (global
+ ? "untrusted-glb" :
+ topUntrusted
+ ? "untrusted" :
+ blockedObjects ? "no-emb" : "no")
+ : (untrusted > 0 && !notificationNeeded
+ ? (blockedObjects ? (global ? "glb-emb" : "yu-emb") : global ? "yu-glb" : "yu")
+ : topTrusted
+ ? allowed === total - blockedObjects
+ ? (global ? "glb-emb" : "emb")
+ : (cascadePermissions ? "yes" : "prt")
+ : cascadePermissions || ns.restrictSubdocScripting
+ ? "no"
+ : "subprt"
+ );
+ notificationNeeded = notificationNeeded &&
+ (totalAnnoyances > 0 &&
+ (!cascadePermissions || !topTrusted || blockedObjects)
+ );
+ }
+
+ let message = this.getString(
+ "allowed." +
+ (lev == "yu" || lev == "subprt" || lev == "emb" || lev == "yu-emb"
+ ? "prt"
+ : (lev == "untrusted" || lev == "no-emb") ? "no" : lev)
+ );
+
+ let shortMessage = message.replace("JavaScript", "JS");
+
+ if (notificationNeeded && active)
+ message += ", " + allowed + "/" + total + " (" + allowedSites.join(", ") + ")";
+
+ let countsMessage = " | <SCRIPT>: " + totalScripts + " | <OBJECT>: " + totalPlugins;
+ message += countsMessage;
+ shortMessage += countsMessage;
+
+
+ const className = this.getStatusClass(lev, !(totalScripts || topUntrusted) /* inactive */ );
+ let widget = this.statusIcon;
+ const hoverUI = this.hoverUI;
+ for (let wg = widget; wg;) {
+ if (hoverUI) wg.removeAttribute("tooltiptext");
+ else wg.setAttribute("tooltiptext", shortMessage);
+ this.updateStatusClass(wg, className);
+
+ if (wg.id === "noscript-tbb") break;
+ wg = $("noscript-tbb");
+ }
+
+ if (notificationNeeded) { // notifications
+
+ if (this.notify) {
+ this.notificationShow(message,
+ this.getIcon(widget),
+ !(ns.getExpando(win, "messageShown") && this.notifyHidePermanent));
+ ns.setExpando(win, "messageShown", true);
+ } else {
+ this.notificationHide();
+ }
+ if (!ns.getExpando(this.currentBrowser, "soundPlayed")) {
+ ns.soundNotify(this.currentURL);
+ ns.setExpando(this.currentBrowser, "soundPlayed");
+ }
+ } else {
+ this.notificationHide();
+ message = shortMessage = "";
+ }
+
+ widget = $("noscript-statusLabelValue");
+ if (widget) {
+ widget.setAttribute("value", shortMessage);
+ widget.parentNode.style.display = message ? "" : "none";
+ }
+
+ widget = $("noscript-tbb-revoke-temp");
+ if (widget) {
+ if (ns.gTempSites.sitesString || ns.tempSites.sitesString || ns.objectWhitelistLen || ns.clearClickHandler && ns.clearClickHandler.whitelistLen) {
+ widget.removeAttribute("disabled");
+ } else {
+ widget.setAttribute("disabled", "true");
+ }
+ }
+
+ widget = $("noscript-tbb-temp-page");
+ if (widget) {
+ if (allowed < total) {
+ widget.removeAttribute("disabled");
+ } else {
+ widget.setAttribute("disabled", "true");
+ }
+ }
+ }
+,
+ notifyHideTimeout: 0,
+ liveReload: false,
+
+ initContentWindow: function(window) {
+ window.addEventListener("pagehide", this.listeners.onPageHide, true);
+ },
+
+ presetChanged: function(menulist) {
+ this.ns.applyPreset(menulist.selectedItem.value);
+ },
+
+ install: function() {
+ // this.ns.dump("*** OVERLAY INSTALL ***\n");
+ this.ns.setPref("badInstall", false);
+ window.addEventListener("load", this.listeners.onLoad, false);
+ },
+
+ dispose: function() {
+ for (var bb = this.browsers, j = bb.length; j-- > 0;) if (bb[j]) {
+ this.ns.cleanupBrowser(bb[j]);
+ }
+ },
+
+ observer: {
+ ns: noscriptUtil.service,
+ QueryInterface: XPCOMUtils.generateQI([
+ Ci.nsIObserver,
+ Ci.nsISupportsWeakReference])
+ ,
+ observe: function(subject, topic, data) {
+ if (subject == this.ns.caps) {
+ noscriptOverlay.syncUI();
+ return;
+ }
+
+ switch(topic) {
+ case "noscript:sync-ui":
+ noscriptOverlay.syncUI(subject);
+ return;
+ case "browser:purge-session-history":
+ noscriptOverlay.ns.purgeRecent();
+ return;
+ }
+
+ // prefs
+
+ switch (data) {
+ case "preset":
+ if (data == "off") noscriptOverlay.statusIcon.setAttribute("hidden", "true");
+ else noscriptOverlay.statusIcon.removeAttribute("hidden");
+ noscriptOverlay.syncUI();
+ break;
+ case "statusIcon": case "statusLabel" :
+ window.setTimeout(function() {
+ var widget =$("noscript-" + data);
+ if (widget) {
+ widget.setAttribute("hidden", !noscriptOverlay.ns.getPref(data))
+ }
+ }, 0);
+ break;
+
+ case "notify":
+ case "notify.bottom":
+ noscriptOverlay[data.replace(/\.b/, 'B')] = this.ns.getPref(data);
+ if (this._registered) noscriptOverlay.notificationHide();
+ break;
+
+ case "keys.ui":
+ case "keys.toggle":
+ case "keys.tempAllowPage":
+ case "keys.revokeTemp":
+ noscriptOverlay.shortcutKeys.setup(data.replace(/^keys\./, ""), this.ns.getPref(data, ""));
+ break;
+
+ case "notify.hidePermanent":
+ case "notify.hideDelay":
+ case "notify.hide":
+ noscriptOverlay[data.replace(/\.h/, 'H')] = this.ns.getPref(data);
+ break;
+
+ case "stickyUI.liveReload":
+ noscriptOverlay.liveReload = this.ns.getPref(data);
+ break;
+
+ case "hoverUI":
+ case "toolbarToggle":
+ noscriptOverlay[data] = this.ns.getPref(data);
+ noscriptOverlay.initPopups();
+
+ break;
+
+ }
+ },
+ _registered: false,
+ _topics: ["noscript:sync-ui", "browser:purge-session-history"],
+ register: function() {
+ const ns = this.ns;
+ const os = ns.os;
+ for (let t of this._topics){
+ os.addObserver(this, t, true);
+ }
+ ns.prefs.addObserver("", this, true);
+ ns.caps.addObserver("", this, true);
+ const initPrefs = [
+ "statusIcon", "statusLabel", "preset",
+ "keys.ui", "keys.toggle", "keys.tempAllowPage", "keys.revokeTemp",
+ "notify", "notify.bottom",
+ "notify.hide", "notify.hidePermanent", "notify.hideDelay",
+ "stickyUI.liveReload",
+ "hoverUI"
+ ];
+ for (let p of initPrefs) {
+ this.observe(null, null, p);
+ }
+ this._registered = true;
+ },
+ remove: function() {
+ const ns = this.ns;
+ const os = ns.os;
+ for (let t of this._topics){
+ try {
+ os.removeObserver(this, t);
+ } catch (e) {}
+ }
+ try {
+ ns.prefs.removeObserver("", this);
+ } catch (e) {}
+ try {
+ ns.caps.removeObserver("", this);
+ } catch (e) {}
+ }
+ },
+
+
+
+
+
+ shortcutKeys: {
+
+ execute: function(cmd, ev) {
+ switch (cmd) {
+ case 'toggle':
+ noscriptOverlay.toggleCurrentPage(noscriptOverlay.ns.preferredSiteLevel);
+ break;
+ case 'tempAllowPage':
+ noscriptOverlay.allowPage();
+ break;
+ case 'revokeTemp':
+ noscriptOverlay.revokeTemp();
+ break;
+ case 'ui':
+ noscriptOverlay.showUI(true);
+ break;
+ }
+ },
+
+ keys: {},
+ setup: function(name, values) {
+ values = values.toLowerCase().replace(/^\s*(.*?)\s*$/g, "$1").split(/\s+/);
+ var vpos = values.length;
+ if (vpos) {
+
+ var mods = { shiftKey: false, altKey: false, metaKey: false, ctrlKey: false };
+
+ var keyVal = values[--vpos];
+ for (var value; vpos-- > 0;) {
+ value = values[vpos] + "Key";
+ if (value in mods) {
+ mods[value] = true;
+ }
+ }
+
+ var key = { modifiers: mods, charCode: 0, keyCode: 0 };
+
+ if (keyVal.length > 3) {
+ var pos = keyVal.indexOf('.');
+ if (pos > 3) {
+ key.charCode = keyVal.charCodeAt(pos + 1) || 0;
+ keyVal = keyVal.substring(0, pos);
+ }
+ key.keyCode = KeyEvent["DOM_" + keyVal.toUpperCase()] || 0;
+ } else {
+ key.charCode = (key.modifiers.shiftKey ? keyVal.toUpperCase() : keyVal).charCodeAt(0) || 0;
+ }
+
+ this.keys[name] = key;
+ } else {
+ delete(this.keys[name]);
+ }
+ },
+
+ listener: function(ev) {
+ const binding = arguments.callee.binding;
+ const skk = binding.keys;
+ var cmd, k, p, sk, mods;
+ for (k in skk) {
+ cmd = k;
+ sk = skk[k];
+ var which = ev.which;
+
+ if (ev.charCode && ev.charCode == sk.charCode || ev.keyCode && ev.keyCode == sk.keyCode) {
+ mods = sk.modifiers;
+ for (p in mods) {
+ if (ev[p] != mods[p]) {
+ cmd = null;
+ break;
+ }
+ }
+
+
+ if (cmd) {
+ ev.preventDefault();
+ binding.execute(cmd, ev);
+ return;
+ }
+ }
+ }
+ },
+
+
+
+ register: function() {
+ this.listener.binding = this;
+ window.addEventListener("keypress", this.listener, true);
+ },
+ remove: function() {
+ window.removeEventListener("keypress", this.listener, true);
+ }
+ },
+
+ listeners: {
+
+ onTabClose: function(ev) {
+ try {
+ var browser = ev.target.linkedBrowser;
+ noscriptOverlay.ns.cleanupBrowser(browser);
+
+ var tabbrowser = getBrowser();
+ if (tabbrowser._browsers) tabbrowser._browsers = null;
+ if (tabbrowser.getNotificationBox) {
+ tabbrowser.getNotificationBox(browser).removeAllNotifications(true);
+ }
+ } catch(e) {}
+ },
+
+ webProgressListener: {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener]),
+ STATE_STOP: Ci.nsIWebProgressListener.STATE_STOP,
+ onLocationChange: function(aWebProgress, aRequest, aLocation) {
+ noscriptOverlay.syncUI();
+ },
+ onStatusChange: function() {},
+ onStateChange: function(aWebProgress, aRequest, stateFlags, status) {
+ if (aWebProgress.isTopLevel && stateFlags & this.STATE_STOP) {
+ noscriptOverlay.syncUI();
+ }
+ },
+ onSecurityChange: function() {},
+ onProgressChange: function() {}
+ },
+
+ onMainContextMenu: function(ev) { noscriptOverlay.prepareContextMenu(ev) },
+
+ _loaded: false,
+ onLoad: function(ev) {
+ if (this._loaded) return;
+ this._loaded = true;
+ let winType = document.documentElement.getAttribute("windowtype");
+ if (winType !== "navigator:browser") noscriptOverlay.ns.dom.browserWinType = winType;
+
+ window.removeEventListener("load", noscriptOverlay.listeners.onLoad, false);
+ window.addEventListener("unload", noscriptOverlay.listeners.onUnload, false);
+
+ try {
+ noscriptOverlay.listeners.setup();
+ noscriptOverlay.wrapBrowserAccess();
+ let hacks = noscriptOverlay.Hacks;
+ hacks.torButton();
+ hacks.allowLocalLinks();
+ setTimeout(() => {
+ noscriptOverlay.syncUI(true); // force real syncUI to start working
+ setTimeout(() => {
+ hacks.pdfDownload();
+ Services.scriptloader.loadSubScript("chrome://noscript/content/noscriptBM.js");
+ noscriptBM.init();
+ }, 1400);
+ }, 100);
+
+ noscriptOverlay.ns.clearClickHandler.chromeInstall(window);
+ } catch(e) {
+ let msg = "[NoScript] Error initializing new window " + e + "\n" + e.stack;
+ noscriptOverlay.ns.dump(msg);
+ }
+
+ },
+ onUnload: function() {
+ noscriptOverlay.ns.dump(`Unloading from ${window.location}`);
+ window.removeEventListener("unload", noscriptOverlay.listeners.onUnload, false);
+ noscriptOverlay.ns.clearClickHandler.chromeUninstall(window);
+ noscriptOverlay.listeners.teardown();
+ let openURI = noscriptOverlay.browserAccess._originalOpenURI;
+ if (openURI && window.browserDOMWindow) {
+ browserDOMWindow.wrappedJSObject.openURI = openURI;
+ }
+ noscriptOverlay.dispose();
+ if (window.noscriptBM) window.noscriptBM.dispose();
+ domCleanup();
+ delete window.noscriptOverlay;
+ delete window.noscriptUtil;
+ },
+
+ onAddonOptionsLoad: function(ev) {
+ var presetUI = $("noscript-preset-menu");
+ if (presetUI) {
+ const ns = noscriptOverlay.ns;
+ const preset = ns.getPref("preset");
+ var mi;
+ try {
+ for (var j = presetUI.itemCount; j-- > 0;) {
+ mi = presetUI.getItemAtIndex(j);
+ if (mi && mi.getAttribute("value") == preset) {
+ presetUI.selectedIndex = j;
+ break;
+ }
+ }
+ } catch(e) { ns.log(e) }
+ }
+ },
+
+ onActivation: function() {
+ noscriptOverlay.syncUI();
+ },
+
+ customizableUIListener: {
+ onWidgetAfterDOMChange: function(aWidget) {
+ for (let b of ['noscript-tbb', 'noscript-statusLabel']) {
+ if(b == aWidget.id) {
+ window.setTimeout(function() { noscriptOverlay.initPopups(); }, 0);
+ return;
+ }
+ }
+ }
+ },
+
+ setup: function(delayed) {
+ var b = getBrowser();
+ if (!b) {
+ setTimeout(() => noscriptOverlay.listeners.setup(true), 100);
+ return;
+ }
+ var tabs = $("tabs") || b.tabContainer;
+ if (tabs) {
+ tabs.addEventListener("TabClose", this.onTabClose, false);
+ }
+
+ let context = $("contentAreaContextMenu");
+ if (!context) return; // not a browser window?
+
+ context.addEventListener("popupshowing", this.onMainContextMenu, false);
+
+ b.addProgressListener(this.webProgressListener);
+
+ noscriptOverlay.shortcutKeys.register();
+ noscriptOverlay.observer.register();
+
+ if ("CustomizableUI" in window) {
+ CustomizableUI.addListener(this.customizableUIListener);
+ }
+
+ },
+
+
+
+ teardown: function() {
+
+ if (window.CustomizableUI) {
+ CustomizableUI.removeListener(this.customizableUIListener);
+ }
+
+ var b = getBrowser();
+ if (b) {
+ b.removeEventListener("click", this.onBrowserClick, true);
+ if (b.tabContainer) {
+ b.tabContainer.removeEventListener("TabClose", this.onTabClose, false);
+ }
+
+ b.removeProgressListener(this.webProgressListener);
+ }
+
+ window.removeEventListener("pagehide", this.onPageHide, true);
+ window.removeEventListener("pageshow", this.onPageShow, true);
+
+ noscriptOverlay.observer.remove();
+ noscriptOverlay.shortcutKeys.remove();
+
+ $("contentAreaContextMenu").removeEventListener("popupshowing", this.onMainContextMenu, false);
+
+ }
+
+ }, // END listeners
+
+
+ get _browserReady() {
+ return ("gBrowser" in window) && window.gBrowser ||
+ ("Browser" in window) && window.Browser &&
+ (("browsers" in Browser) || Browser._canvasBrowser || Browser._content);
+ },
+ get currentBrowser() {
+ if (!this._browserReady) return null;
+ delete this.currentBrowser;
+ this.__defineGetter__("currentBrowser",
+ window.gBrowser && function() { return gBrowser.selectedBrowser; }
+ || Browser.selectedBrowser && function() { return Browser.selectedBrowser; }
+ || Browser.currentBrowser && function() { return Browser.currentBrowser; }
+ );
+ return this.currentBrowser;
+ },
+
+ get currentURI() {
+ return this.currentBrowser.currentURI;
+ },
+ get currentURL() {
+ let uri = this.currentURI;
+ return uri && uri.spec || "";
+ },
+ get fennec() {
+ if (!this._browserReady) return false;
+ delete this.fennec;
+ return this.fennec = "Browser" in window;
+ },
+
+ get browsers() {
+ if (!this._browserReady) return [];
+ delete this.browsers;
+ var browsersContainer = window.Browser // Fennec
+ ? ("browsers" in Browser) && Browser || Browser._canvasBrowser || Browser._content
+ : window.gBrowser; // desktop Firefox
+
+ this.__defineGetter__("browsers", function() { return browsersContainer.browsers; });
+
+ if ("Browser" in window && window.Browser._content) { // Fennec Alpha 1
+ getBrowserForDisplay = function() { Browser._content.getBrowserForDisplay.apply(Browser._content, arguments); };
+ }
+ return this.browsers;
+ },
+
+ isBrowserEnabled: function(browser) {
+ browser = browser || this.currentBrowser;
+ return browser.docShell ? browser.docShell.allowJavascript : !this.getSites(browser).docJSBlocked;
+ },
+
+
+ wrapBrowserAccess: function(retryCount) { // called onload
+ if (!window.nsBrowserAccess) {
+ noscriptOverlay.ns.log("[NoScript] nsBrowserAccess not found?!");
+ return;
+ }
+
+ if (!nsBrowserAccess.prototype.wrappedJSObject) {
+ nsBrowserAccess.prototype.__defineGetter__("wrappedJSObject", noscriptOverlay.browserAccess.self);
+ }
+
+ if (!(window.browserDOMWindow && browserDOMWindow.wrappedJSObject && (browserDOMWindow.wrappedJSObject instanceof nsBrowserAccess))) {
+ if (!retryCount) {
+ retryCount = 0;
+ } else if (retryCount >= 10) {
+ noscriptOverlay.ns.log("[NoScript] browserDOMWindow not found in 10 attempts, giving up.");
+ return;
+ }
+ window.setTimeout(noscriptOverlay.wrapBrowserAccess, 0, ++retryCount);
+ return;
+ }
+ noscriptOverlay.browserAccess._originalOpenURI = browserDOMWindow.wrappedJSObject.openURI;
+ browserDOMWindow.wrappedJSObject.openURI = noscriptOverlay.browserAccess.openURI;
+
+ if(noscriptOverlay.ns.consoleDump)
+ noscriptOverlay.ns.dump("browserDOMWindow wrapped for external load interception");
+ },
+
+ browserAccess: {
+ self: function() { return this; },
+ openURI: function(aURI, aOpener, aWhere, aContext) {
+ const ns = noscriptUtil.service;
+
+ var external = aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL && aURI;
+ if (external) {
+ if (aURI.schemeIs("http") || aURI.schemeIs("https")) {
+ // remember for filter processing
+ ns.requestWatchdog.externalLoad = aURI.spec;
+ } else {
+ // don't let the external protocol open dangerous URIs
+ if (aURI.schemeIs("javascript") || aURI.schemeIs("data")) {
+ var err = "[NoScript] external non-http load blocked: " + aURI.spec;
+ ns.log(err);
+ throw err;
+ }
+ }
+ }
+
+ if (aURI && ns.extraCapturedProtocols && ns.extraCapturedProtocols.indexOf(aURI.scheme) > -1) {
+ return aOpener || content;
+ }
+
+ var w = null;
+ try {
+ w = nsBrowserAccess.prototype.openURI.apply(this, arguments);
+ if (external && ns.consoleDump) ns.dump("[NoScript] external load intercepted");
+ } finally {
+ if (external && !w) ns.requestWatchdog.externalLoad = null;
+ }
+ return w;
+ }
+ },
+
+ Hacks: {
+ allowLocalLinks: function() {
+ let ns = noscriptOverlay.ns;
+ if (ns.geckoVersionCheck("30") >= 0) return;
+
+ if ("urlSecurityCheck" in window) {
+ let usc = window.urlSecurityCheck;
+ window.urlSecurityCheck = function(aURL, aPrincipal, aFlags) {
+ if (!ns.checkLocalLink(aURL, aPrincipal)) {
+ usc.apply(this, arguments);
+ }
+ }
+ }
+ if ("handleLinkClick" in window) {
+ let hlc = window.handleLinkClick;
+ window.handleLinkClick = function(ev, href, linkNode) {
+ let ret = hlc.apply(this, arguments);
+ if (!ret && ns.checkLocalLink(linkNode.href, linkNode.nodePrincipal)) {
+ try {
+ let w = ev.view.open("about:blank", linkNode.target || "_self");
+ w.location.href = linkNode.href;
+ ev.preventDefault();
+ ret = true;
+ } catch (e) {
+ ret = false;
+ }
+ }
+ return ret;
+ }
+ }
+ },
+ pdfDownload: function() {
+ if (typeof(mouseClick) != "function") return;
+ var tb = getBrowser();
+ tb.removeEventListener("click", mouseClick, true);
+ tb.addEventListener("click", mouseClick, false);
+ },
+
+ torButton: function() {
+ if ("torbutton_update_tags" in window && typeof(window.torbutton_update_tags) == "function") {
+ // we make TorButton aware that we could have a part in suppressing JavaScript on the browser
+ noscriptOverlay.ns.log("TB: " + window.torbutton_update_tags);
+ window.eval(
+ window.torbutton_update_tags.toSource().replace(/\bgetBoolPref\("javascript\.enabled"\)/g,
+ "$& && (!noscriptOverlay || noscriptOverlay.isBrowserEnabled(browser))"));
+ noscriptOverlay.ns.log("Patched TB: " + window.torbutton_update_tags);
+ }
+ }
+ },
+}
+})()
+
+noscriptOverlay.install();
+
diff --git a/extensions/noscript/chrome/content/noscript/noscriptOverlay.xul b/extensions/noscript/chrome/content/noscript/noscriptOverlay.xul
new file mode 100644
index 0000000..ab5541e
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/noscriptOverlay.xul
@@ -0,0 +1,318 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay SYSTEM "chrome://noscript/locale/noscript.dtd">
+
+<?xml-stylesheet href="chrome://noscript/skin/browser.css" type="text/css"?>
+
+<overlay id="noscriptOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/x-javascript" src="noscript.js" />
+ <script type="application/x-javascript" src="noscriptOverlay.js"/>
+
+ <toolbarpalette id="BrowserToolbarPalette">
+ <toolbarbutton id="noscript-tbb"
+ buttonstyle="pictures"
+ class="toolbarbutton-1 noscript-no"
+ label="NoScript"
+ type="menu-button"
+ removable="true"
+ oncommand="noscriptOverlay.onUICommand(event)"
+ oncontextmenu="noscriptOverlay.onContextMenu(event);"
+ onmouseover="noscriptOverlay.onUIOver(event)"
+ onmousemove="noscriptOverlay.onUIMove(event)"
+ onmouseout="noscriptOverlay.onUIOut(event)"
+ onmouseup="noscriptOverlay.onUIUp(event)"
+ context="noscript-tbb-popup"
+ />
+
+ <toolbarbutton id="noscript-tbb-temp-page"
+ tooltiptext="&noscriptTempAllowPage;"
+ buttonstyle="pictures"
+ class="toolbarbutton-1 noscript-temp noscript-allow"
+ label="&noscriptTempAllowPage;"
+ oncommand="noscriptOverlay.allowPage()"
+ />
+ <toolbarbutton id="noscript-tbb-revoke-temp"
+ tooltiptext="&noscriptRevokeTemp;"
+ buttonstyle="pictures"
+ class="toolbarbutton-1 noscript-revoke-temp"
+ label="&noscriptRevokeTemp;"
+ oncommand="noscriptOverlay.revokeTemp()"
+ />
+ </toolbarpalette>
+
+ <popup id="contentAreaContextMenu">
+ <menu id="noscript-context-menu" class="menu-iconic" label="NoScript" >
+ <menupopup id="noscript-context-popup" onpopupshowing="noscriptOverlay.onMenuShowing(event, true)">
+ <menuseparator class="noscript-sep-insert" hidden="true" />
+ <menuseparator class="noscript-sep-stop-untrusted"/>
+ <!-- dynamically inserted #noscript-menu-untrusted -->
+
+ <menuseparator class="noscript-sep-global" />
+ <menuitem class="menuitem-iconic" />
+
+ <menuseparator />
+ <menuitem id="noscript-options-ctx-menuitem"
+ label="&noscriptOptions;"
+ accesskey="&noscriptOptions.accesskey;"
+ oncommand="noscriptUtil.openOptionsDialog()"
+ tooltiptext="&noscriptOptionsLong;"
+ class="menuitem-iconic noscript-options"
+ />
+ <menuitem id="noscript-about-ctx-menuitem"
+ label="&noscriptAbout;"
+ tooltiptext="&noscriptAbout;"
+ oncommand="noscriptUtil.openAboutDialog()"
+ class="menuitem-iconic noscript-about"
+ />
+ </menupopup>
+ </menu>
+ </popup>
+
+ <window id="main-window">
+ <popupset id="mainPopupSet"></popupset><!-- SeaMonkey compatibility -->
+ </window>
+
+
+
+ <popupset id="mainPopupSet">
+ <menupopup id="noscript-notify-popup" onpopupshowing="noscriptOverlay.onMenuShowing(event, true)">
+ <menuseparator />
+ <menuitem
+ id="noscript-options-menuitem"
+ label="&noscriptOptions;"
+ accesskey="&noscriptOptions.accesskey;"
+ oncommand="noscriptUtil.openOptionsDialog()"
+ tooltiptext="&noscriptOptionsLong;"
+ class="menuitem-iconic noscript-options"
+ />
+ <menuitem id="noscript-mi-opt-notify"
+ label="&noscriptNotify;"
+ oncommand="noscriptOverlay.toggleMenuOpt(this)"
+ type="checkbox" autocheck="true"
+ />
+ <menuitem id="noscript-mi-opt-notify.bottom"
+ label="&noscriptNotify.bottom;"
+ oncommand="noscriptOverlay.toggleMenuOpt(this)"
+ type="checkbox" autocheck="true"
+ />
+ <menuitem id="noscript-mi-opt-sound"
+ label="&noscriptSound;"
+ oncommand="noscriptOverlay.toggleMenuOpt(this)"
+ type="checkbox" autocheck="true"
+ />
+
+ <menuseparator class="noscript-sep-global" />
+ <menuitem class="menuitem-iconic" />
+
+ <menuitem id="noscript-mi-invopt-volatilePrivatePermissions"
+ label="&noscriptPermanentInPrivate;"
+ type="checkbox" autocheck="true"
+ oncommand="noscriptOverlay.toggleMenuOpt(this);noscriptOverlay._syncUINow()"
+ />
+ <menuitem id="noscript-revoke-temp-mi"
+ class="menuitem-iconic noscript-revoke-temp"
+ label="&noscriptRevokeTemp;" accesskey="&noscriptRevokeTemp.accesskey;"
+ oncommand="noscriptOverlay.revokeTemp()"
+ />
+ <menuitem id="noscript-allow-page-mi"
+ class="menuitem-iconic noscript-allow"
+ label="&noscriptAllowPage;" noaccesskey="&noscriptAllowPage.accesskey;"
+ oncommand="noscriptOverlay.allowPage(true)"
+ />
+ <menuitem id="noscript-temp-allow-page-mi"
+ class="menuitem-iconic noscript-temp noscript-allow"
+ label="&noscriptTempAllowPage;" noaccesskey="&noscriptTempAllowPage.accesskey;"
+ oncommand="noscriptOverlay.allowPage()"
+ />
+ <menuitem id="noscript-temp2perm-mi"
+ class="menuitem-iconic noscript-allow"
+ label="&noscriptTempToPerm;" accesskey="&noscriptTempToPerm.accesskey;"
+ oncommand="noscriptOverlay.tempToPerm()"
+ />
+
+ <menu id="noscript-xss-menu" class="menu-iconic noscript-xss"
+ onpopupshowing="event.stopPropagation()"
+ onpopuphidden="event.stopPropagation()"
+ label="&noscriptXss;">
+ <menupopup id="noscript-xss-menupopup"></menupopup>
+ </menu>
+
+
+ <menuseparator />
+ <menuseparator class="noscript-sep-untrusted"/>
+
+ <menu id="noscript-menu-blocked-objects" class="menu-iconic noscript-embed"
+ onpopupshowing="event.stopPropagation()"
+ onpopuphidden="event.stopPropagation()"
+ label="&noscriptBlockedObjects;">
+ <menupopup />
+ </menu>
+
+ <menu id="noscript-menu-recent-blocked" class="menu-iconic"
+ onpopupshowing="event.stopPropagation()"
+ onpopuphidden="event.stopPropagation()"
+ label="&noscriptRecentBlocked;">
+ <menupopup>
+ <menuitem id="noscript-mi-recent-blocked-reset"
+ label="&noscriptReset;"
+ class="menuitem-iconic"
+ accesskey="&noscriptReset.accesskey;"
+ oncommand="noscriptOverlay.ns.purgeRecent()"
+ />
+ </menupopup>
+ </menu>
+
+ <menu id="noscript-menu-untrusted" class="menu-iconic noscript-untrusted"
+ onpopupshowing="event.stopPropagation()"
+ onpopuphidden="event.stopPropagation()"
+ label="&noscriptUntrusted;">
+ <menupopup />
+ </menu>
+
+
+ <menuseparator class="noscript-sep-insert"/>
+ <menuseparator class="noscript-sep-stop" hidden="true" />
+ </menupopup>
+
+
+
+ <menupopup id="noscript-xss-popup" onpopupshowing="noscriptOverlay.prepareXssMenu(this)">
+ <menuitem id="noscript-mi-xss-console"
+ label="&noscriptShowConsole;"
+ class="menuitem-iconic noscript-console"
+ accesskey="&noscriptShowConsole.accesskey;"
+ oncommand="noscriptUtil.openConsole()"
+ />
+
+ <menuitem id="noscript-mi-xss-unsafe-reload"
+ class="menuitem-iconic noscript-unsafe-reload"
+ label="&noscriptUnsafeReload;"
+ accesskey="&noscriptUnsafeReload.accesskey;"
+ oncommand="noscriptOverlay.unsafeReload()"
+ />
+
+ <menuseparator />
+ <menuitem id="noscript-mi-xss-opt-xss.notify"
+ label="&noscriptNotifications;"
+ type="checkbox" autocheck="true"
+ oncommand="noscriptOverlay.toggleMenuOpt(this)"
+ />
+
+ <menuitem id="noscript-mi-xss-options"
+ label="&noscriptOptions;"
+ class="menuitem-iconic noscript-options"
+ accesskey="&noscriptOptions.accesskey;"
+ oncommand="noscriptUtil.openXssOptions()"
+ />
+
+ <menuseparator />
+ <menuitem id="noscript-mi-xss-faq"
+ label="&noscriptXssFaq;"
+ class="menuitem-iconic noscript-faq"
+ accesskey="&noscriptXssFaq.accesskey;"
+ oncommand="noscriptUtil.openFaq('xss')"
+ />
+ <menuitem id="noscript-abe-opts" class="menuitem-iconic noscript-abe"
+ style="display: none !important" />
+ </menupopup>
+
+
+ <menupopup id="noscript-sticky-ui"
+ onpopupshowing="noscriptOverlay.onMenuShowing(event)"
+ position="after_end"
+ >
+
+ <menuseparator class="noscript-sep-insert" hidden="true" />
+
+ <menuseparator class="noscript-sep-stop-untrusted"/>
+ <!-- dynamically inserted #noscript-menu-untrusted -->
+
+ <menuseparator class="noscript-sep-global" />
+ <menuitem class="menuitem-iconic" />
+ <menuseparator />
+ <menuitem id="noscript-options-fn-tbb-menuitem"
+ label="&noscriptOptions;"
+ accesskey="&noscriptOptions.accesskey;"
+ oncommand="noscriptUtil.openOptionsDialog()"
+ tooltiptext="&noscriptOptionsLong;"
+ class="menuitem-iconic noscript-options"
+ />
+
+ </menupopup>
+
+
+
+ <menupopup id="noscript-status-popup"
+ onpopupshowing="noscriptOverlay.onMenuShowing(event)"
+ >
+ <menuitem
+ label="&noscriptAbout;"
+ tooltiptext="&noscriptAbout;"
+ oncommand="noscriptUtil.openAboutDialog()"
+ class="menuitem-iconic noscript-about"
+ />
+
+ <menuitem
+ label="&noscriptOptions;"
+ accesskey="&noscriptOptions.accesskey;"
+ oncommand="noscriptUtil.openOptionsDialog()"
+ tooltiptext="&noscriptOptionsLong;"
+ class="menuitem-iconic noscript-options"
+ />
+
+ <menuseparator class="noscript-sep-global"/>
+ <menuitem class="menuitem-iconic" />
+
+ <menuseparator class="noscript-sep-untrusted"/>
+
+ <menuseparator class="noscript-sep-insert"/>
+ <menuseparator class="noscript-sep-stop" hidden="true" />
+ </menupopup>
+
+
+ </popupset>
+
+<statusbar id="status-bar">
+ <statusbarpanel id="noscript-statusLabel"
+ insertbefore="statusbar-updates"
+ hidden="true"
+ oncontextmenu="noscriptOverlay.onContextMenu(event)"
+ onclick="noscriptOverlay.openPopup(this.firstChild, this)"
+ >
+ <vbox flex="1" align="center" pack="center">
+ <label id="noscript-statusLabelValue"/>
+ </vbox>
+ </statusbarpanel>
+
+
+ <statusbarpanel id="noscript-statusIcon"
+ insertbefore="statusbar-updates"
+ class="statusbarpanel-menu-iconic noscript-no"
+ hidden="false"
+ oncontextmenu="noscriptOverlay.onContextMenu(event)"
+ onmouseup="noscriptOverlay.onUIUp(event)"
+ onmouseover="noscriptOverlay.onUIOver(event)"
+ onmousemove="noscriptOverlay.onUIMove(event)"
+ onmouseout="noscriptOverlay.onUIOut(event)"
+ />
+
+
+ <statusbarpanel id="noscript-statusXss" insertbefore="statusbar-updates"
+ class="statusbarpanel-menu-iconic noscript-xss"
+ hidden="true"
+ onclick="switch(event.button) { case 1: this.hidden = true; break; case 2: event.preventDefault(); this.firstChild.showPopup(); }"
+ >
+ <menupopup id="noscript-status-xss-popup" onpopupshowing="noscriptOverlay.prepareXssMenu(this, true)" />
+ </statusbarpanel>
+
+ <statusbarpanel id="noscript-statusRedirect" insertbefore="statusbar-updates"
+ class="statusbarpanel-iconic noscript-redirect"
+ hidden="true"
+ onclick="if(event.button == 1) this.hidden = true"
+ oncommand="noscriptOverlay.followMetaRefresh(event)"
+ />
+
+</statusbar>
+
+</overlay>
diff --git a/extensions/noscript/chrome/content/noscript/tree-copy.js b/extensions/noscript/chrome/content/noscript/tree-copy.js
new file mode 100644
index 0000000..43c9b63
--- /dev/null
+++ b/extensions/noscript/chrome/content/noscript/tree-copy.js
@@ -0,0 +1,53 @@
+// Tree clipboard utils
+
+const Cc = Components.classes, Ci = Components.interfaces, Cu = Components.utils;
+
+var noscriptTreeCc = {
+ cb: Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper),
+
+ getSelectionString: function(tree, csc, rsc) {
+ if (!rsc) rsc = "\n";
+ let start = new Object(), end = new Object(), v = tree.view, out = "";
+ let numRanges = v.selection.getRangeCount();
+ let b = tree.boxObject;
+ b.QueryInterface(Ci.nsITreeBoxObject);
+ let cols = b.columns, l = cols.length - 1;
+
+ for (let i = 0; i < numRanges; i++) {
+ v.selection.getRangeAt(i,start,end);
+ for (let r = start.value; r <= end.value; r++) {
+ for (let c = 0; c <= l; c++) {
+ let f = c != l ? csc : ""
+ out += v.getCellText(r, cols.getColumnAt(c)) + f;
+ }
+ out += rsc;
+ }
+ }
+ return out.trim();
+ },
+
+ getSelectedItems: function(tree, sourceData) {
+ let start = new Object(), end = new Object(), v = tree.view, out = [];
+ let numRanges = v.selection.getRangeCount();
+ let b = tree.boxObject;
+ b.QueryInterface(Ci.nsITreeBoxObject);
+ let cols = b.columns, l = cols.length - 1;
+
+ for (let i = 0; i < numRanges; i++) {
+ v.selection.getRangeAt(i,start,end);
+ for (let r = start.value; r <= end.value; r++) {
+ out.push(sourceData[r]);
+ }
+ }
+ return out;
+ },
+
+ selectAll: function(t) {
+ t.view.selection.selectAll();
+ },
+
+ doCopy: function(t, csc, rsc) {
+ this.cb.copyString(this.getSelectionString(t, csc, rsc));
+ }
+
+};
diff --git a/extensions/noscript/chrome/locale/ar/noscript/about.properties b/extensions/noscript/chrome/locale/ar/noscript/about.properties
new file mode 100644
index 0000000..99d4413
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ar/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=حمايةاضاÙية Ù„ÙيرÙوكس : نوسكربت يسمح لجاÙاسكربت Ùˆ جاÙا وتقنيات اخرى Ùقظ للمجالات التي تثق بها.
+aboutTitle=عن %S
+extensionContributors=المساهمون:
+extensionContributors.tip=أشخاص يستحقون الشكر لهذا الامتداد
+extensionCreatorLabel=المؤلÙ:
+changelog=سجل التغييرات
+changelog.tip=استعرض سجلل التغييرات
+license=الترخيص
+license.tip=اقرأ رخصة المستخدم
+logo.tip=زيارة موقع الامتدادة
+sponsor.tip=زيارة موقع الراعي
+informaction.tip=زيارة موقع إنÙورماكشن
+extensionHomepage.tip=زيارة موقع الامتدادة
+extensionCreator.tip=زيارة موقع المؤلÙ
+version=
diff --git a/extensions/noscript/chrome/locale/ar/noscript/noscript.dtd b/extensions/noscript/chrome/locale/ar/noscript/noscript.dtd
new file mode 100644
index 0000000..4c8b9a6
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ar/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "خيارات…">
+<!ENTITY noscriptOptions.accesskey "Ø®">
+<!ENTITY noscriptOptionsLong "خيارات نوسكربت">
+<!ENTITY noscriptAbout "حول نوسكربت…">
+<!ENTITY noscriptPermissionsText "يمكنك تعيين المواقع المسموح لها تنÙيذ سكربتات. أدخل مسار أو نطاق (مثل &quot;http://www.example.com&quot; أو &quot;example.com&quot;) الموقع الذي تود السماح له ومن ثم اختر &quot;اسمح&quot;.">
+<!ENTITY noscriptWebAddress "مسار موقع وب:">
+<!ENTITY noscriptAllow "السماح">
+<!ENTITY noscriptAllow.accesskey "س">
+<!ENTITY noscriptForbid "المنع">
+<!ENTITY noscriptForbid.accesskey "Ù…">
+<!ENTITY noscriptTrust "التأشير كغير موثوق به">
+<!ENTITY noscriptTrust.accesskey "Ø«">
+<!ENTITY noscriptUntrust "">
+<!ENTITY noscriptUntrust.accesskey "غ">
+<!ENTITY noscriptRemoveSelected "أزالة المواقع المختارة">
+<!ENTITY noscriptGloballyEnabled "السكربتات المسموح لها كليا (خطر)">
+<!ENTITY noscriptAutoReload "أعادة تحميل الصÙحات المتأثرة عند تغيير الصلاحيات آلياً">
+<!ENTITY noscriptGeneral "عامة">
+<!ENTITY noscriptAppearance "المظهر">
+<!ENTITY noscriptShow "أظهر">
+<!ENTITY noscriptCtxMenu "قائمة السياق">
+<!ENTITY noscriptStatusIcon "أيقونة شريط الحالة">
+<!ENTITY noscriptFullAddr "مسارات كاملة (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "نطاقات كاملة (www.noscript.net)">
+<!ENTITY noscriptBaseDom "نطاقات المستوى الثاني (noscript.net)">
+<!ENTITY noscriptTempCmd "السماح المؤقت […]">
+<!ENTITY noscriptSound "تنبيه صوتي عند اعتراض السكربتات">
+<!ENTITY noscriptImport "الاستيراد">
+<!ENTITY noscriptImport.accesskey "س">
+<!ENTITY noscriptExport "التصدير">
+<!ENTITY noscriptExport.accesskey "ص">
+<!ENTITY noscriptNotify "اعرض رسالة عن السكربتات المعترضة">
+<!ENTITY noscriptNotify.bottom "أظهار الرسالة ÙÙŠ الاسÙÙ„">
+<!ENTITY noscriptSound.choose "اختيار">
+<!ENTITY noscriptSound.choose.accesskey "ت">
+<!ENTITY noscriptSound.play "تشغيل">
+<!ENTITY noscriptSound.play.accesskey "Ø´">
+<!ENTITY noscriptSound.reset "تصÙير">
+<!ENTITY noscriptSound.reset.accesskey "ص">
+<!ENTITY noscriptAdvanced "متقدمة">
+<!ENTITY noscriptAdditionalPermissions "صلاحيات إضاÙية للمواقع الموثوقة">
+<!ENTITY noscriptAllowClipboard "السماح بنسخ ولصق النص الغني من حاÙظة القصاصات الخارجية">
+<!ENTITY noscriptAdditionalRestrictions "قيود إضاÙية على المواقع غير الموثوق بها">
+<!ENTITY noscriptPlugins "الملحقات">
+<!ENTITY noscriptContentBlocker "تطبيق هذه القيود على المواقع الموثوقة كذلك">
+<!ENTITY noscriptForbidJava "منع جاÙا">
+<!ENTITY noscriptForbidXSLT "منع أكس أس أل تي">
+<!ENTITY noscriptForbidSilverlight "منع ميكروسوÙت سÙÙ„Ùَرلَيت">
+<!ENTITY noscriptForbidIFrames "منع &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "منع &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "منع @font-face">
+<!ENTITY noscriptForbidWebGL "منع WebGL">
+<!ENTITY noscriptForbidMedia "منع &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "منع ماكروميديا Ùلاش">
+<!ENTITY noscriptForbidPlugins "منع الملحقات الأÙخرى">
+<!ENTITY noscriptReloadWarn "سيتم تÙعيل هذه الخيارات ÙÙŠ الصÙحات الجديدة أو الصÙحات المعاد تحميلها (يدوياً)">
+<!ENTITY noscriptConfirmUnblock "طلب التوكيد قبل رÙع المنع بشكل مؤقت عن عنصر ما">
+<!ENTITY noscriptStatusLabel "عنوان شريط الحالة">
+<!ENTITY noscriptForbidBookmarklets "منع العلامات البرمجية">
+<!ENTITY noscriptShowPlaceholder "أظهار أيقونة شاغلة للحيز">
+<!ENTITY noscriptTruncateTitle "اختصار عناوين الوثائق">
+<!ENTITY noscriptFixLinks "محاولة تصحيح روابط جاÙاسركبت">
+<!ENTITY noscriptAllowBookmarks "السماح للمواقع التي تÙتح من علامات">
+<!ENTITY noscriptAllowViaBookmarks "السماح للمواقع التي تÙتح من علامات">
+<!ENTITY noscriptAllowPing "السماح ل &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "السماح بالروابط المحلية">
+<!ENTITY noscriptForbidPing "منع &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "امنع تحويلات META من داخل عناصر &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "ت">
+<!ENTITY noscriptNotifyMeta "اظهار الرسائل من ميتا محجوبة متغيرة الهدÙ">
+<!ENTITY noscriptNotifyMeta.accesskey "Ù…">
+<!ENTITY noscriptWhitelist "القائمة البيضاء">
+<!ENTITY noscriptPermissions "الصلاحيات">
+<!ENTITY noscriptRefresh "أنعاش">
+<!ENTITY noscriptNotifications "تنويهات">
+<!ENTITY noscriptToolbarToggle "النقر باليسار على أيقونة نوسكربت ÙÙŠ شريط نوسكربت يعكس حالة السماح للمواقع ÙÙŠ المستوى الأعلى">
+<!ENTITY noscriptTrusted "موثوق">
+<!ENTITY noscriptUntrusted "غير موثوق">
+<!ENTITY noscriptUnknown "غير معروÙ">
+<!ENTITY noscriptAdd "أضاÙØ©">
+<!ENTITY noscriptAdd.accesskey "ض">
+<!ENTITY noscriptClose "أغلاق">
+<!ENTITY noscriptSiteManager "مدير المواقع">
+<!ENTITY noscriptSecurityManager "مدير الأمن">
+<!ENTITY noscriptPolicies "السياسات">
+<!ENTITY noscriptDefaultPolicies "السياسات المبدئية">
+<!ENTITY noscriptSitePolicies "سياسات مواقع معينة">
+<!ENTITY noscriptNselNever "أخÙاء محتويات عناصر &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "أظهار محتويات عنصر &lt;NOSCRIPT&gt; الذي يلي &lt;SCRIPT&gt; معترض">
+<!ENTITY noscriptAutoAllowTopLevel "مبدئيا السماح مؤقتا لمواقع المستوى الأعلى">
+<!ENTITY noscriptDescription "حماية إضاÙية Ù„ÙيرÙوكس: نوسكربت يسمح لجاÙاسكربت Ùˆ جاÙا (Ùˆ ملحقات أخرى) للعمل Ùقط من المواقع الموثوقة التي تختارها (مثلا:موقع مصرÙÙƒ). هذه المقاربة التحÙظية المبنية على القوائم البيضاء تمنع استغلال الثغرات الأمنية (حتى غير المعلومة منها) دون تقليل الكÙاءة…سيؤكد المحترÙون أن ÙيرÙوكس أكثر أمناً مع نوسكربت.:-)">
+<!ENTITY noscriptOptBlockCssScanners "اعتراض الماسحات المبنية على تقنية XSS">
+<!ENTITY noscriptOptFilterXGet "تطهير الطلبات المشبوهة عابرة المواقع">
+<!ENTITY noscriptOptFilterXPost "تحويل الطلبات العابرة للمواقع من النوع POST إلى طلبات من GET خالية من البيانات">
+<!ENTITY noscriptShowConsole "أظهار وحدة التحكم">
+<!ENTITY noscriptShowConsole.accesskey "Ùƒ">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "أسئلة شائعة عن ‮ ‪XSS">
+<!ENTITY noscriptXssFaq.accesskey "ع">
+<!ENTITY noscriptUnsafeReload "إعادة تحميل غير آمنة">
+<!ENTITY noscriptUnsafeReload.accesskey "د">
+<!ENTITY noscriptXssExceptions "إستثناءات من الحماية ضد أكس أس">
+<!ENTITY noscriptXssExceptions.description "المواقع المطابقة لهذه العبارات الاعتيادية لن تكون محمية ضد أكس أس">
+<!ENTITY noscriptMatchSample "عينة مطابقة للنمط">
+<!ENTITY noscriptReset "تصÙير">
+<!ENTITY noscriptReset.accesskey "ص">
+<!ENTITY noscriptResetDef "تصÙير للمبدئية">
+<!ENTITY noscriptResetDef.accesskey "Ù">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "ألغاء الصلاحيات المؤقتة">
+<!ENTITY noscriptRevokeTemp.accesskey "Ù…">
+<!ENTITY noscriptNoUntrustedPlaceholder "لا توجد حواÙظ مكان لعناصر قادمة من مواقع محددة كغير آمنة">
+<!ENTITY noscriptCollapseBlockedObjects "تقليص العناصر المÙعتَرضة">
+<!ENTITY noscriptExceptions "استثناءات">
+<!ENTITY noscriptBlockedObjects "عناصر Ù…Ùعتَرضة">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "اعتراض كل شيء آت من موقع محدّد كغير موثوق">
+<!ENTITY noscriptTempAllowPage "السماح مؤقتا للكل ÙÙŠ الصÙحة الحالية">
+<!ENTITY noscriptTempAllowPage.accesskey "س">
+<!ENTITY noscriptAllowPage "السماح لهذه الصÙحة">
+<!ENTITY noscriptAllowPage.accesskey "Ø­">
+<!ENTITY noscriptTempToPerm "جعل صلاحيات الصÙحة دائمة">
+<!ENTITY noscriptTempToPerm.accesskey "ص">
+<!ENTITY noscriptHttps "أتش تي تي بي الآمن">
+<!ENTITY noscriptHttpsFaq "الأسئلة المتكررة حول أتش تي تي بي الآمن">
+<!ENTITY noscriptHttpsFaq.accesskey "Ø´">
+<!ENTITY noscriptHttps.behavior "التصرّÙ">
+<!ENTITY noscriptHttps.cookies "الكعكات">
+<!ENTITY noscriptHttps.description "منع محتويات الشبكة الا اذا كانت عن طريق اتصال آمن">
+<!ENTITY noscriptHttps.never "أبدًا">
+<!ENTITY noscriptHttps.proxy "عند استعمال وسيط">
+<!ENTITY noscriptHttps.always "دائمًا">
+<!ENTITY noscriptHttpsForced "Ùرض استعمال اتصالات آمنة على هذه المواقع">
+<!ENTITY noscriptHttpsForcedExceptions "لا تÙرض استعمال اتصالات آمنة على هذه المواقع">
+<!ENTITY noscriptSecureCookies "تÙعيل الادارة الآلية للكعكات الآمنة">
+<!ENTITY noscriptSecureCookiesForced "Ùرض تعمية كل الكعكات المحددة عبر اتصال آمن للمواقع التالية:">
+<!ENTITY noscriptSecureCookiesExceptions "أهمال الكعكات غير الآمنة عبر اتصال آمن للمواقع التالية:">
+<!ENTITY noscriptClearClickTitle "مسح التحذير">
+<!ENTITY noscriptClearClickHeader "محاولة قرصنة النقر أو تحويل للعنوان">
+<!ENTITY noscriptClearClickDescription "لقد منع نوسكربت تÙاعل لللوحة أو الÙأرة مع عنصر Ù…Ùخَبَّأ.أضغط على الضورة ÙÙŠ الاسÙÙ„ لرؤية كلا النسخ">
+<!ENTITY noscriptClearClickOpt "رÙع الحماية عن الصÙحات…">
+<!ENTITY noscriptClearClickReport "تقرير">
+<!ENTITY noscriptClearClickReport.accesskey "ت">
+<!ENTITY noscriptClearClickReportId "رقم التقرير:">
+<!ENTITY noscriptTrustedPagesAdj "موثوق">
+<!ENTITY noscriptUntrustedPagesAdj "غير موثوق">
+<!ENTITY noscriptKeepLocked "ترك هذا العنصر موصدا (Ù…Ùضّل)">
+<!ENTITY noscriptEmbeddings "عناصر مغروسة">
+<!ENTITY noscriptPrev "السابق">
+<!ENTITY noscriptNext "التالي">
+<!ENTITY noscriptFrameOptErr.title "لا يمكن اظهار المحتويات ÙÙŠ صÙÙَيحةframe">
+<!ENTITY noscriptFrameOptErr.desc "لامانك, ناشر المحتويات لا يسمح باظهارها ÙÙŠ صÙÙَيحة frame">
+<!ENTITY noscriptFrameOptErr.link "النقر هنا Ù„Ùتح المحتويات ÙÙŠ ناÙذة جديدة">
+<!ENTITY noscriptBookmarkSync "عمل نسخة احتياطية للاعدادت Ù…ÙؤَشّÙر لتسهيل التزامن">
+<!ENTITY noscriptShowReleaseNotes "اظهار ملاحظات الاصدار ÙÙŠ التحديثات">
+<!ENTITY ABE "أيب">
+<!ENTITY ABE.accesskey "Ø£">
+<!ENTITY ABE.rulesets.label "القواعد">
+<!ENTITY ABE.enabled.label "تÙعيل أيب (منÙّذ حدود البرامج)">
+<!ENTITY ABE.siteEnabled.label "السماح للمواقع دÙع قواعدهم الخاصة">
+<!ENTITY ABE.edit.label "تحرير">
+<!ENTITY ABE.edit.accesskey "ت">
+<!ENTITY ABE.enable.label "تÙعيل">
+<!ENTITY ABE.enable.accesskey "Ù">
+<!ENTITY ABE.disable.label "ايقاÙ">
+<!ENTITY ABE.disable.accesskey "Ù‚">
+<!ENTITY ABE.refresh.label "تجديد">
+<!ENTITY ABE.refresh.accesskey "ج">
+<!ENTITY noscriptUninstall "ازالة">
+<!ENTITY noscriptRecentBlocked "مواقع معترضة مأخراً">
+<!ENTITY noscriptExternalFilters "Ùلاتر خارجية">
+<!ENTITY noscriptEF.enable "تÙعيل الÙلاتر الخارجية">
+<!ENTITY noscriptEF.add "Ùلتر جديد…">
+<!ENTITY noscriptEF.executable "مل٠تشغيل:">
+<!ENTITY noscriptEF.browse "التصÙح…">
+<!ENTITY noscriptEF.contentType "نوع المحتوى(مايم) الذي سيتم Ùلترته (تطابق">
+<!ENTITY noscriptEF.exceptions "عدك تصÙية كائنات قادمة من هذه المواقع :">
+<!ENTITY noscriptEF.remove "ازالة">
+<!ENTITY noscriptPreset "مستوى الأمن">
+<!ENTITY noscriptPreset.off "إيقا٠(هل أنت متأكد؟!)">
+<!ENTITY noscriptPreset.low "الوضع السهل (القائمة السوداء + أمن الويب)">
+<!ENTITY noscriptPreset.medium "كلاسيكي (القائمة البيضاء+أمن الويب)">
+<!ENTITY noscriptPreset.high "الحصن (أمن تام)">
+<!ENTITY noscript.hoverUI "Ùتح قائمة الإذÙÙ† عندما يحوم المؤشّر Ùوق رمز نوسكريبت">
+<!ENTITY noscriptDonate "التبرع">
+<!ENTITY noscriptDonate.accesskey "ت">
+<!ENTITY noscriptAutoReload.currentTab "اعادة تحميل علام التبويب الحالية Ùقط">
+<!ENTITY noscriptCascadePermissions "">
+<!ENTITY noscriptRestrictSubdocScripting "منع السكربتات ÙÙŠ ملÙات القائمة البيضاء المتواجدة ÙÙŠ الصÙحات الغير موجودة ÙÙŠ القائمة البيضاء">
+<!ENTITY noscriptGlobalHttpsWhitelist "السماح لسكربتات اتش تي تي بي اس بشكل عام ÙÙŠ مستدات اتش تي تي بي اس">
+<!ENTITY noscriptPermanentInPrivate "الدائم للأوامر ÙÙŠ النواÙØ° الشخصية &quot;السماح&quot;">
+<!ENTITY noscriptCustom "Custom">
diff --git a/extensions/noscript/chrome/locale/ar/noscript/noscript.properties b/extensions/noscript/chrome/locale/ar/noscript/noscript.properties
new file mode 100644
index 0000000..535befc
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ar/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=السماح للسكربتات بشكل شامل (غير آمن)
+forbidGlobal=منع السكربتات نهائيا (محبذ)
+allowLocal=السماح من %S
+allowTemp=السماح من %S مؤقتا
+forbidLocal=المنع من %S
+allowed.glb=خطر! السكربتات مسموحة كلياً
+allowed.yes=السكربتات مسموحة حاليًا
+allowed.prt=السكربتات مسموحة جزئيًا
+allowed.no=السكربتات ممنوعة حاليًا
+global.warning.title=تحذير!
+global.warning.text=سيسمح للسكربتات كلياً (لكل المواقع).\nيمكن أن يكون هذا خطيرا.\nأمتأكد أنك تريد المواصلة؟
+audio.samples=عينات صوتية
+confirm=هل أنت متأكد؟
+alwaysAsk=إسأل دائما للتوكيد
+notifyHide=أخÙ٠بعد %S ثانية
+trust=ثق ÙÙŠ %S
+distrust=ألتأشير %S كغير موثوق
+untrustedOrigin=مصدر غير موثوق
+xss.notify.generic=منع نوسكربت محاولة لتشغيل سركيبتات عبر المواقع من %S. تم تسجيل التÙاصيل التقنية ÙÙŠ المرقاب-الكونسول.
+xss.notify.showConsole=أظهار المرقاب-الكونسول…
+xss.notify.showConsole.accessKey=ر
+xss.reason.filterXGet=تم تطهير طلب مشبوه. المسار الأصلي [%1$S] Ø·Ùلب من [%2$S]. المسار المطهر هو: [%3$S]
+xss.reason.filterXGetRef=تم تطهير محيل طلب مشبوه. المسار الأصلي [%1$S] Ø·Ùلب من [%2$S]. المسار المطهر هو: [%3$S]
+xss.reason.filterXPost=تم تطهير تحميل مشبوه إلى [%1$S] من [%2$S]: تم تحويله إلى تنزيل Ùقط بالÙعل GET.
+unsafeReload.warning=تجري إعادة تحميل غير آمنة\n\n[%1$S] [%2$S]\n\nمن[%3$S]\n\nلن يحمي نوسكربت هذا الطلب\n
+metaRefresh.notify=نوسكربت اعترض تحويلا باستخدام <META> داخل عنصر <NOSCRIPT>: %S بعد %S ثانية
+metaRefresh.notify.follow=اتباع التحويل
+metaRefresh.notify.follow.accessKey=ت
+notify.options=خيارات
+notify.options.accessKey=Ø®
+reset.title=تصÙير نوسكربت
+reset.warning=ستعاد كل تخصيصات نوسكربت Ùˆ صلاحيات المواقع إلى القيم المبدئية Ùورا.\nهذا العمل لا يمكن استدراكه.\nأمتأكد أنك تريد المواصلة؟
+bookmarkSync.title=علامة تبويب ضبط نوسكربت
+bookmarkSync.message=علامة التبويب هذه ليست للÙتح وانما لتزامنها باستخدام خدمة مثل Weave أوا Xmarks او XMarks Extension
+bookmarkSync.confirm=وجد نوسكربت اعداد مؤشر محÙوظ ÙÙŠ \n%S, هل تريد حقاً تغيير اعدادات نوسكربت المحلية بمحتويات هذا المؤشر
+ABE.notify=الطلب %1$S تمت تصÙيته من قبل أيب <%2$S> %3$S
+ABE.chooseEditor=الرجاء اختيار محرر نصوص لقواعد أيب
+ABE.syntaxError=خطأ ÙÙŠ بناء الجملة ÙÙŠ مجموعة أوامر آيب!
+ABE.wanIpAsLocal=عنوان الشبكة الخارجي (%S) كداخلي
+allowFrom=السماح للكل من %S
+allowTempFrom=السماح مؤقتاً للكل من %S
+siteInfo.confirm=أنت بصدد السؤال عن الموقع "%1$S" \n يمجرد التقدم بأسÙسار Ù„ %2$S. \n هل تريد المواصلة؟
+siteInfo.tooltip=النقر بالماوس المتوسط أو النقر+Ø´Ùت للحصول على معلومات موقع…
+ef.activate=تصÙية %S
+ef.options=خيارات %S …
+ef.newName=أدخل اسم الÙلتر الجديد :
+ef.locateExe=اختر مل٠التشغيل للÙلتر %S
+disable=تعطيل ال %S
+disable.accessKey=Ø·
+allowed.glb-emb=السكربتات مسموحة كلياً ولكن بعض الامور الضمنية ممنوعة
+removal.title=تحذير تنزيل المستوى الامني
+removal.message=الغاء نوسكربت او ازالته تتنازل عن كل الحماية المتوÙرة من البنرنامج.\n\nاذا تعبت من تÙعيل اوامر السكربتات كل مرة اذا هنالك خيار آخر: \n\n يمكنك نوسكربت من الغاء توقي٠السكربتات الا تلك التي تعينها كغير آمنة وهكذا تبقى محمياً بتدابير الامان المتقدمة مثل اكس اس اس, خط٠النقر, سي اس ار ا٠وتهديدات ويب الاخرى. \n\n هل انت متأكد انك تريد كل حماية نوسكربت؟\n
+removal.no=لا, Ùقط ايقا٠صد السكربتات
+removal.yes=نعم, ازالة كل وسائل الحماية
+incompatibleOptions.title=خيارات تحذير غير متواÙقة
+incompatibleOptions="%1$S"\nغير متواÙÙ‚ مع "%2$S".\b هل تريد تÙعيل الاول وتعطيل الاخÙر؟
diff --git a/extensions/noscript/chrome/locale/be-BY/noscript/about.properties b/extensions/noscript/chrome/locale/be-BY/noscript/about.properties
new file mode 100644
index 0000000..98a4b3b
--- /dev/null
+++ b/extensions/noscript/chrome/locale/be-BY/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Ð”Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ñ Ð°Ð±Ð°Ñ€Ð¾Ð½Ð° Ð´Ð»Ñ Firefox: NoScript дазвалÑе дазвалÑць выкананне JavaScript, Java (Ñ– іншых убудоваў) толькі даменам, Ñкім давÑраеце (напрыклад, ваш вÑб-Ñайт). Белы ÑпіÑ, заÑнаваны на прынцыпе папераджальнага блакаваннÑ, дазвалÑе прадухіліць выкарыÑтанне ўразліваÑцÑÑž (вÑдомых Ñ– ÑÑˆÑ‡Ñ Ð½ÐµÐ²Ñдомых!) без Ñтраты функцыÑнальнаÑці… ЭкÑперты згаджаюцца: Firefox Ñапраўды бÑÑпечней з NoScript :-)
+aboutTitle=Ðб пашырÑнні %S
+extensionContributors=Удзельнікі:
+extensionContributors.tip=Людзі, ÑÐºÑ–Ñ Ð´Ð°Ð¿Ð°Ð¼Ð°Ð³Ð°Ð»Ñ– палÑпшаць пашырÑнне
+extensionCreatorLabel=Ðўтар:
+changelog=Ð¡Ð¿Ñ–Ñ Ð·Ð¼ÐµÐ½Ð°Ñž
+changelog.tip=Паказаць ÑÐ¿Ñ–Ñ Ð·Ð¼ÐµÐ½Ð°Ñž
+license=ЛіцÑÐ½Ð·Ñ–Ð¹Ð½Ð°Ñ Ð´Ð°Ð¼Ð¾Ð²Ð°
+license.tip=Прачытаць ліцÑнзійную дамову з канчатковым карыÑтальнікам
+logo.tip=Ðаведаць хатнюю Ñтаронку пашырÑннÑ
+sponsor.tip=Ðаведаць хатнюю Ñтаронку ÑпонÑара
+informaction.tip=Ðаведаць хатнюю Ñтаронку InformAction
+extensionHomepage.tip=Ðаведаць хатнюю Ñтаронку пашырÑннÑ
+extensionCreator.tip=Ðаведаць хатнюю Ñтаронку аўтара
+version=ВерÑÑ–Ñ %S
diff --git a/extensions/noscript/chrome/locale/be-BY/noscript/noscript.dtd b/extensions/noscript/chrome/locale/be-BY/noscript/noscript.dtd
new file mode 100644
index 0000000..8247e59
--- /dev/null
+++ b/extensions/noscript/chrome/locale/be-BY/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Ðаладкі…">
+<!ENTITY noscriptOptions.accesskey "а">
+<!ENTITY noscriptOptionsLong "Ðаладкі NoScript">
+<!ENTITY noscriptAbout "Ðб пашырÑнні">
+<!ENTITY noscriptPermissionsText "Ð’Ñ‹ можаце вызначыць, Ñкім вÑб-Ñайтам будзе дазволена выконваць код JavaScript. УвÑдзіце Ð°Ð´Ñ€Ð°Ñ Ð°Ð±Ð¾ дамен (напрыклад «http://www.site.com» або «site.com») Ñайта Ñкому вы жадаеце дазволіць выкананне JavaScript у Ñ‚ÑкÑтавым полі ніжÑй, а затым націÑніце «Дазволіць».">
+<!ENTITY noscriptWebAddress "ÐÐ´Ñ€Ð°Ñ Ð²Ñб-Ñайта:">
+<!ENTITY noscriptAllow "Дазволіць">
+<!ENTITY noscriptAllow.accesskey "е">
+<!ENTITY noscriptForbid "Забараніць">
+<!ENTITY noscriptForbid.accesskey "ь">
+<!ENTITY noscriptTrust "Ðдзначыць давераным">
+<!ENTITY noscriptTrust.accesskey "аб">
+<!ENTITY noscriptUntrust "Ðдзначыць ненадзейным">
+<!ENTITY noscriptUntrust.accesskey "у">
+<!ENTITY noscriptRemoveSelected "Выдаліць Ð²Ñ‹Ð»ÑƒÑ‡Ð°Ð½Ñ‹Ñ Ñайты">
+<!ENTITY noscriptGloballyEnabled "Цалкам дазвалÑць выкананне JavaScript на Ñтаронках (небÑÑпечна)">
+<!ENTITY noscriptAutoReload "Ðўтаматычна абнаўлÑць Ñтаронку паÑÐ»Ñ Ð·Ð¼ÐµÐ½Ñ‹ Ð´Ð»Ñ Ñе правілаў">
+<!ENTITY noscriptGeneral "ÐÑноўныÑ">
+<!ENTITY noscriptAppearance "Знешні выглÑд">
+<!ENTITY noscriptShow "ÐдлюÑтроўваць наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ñлементы NoScript…">
+<!ENTITY noscriptCtxMenu "Пункт у кантÑкÑтным меню">
+<!ENTITY noscriptStatusIcon "Значок у радку Ñтану">
+<!ENTITY noscriptFullAddr "ÐŸÐ¾ÑžÐ½Ñ‹Ñ Ð°Ð´Ñ€Ð°ÑÑ‹ (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "ÐŸÐ¾ÑžÐ½Ñ‹Ñ Ð´Ð°Ð¼ÐµÐ½Ñ‹ (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Ð‘Ð°Ð·Ð°Ð²Ñ‹Ñ Ð´Ð°Ð¼ÐµÐ½Ñ‹ 2-го ÑžÐ·Ñ€Ð¾ÑžÐ½Ñ (noscript.net)">
+<!ENTITY noscriptTempCmd "ЧаÑова дазволіць […]">
+<!ENTITY noscriptSound "Прайграваць аўдыёфайл пры блакаванні Ñкрыптоў">
+<!ENTITY noscriptImport "Імпарт">
+<!ENTITY noscriptImport.accesskey "м">
+<!ENTITY noscriptExport "ЭкÑпарт">
+<!ENTITY noscriptExport.accesskey "да">
+<!ENTITY noscriptNotify "ÐдлюÑтроўваць паведамленні аб заблакаваных Ñкрыптах">
+<!ENTITY noscriptNotify.bottom "РазмÑшчаць паведамленні знізу Ñкрана">
+<!ENTITY noscriptSound.choose "ÐглÑд">
+<!ENTITY noscriptSound.choose.accesskey "аб">
+<!ENTITY noscriptSound.play "ПраÑлухаць">
+<!ENTITY noscriptSound.play.accesskey "а">
+<!ENTITY noscriptSound.reset "Скід">
+<!ENTITY noscriptSound.reset.accesskey "бы">
+<!ENTITY noscriptAdvanced "Дадаткова">
+<!ENTITY noscriptAdditionalPermissions "Ð”Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ñ‹Ñ Ð¼Ð°Ð³Ñ‡Ñ‹Ð¼Ð°Ñці Ð´Ð»Ñ Ð´Ð°Ð²ÐµÑ€Ð°Ð½Ñ‹Ñ… Ñайтаў">
+<!ENTITY noscriptAllowClipboard "Пашыранае капіÑванне/уÑтаўка з знешнÑга буфера абмену">
+<!ENTITY noscriptAdditionalRestrictions "Ð”Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ñ‹Ñ Ð°Ð±Ð¼ÐµÐ¶Ð°Ð²Ð°Ð½Ð½Ñ– Ð´Ð»Ñ Ð½ÐµÐ½Ð°Ð´Ð·ÐµÐ¹Ð½Ñ‹Ñ… Ñайтаў">
+<!ENTITY noscriptPlugins "Плагіны">
+<!ENTITY noscriptContentBlocker "Ужываць гÑÑ‚Ñ‹Ñ Ð°Ð±Ð¼ÐµÐ¶Ð°Ð²Ð°Ð½Ð½Ñ– такÑама Ð´Ð»Ñ Ð´Ð°Ð²ÐµÑ€Ð°Ð½Ñ‹Ñ… Ñайтаў">
+<!ENTITY noscriptForbidJava "Забараніць адлюÑтраванне Ñлементаў Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Забараніць адлюÑтраванне Ñлементаў XSLT">
+<!ENTITY noscriptForbidSilverlight "Забараніць адлюÑтраванне Ñлементаў Microsoft® Silverlightâ„¢">
+<!ENTITY noscriptForbidIFrames "Забараніць адлюÑтраванне Ñлементаў &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Забараніць адлюÑтраванне Ñлементаў &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Забараніць адлюÑтраванне Ñлементаў @font-face">
+<!ENTITY noscriptForbidWebGL "Забараніць адлюÑтраванне Ñлементаў WebGL">
+<!ENTITY noscriptForbidMedia "Забараніць адлюÑтраванне Ñлементаў &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Забараніць адлюÑтраванне Ñлементаў Macromedia® Flash®">
+<!ENTITY noscriptForbidPlugins "Забараніць адлюÑтраванне Ñлементаў іншых убудоваў">
+<!ENTITY noscriptReloadWarn "Ðататка: УÑталÑÐ²Ð°Ð½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´ÐºÑ– ÑžÑтупаюць у Ñілу альбо на новай Ñтаронцы, альбо паÑÐ»Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð° Ð°Ð±Ð½Ð°ÑžÐ»ÐµÐ½Ð½Ñ Ð±Ñгучае Ñтаронкі">
+<!ENTITY noscriptConfirmUnblock "ПацвÑрджаць чаÑовую разблакоўку аб&apos;екта на Ñтаронцы">
+<!ENTITY noscriptStatusLabel "Паведамленні Ñž радку Ñтану">
+<!ENTITY noscriptForbidBookmarklets "Забараніць выкарыÑтанне Bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Вылучаць Ð·Ð°Ð±Ð»Ð°ÐºÐ°Ð²Ð°Ð½Ñ‹Ñ Ñлементы значком з рамкаю">
+<!ENTITY noscriptTruncateTitle "ÐдÑÑкаць занадта Ð´Ð¾ÑžÐ³Ñ–Ñ Ð·Ð°Ð³Ð°Ð»Ð¾ÑžÐºÑ– вÑб-Ñайтаў">
+<!ENTITY noscriptFixLinks "Ужываць алгарытм Ð²Ñ‹Ð¿Ñ€Ð°ÑžÐ»ÐµÐ½Ð½Ñ JavaScript-ÑпаÑылкаў">
+<!ENTITY noscriptAllowBookmarks "ДазвалÑць выкананне JavaScript уÑім вÑб-Ñайтам з закладкаў">
+<!ENTITY noscriptAllowViaBookmarks "ДазвалÑць выкананне JavaScript уÑім вÑб-Ñайтам з закладкаў">
+<!ENTITY noscriptAllowPing "Дазволіць вÑб-Ñайту выкарыÑтаць параметр &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Дазволіць Ð»Ð°ÐºÐ°Ð»ÑŒÐ½Ñ‹Ñ ÑпаÑылкі">
+<!ENTITY noscriptForbidPing "Забараніць вÑб-Ñайту выкарыÑтаць параметр &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Забараніць META-перанакіраванні ўнутры Ñлементаў &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptWhitelist "Белы ÑпіÑ">
+<!ENTITY noscriptPermissions "Дазволы">
+<!ENTITY noscriptRefresh "Ðбнавіць">
+<!ENTITY noscriptNotifications "ÐпавÑшчÑнні">
+<!ENTITY noscriptToolbarToggle "ÐаціÑкам на значку NoScript перамыкаць дазволы Ð´Ð»Ñ ÑžÑÑго Ñайта">
+<!ENTITY noscriptTrusted "Давераны">
+<!ENTITY noscriptUntrusted "Ðенадзейны">
+<!ENTITY noscriptUnknown "ÐевÑдомы">
+<!ENTITY noscriptAdd "Дадаць">
+<!ENTITY noscriptAdd.accesskey "аб">
+<!ENTITY noscriptClose "Зачыніць">
+<!ENTITY noscriptSiteManager "ÐœÑнÑджÑÑ€ Ñайтаў">
+<!ENTITY noscriptSecurityManager "Кіраванне бÑÑпекаю">
+<!ENTITY noscriptPolicies "Палітыкі">
+<!ENTITY noscriptDefaultPolicies "Палітыкі па змаўчанні">
+<!ENTITY noscriptSitePolicies "ÐдмыÑÐ»Ð¾Ð²Ñ‹Ñ Ð¿Ð°Ð»Ñ–Ñ‚Ñ‹ÐºÑ– Ð´Ð»Ñ Ñайтаў">
+<!ENTITY noscriptNselNever "Хаваць Ñлементы &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Паказваць Ñлемент &lt;NOSCRIPT&gt; Ñкі блакуе &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "ЧаÑова дазвалÑць базавым даменам 2-го ÑžÐ·Ñ€Ð¾ÑžÐ½Ñ Ð¿Ð° змаўчанні">
+<!ENTITY noscriptDescription "Ð”Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ñ Ð°Ð±Ð°Ñ€Ð¾Ð½Ð° Ð´Ð»Ñ Firefox: NoScript дазвалÑе дазвалÑць выкананне JavaScript, Java (Ñ– іншых убудоваў) толькі даменам, Ñкім давÑраеце (напрыклад, ваш вÑб-Ñайт). Белы ÑпіÑ, заÑнаваны на прынцыпе папераджальнага блакаваннÑ, дазвалÑе прадухіліць выкарыÑтанне ўразліваÑцÑÑž (вÑдомых Ñ– ÑÑˆÑ‡Ñ Ð½ÐµÐ²Ñдомых!) без Ñтраты функцыÑнальнаÑці… ЭкÑперты згаджаюцца: Firefox Ñапраўды бÑÑпечней з NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Блакаваць CSS-Ñканары">
+<!ENTITY noscriptOptFilterXGet "Фільтраваць запыты, Ð¿Ð°Ð´Ð°Ð·Ñ€Ð°Ð²Ð°Ð½Ñ‹Ñ Ð½Ð° XSS">
+<!ENTITY noscriptOptFilterXPost "ЗамÑнÑць XSS POST-запыты на GET-запыты без дадзеных">
+<!ENTITY noscriptShowConsole "Паказаць канÑоль…">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ…">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "ÐебÑÑÐ¿ÐµÑ‡Ð½Ð°Ñ Ð¿ÐµÑ€Ð°Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "ВыключÑнні абароны анты-XSS">
+<!ENTITY noscriptXssExceptions.description "ПрызначÑнні, адпавÑÐ´Ð°ÑŽÑ‡Ñ‹Ñ Ð³Ñтым Ñ€ÑгулÑрным выразам, ÐЕ будуць Ð°Ð±Ð°Ñ€Ð¾Ð½ÐµÐ½Ñ‹Ñ Ñупраць XSS">
+<!ENTITY noscriptMatchSample "Прыклад адпавÑÐ´Ð°Ð½Ð½Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ñƒ:">
+<!ENTITY noscriptReset "Скінуць">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Скінуць на наладкі па змаўчанні">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "ÐнулÑваць чаÑÐ¾Ð²Ñ‹Ñ Ð´Ð°Ð·Ð²Ð¾Ð»Ñ‹">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ðе ўжываць запаўнÑльнікі Ð´Ð»Ñ Ð°Ð±&apos;ектаў, прыходзÑчых з Ñайтаў, пазначаных Ñк ненадзейныÑ">
+<!ENTITY noscriptCollapseBlockedObjects "Згарнуць Ð·Ð°Ð±Ð»Ð°ÐºÐ°Ð²Ð°Ð½Ñ‹Ñ Ð°Ð±&apos;екты">
+<!ENTITY noscriptExceptions "ВыключÑнні…">
+<!ENTITY noscriptBlockedObjects "Ð—Ð°Ð±Ð»Ð°ÐºÐ°Ð²Ð°Ð½Ñ‹Ñ Ð°Ð±&apos;екты">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Блакаваць уÑе аб&apos;екты, прыходзÑÑ‡Ñ‹Ñ Ð· Ñайтаў, пазначаных Ñк ненадзейныÑ">
+<!ENTITY noscriptTempAllowPage "ЧаÑова дазволіць уÑÑ‘ на гÑтай Ñтаронцы">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Дазволіць уÑÑ‘ на гÑтай Ñтаронцы">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Зрабіць дазволы паÑтаÑннымі">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Паводзіны">
+<!ENTITY noscriptHttps.cookies "Кукі">
+<!ENTITY noscriptHttps.description "ЗабаранÑць актыўны вÑб-змеÑÑ‚ калі ён прыходзіць не па бÑÑпечным (HTTPS) злучÑнні:">
+<!ENTITY noscriptHttps.never "Ðіколі">
+<!ENTITY noscriptHttps.proxy "Пры ўжыванні прокÑÑ– (Ñ€Ñкамендавана з Tor)">
+<!ENTITY noscriptHttps.always "Заўжды">
+<!ENTITY noscriptHttpsForced "Прымушаць наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ñайты выкарыÑтоўваць бÑÑÐ¿ÐµÑ‡Ð½Ñ‹Ñ (HTTPS) злучÑнні:">
+<!ENTITY noscriptHttpsForcedExceptions "Ðіколі не прымушаць выкарыÑтоўваць бÑÑÐ¿ÐµÑ‡Ð½Ñ‹Ñ (HTTPS) злучÑнні Ð´Ð»Ñ Ð½Ð°Ñтупных Ñайтаў:">
+<!ENTITY noscriptSecureCookies "Дазволіць аўтаматычнае кіраванне бÑÑпечнымі кукі">
+<!ENTITY noscriptSecureCookiesForced "ПрымуÑова шыфраваць уÑе кукі, даÑÑ‹Ð»Ð°ÐµÐ¼Ñ‹Ñ Ð¿Ñ€Ð°Ð· HTTPS наÑтупными Ñайтамиі:">
+<!ENTITY noscriptSecureCookiesExceptions "Ігнараваць небÑÑÐ¿ÐµÑ‡Ð½Ñ‹Ñ ÐºÑƒÐºÑ–, даÑÑ‹Ð»Ð°ÐµÐ¼Ñ‹Ñ Ð¿Ñ€Ð°Ð· HTTPS наÑтупными Ñайтамиі:">
+<!ENTITY noscriptClearClickTitle "ПапÑÑ€Ñджанне ClearClick">
+<!ENTITY noscriptClearClickHeader "ПатÑÐ½Ñ†Ñ‹Ð¹Ð½Ð°Ñ Ñпроба Clickjacking / змÑÐ½ÐµÐ½Ð½Ñ UI!">
+<!ENTITY noscriptClearClickDescription "NoScript перахапіў узаемадзеÑнне мышы альбо клавіÑтуры з чаÑткова Ñхаваным Ñлементам. ÐаціÑкайце на значку вышÑй каб пераключацца паміж перашкоджаным Ñ– чыÑтым варыÑнтамі.">
+<!ENTITY noscriptClearClickOpt "Ðбарона ClearClick на Ñтаронках…">
+<!ENTITY noscriptClearClickReport "Справаздача">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "ID Ñправаздачы:">
+<!ENTITY noscriptTrustedPagesAdj "давераныÑ">
+<!ENTITY noscriptUntrustedPagesAdj "ненадзейныÑ">
+<!ENTITY noscriptKeepLocked "Трымаць гÑÑ‚Ñ‹ Ñлемент заблакаваным (Ñ€Ñкамендуецца)">
+<!ENTITY noscriptEmbeddings "Ð£Ð±ÑƒÐ´Ð°Ð²Ð°Ð½Ñ‹Ñ Ð°Ð±&apos;екты">
+<!ENTITY noscriptPrev "ПапÑÑ€Ñдні">
+<!ENTITY noscriptNext "ÐаÑтупны">
+<!ENTITY noscriptFrameOptErr.title "ГÑÑ‚Ñ‹ змеÑÑ‚ не можа быць адлюÑтраваны Ñž рамцы">
+<!ENTITY noscriptFrameOptErr.desc "Каб абараніць вашу бÑÑпеку, выдавец гÑтага змеÑту не дазвалÑе Ñму быць адлюÑтраваным Ñž рамцы.">
+<!ENTITY noscriptFrameOptErr.link "ÐаціÑніце тут, каб адкрыць гÑÑ‚Ñ‹ змеÑÑ‚ у новым акне">
+<!ENTITY noscriptBookmarkSync "Захаваць наладкі NoScript у закладках Ð´Ð»Ñ Ð»Ñ‘Ð³ÐºÐ°Ð¹ Ñінхранізацыі">
+<!ENTITY noscriptAutoReload.currentTab "Перазагрузіць толькі актыўнае акно">
+<!ENTITY noscriptNotifyMeta "Паказваць паведамленне аб заблакаваных META-перанакіраваннÑÑ…">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptShowReleaseNotes "Паказаць нататкі аб выпуÑку пры абнаўленнÑÑ…">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Ðаборы правілаў:">
+<!ENTITY ABE.enabled.label "Уключыць ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "ДазвалÑць Ñайтам праÑоўваць ўлаÑÐ½Ñ‹Ñ Ð½Ð°Ð±Ð¾Ñ€Ñ‹ правілаў">
+<!ENTITY ABE.edit.label "РÑдагаваць…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Уключыць">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Ðдключыць">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Ðбнавіць">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "ÐдуÑталÑваць">
+<!ENTITY noscriptRecentBlocked "ÐÑдаўна Ð·Ð°Ð±Ð»Ð°ÐºÐ°Ð²Ð°Ð½Ñ‹Ñ Ñайты">
+<!ENTITY noscriptExternalFilters "Ð—Ð½ÐµÑˆÐ½Ñ–Ñ Ñ„Ñ–Ð»ÑŒÑ‚Ñ€Ñ‹">
+<!ENTITY noscriptEF.enable "Уключыць Ð·Ð½ÐµÑˆÐ½Ñ–Ñ Ñ„Ñ–Ð»ÑŒÑ‚Ñ€Ñ‹">
+<!ENTITY noscriptEF.add "Ðовы фільтр…">
+<!ENTITY noscriptEF.executable "Выканальны файл:">
+<!ENTITY noscriptEF.browse "ПраглÑдаць…">
+<!ENTITY noscriptEF.contentType "Фільтруемы тып змеÑту (MIME) (дакладнае Ñупадзенне або Ñ€ÑгулÑрны выраз):">
+<!ENTITY noscriptEF.exceptions "Ðе фільтраваць аб&apos;екты, прыходзÑÑ‡Ñ‹Ñ Ð· наÑтупных Ñайтаў:">
+<!ENTITY noscriptEF.remove "Выдаліць">
+<!ENTITY noscriptPreset "Узровень бÑÑпекі">
+<!ENTITY noscriptPreset.off "Выключыць (вы Ñур&apos;ёзна?!)">
+<!ENTITY noscriptPreset.low "Палегчаны (чорны ÑÐ¿Ñ–Ñ + вÑб-бÑÑпека)">
+<!ENTITY noscriptPreset.medium "КлаÑічны (белы ÑÐ¿Ñ–Ñ + вÑб-бÑÑпека)">
+<!ENTITY noscriptPreset.high "КрÑпаÑць (Ð¿Ð¾ÑžÐ½Ð°Ñ Ð±Ð»Ð°ÐºÑ–Ñ€Ð¾ÑžÐºÐ°)">
+<!ENTITY noscript.hoverUI "Ðдкрыць меню дазволаў пры навÑдзенні мышы на значок NoScript">
+<!ENTITY noscriptDonate "ÐхвÑраваць">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "РаÑпаўÑюджвацць дазволы пачатковага дакумента на Ñкрыпты з іншых крыніц">
+<!ENTITY noscriptRestrictSubdocScripting "Блакаваць Ñкрыпты на ўключаных у белы ÑÐ¿Ñ–Ñ Ð´Ð°ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ…, змешчаных на Ñтаронак па-за белага ÑпіÑу">
+<!ENTITY noscriptGlobalHttpsWhitelist "ДазвалÑць HTTPS-Ñкрыпты глабальна на HTTPS-дакументах">
+<!ENTITY noscriptPermanentInPrivate "ПаÑтаÑнна &quot;дазвалÑць&quot; каманды Ñž прыватных вокнах">
+<!ENTITY noscriptCustom "Custom">
diff --git a/extensions/noscript/chrome/locale/be-BY/noscript/noscript.properties b/extensions/noscript/chrome/locale/be-BY/noscript/noscript.properties
new file mode 100644
index 0000000..70a198b
--- /dev/null
+++ b/extensions/noscript/chrome/locale/be-BY/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Дазволіць Ñкрыпты паўÑюль (небÑÑпечна)
+forbidGlobal=Забараніць JavaScript цалкам (Ñ€Ñкамендуецца)
+allowLocal=Дазволіць %S
+allowTemp=ЧаÑова дазволіць %S
+forbidLocal=Забараніць %S
+allowed.glb=ÐебÑÑпека! Выкананне JavaScript цалкам дазволена.
+allowed.yes=JavaScript дазволены на Ñтаронцы.
+allowed.prt=JavaScript чаÑткова дазволены.
+allowed.no=JavaScript забаронены на Ñтаронцы.
+global.warning.title=Увага!
+global.warning.text=JavaScript будзе цалкам дазволены (Ð´Ð»Ñ ÑžÑÑ–Ñ… вÑб-Ñайтаў).\n ГÑта патÑнцыйна небÑÑпечнае дзеÑнне.\nÐ’Ñ‹ Ñапраўды жадаеце працÑгнуць?
+audio.samples=ÐудыÑпрыклад
+confirm=Ð’Ñ‹ ўпÑўненыÑ?
+alwaysAsk=ЗаўÑёды пытаць пацверджанне
+notifyHide=Хаваць паведамленні паÑÐ»Ñ %S Ñекундаў
+trust=ДавÑраць %S
+distrust=Ðе давÑраць %S
+untrustedOrigin=Ñк крыніца недаверу
+xss.notify.generic=NoScript адфільтраваў патÑнцыйную XSS-атаку (Ñпробу межÑайтового Ñкриптинга) з адраÑу %S. ТÑÑ…Ð½Ñ–Ñ‡Ð½Ñ‹Ñ Ð¿Ð°Ð´Ñ€Ð°Ð±ÑзнаÑці занеÑÐµÐ½Ñ‹Ñ Ñž канÑоль.
+xss.notify.showConsole=Ðдкрыць канÑоль
+xss.notify.showConsole.accessKey=аб
+xss.reason.filterXGet=Ðдфільтраваны падазроны запыт: Ðрыгінальны URL-Ð°Ð´Ñ€Ð°Ñ [%1$S] запытаны Ñа Ñтаронкі [%2$S]. (Ðдфільтраваны адраÑ: [%3$S])
+xss.reason.filterXGetRef=Ðдфільтраваны падазроны «referer»: URL-запыт да [%1$S] Ñа Ñтаронкі [%2$S]. (Ðдфільтраваны адраÑ: [%3$S])
+xss.reason.filterXPost=ÐÐ´Ñ„Ñ–Ð»ÑŒÑ‚Ñ€Ð°Ð²Ð°Ð½Ð°Ñ Ð¿Ð°Ð´Ð°Ð·Ñ€Ð¾Ð½Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° з [%2$S] да [%1$S]: запыт ператвораны Ñž GET-запыт Ð´Ð»Ñ Ð·Ð°Ð¿Ð°Ð¼Ð¿Ð¾ÑžÐºÑ–.
+unsafeReload.warning=ÐебÑÑÐ¿ÐµÑ‡Ð½Ð°Ñ Ð¿ÐµÑ€Ð°Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° падазронага\n\n%1$S [%2$S]\n\nад [%3$S]\n\nNoScript ÐЕ зможа абараніць гÑÑ‚Ñ‹ запыт!\n
+metaRefresh.notify=NoScript заблакаваў <META>-перанакіраванне ўнутры Ñлементу <NOSCRIPT>: %S за %S Ñек.
+metaRefresh.notify.follow=ІÑці па перанакіраванні
+metaRefresh.notify.follow.accessKey=F
+notify.options=Ðаладкі
+notify.options.accessKey=O
+reset.title=Скінуць NoScript
+reset.warning=УСЕ наладкі NoScript Ñ– дазволы Ð´Ð»Ñ Ñайтаў будуць ÑÐºÑ–Ð½ÑƒÑ‚Ñ‹Ñ Ð´Ð° Ñ–Ñ… значÑннÑÑž па змаўчанні.\nГÑтае дзеÑнне не можа быць ÑкаÑавана.\nПрацÑгваць?
+bookmarkSync.title=Закладка канфігурацыі NoScript
+bookmarkSync.message=ГÑÑ‚Ð°Ñ Ð·Ð°ÐºÐ»Ð°Ð´ÐºÐ° Ð¿Ñ€Ñ‹Ð·Ð½Ð°Ñ‡Ð°Ð½Ð°Ñ ÐЕ Ð´Ð»Ñ Ð°Ð´ÐºÑ€Ñ‹Ñ†Ñ†Ñ, а Ð´Ð»Ñ Ñінхранізацыі з дапамогай ÑÑрвіÑаў кшталту Weave альбо пашырÑÐ½Ð½Ñ XMarks.
+allowed.glb-emb=Скрыпты цалкам дазволеныÑ, але Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ ÑžÐºÐ»Ð°Ð´Ð°Ð½Ð½Ñ– заблакаваныÑ
+bookmarkSync.confirm=NoScript знайшоў закладку канфигурацыі меркавана захаваную на\n%S.\nÐ’Ñ‹ Ñапраўды хочаце перазапіÑаць лакальную канфігурацыю змеÑтам гÑтай закладкі?
+ABE.notify=Запыт %1$S адфільтраваны ABE: <%2$S> %3$S
+ABE.chooseEditor=Калі лаÑка, абÑрыце Ñ‚ÑкÑтавы Ñ€Ñдактар Ð´Ð»Ñ Ð½Ð°Ð±Ð¾Ñ€Ð°Ñž правілаў ABE
+ABE.syntaxError=СінтакÑÑ–Ñ‡Ð½Ð°Ñ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° Ñž наборы правілаў ABE!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=ДазвалÑць уÑе з %S
+allowTempFrom=ЧаÑова дазволіць уÑе з %S
+siteInfo.confirm=Ð’Ñ‹ збіраецеÑÑ Ð°Ñ‚Ñ€Ñ‹Ð¼Ð°Ñ†ÑŒ даведку аб Ñайце "%1$S"\nдаÑлаўшы запыт да %2$S.\nПрацÑгваць?
+siteInfo.tooltip=Middle-click альбо shift+click Ð´Ð»Ñ Ð´Ð°Ð²ÐµÐ´ÐºÑ– аб Ñайце...
+ef.activate=Фільтр %S
+ef.options=Ðаладкі %S…
+ef.newName=УвÑдзіце назву новага фільтра:
+ef.locateExe=Выберыце выканальны файл Ð´Ð»Ñ Ñ„Ñ–Ð»ÑŒÑ‚Ñ€Ð° %S
+disable=Ðдключыць %S
+disable.accessKey=D
+removal.title=ПапÑÑ€Ñджанне аб паніжÑнні бÑÑпекі
+removal.message=Ðдключаючы або адуÑталёўваючы NoScript, вы адмаўлÑецеÑÑ Ð°Ð´ ЎСÐЙ абароны, забÑÑпечваемай NoScript.\n\nКалі вам надакучыла апрацоўваць дазволы Ð´Ð»Ñ Ñкрыптоў на кожным Ñайце, Ñ–Ñнуе больш бÑÑпечны выбар.\n\nNoScript можа Ñпыніць блакаванне Ñкрыптоў, Ð°ÐºÑ€Ð°Ð¼Ñ Ñ‚Ñ‹Ñ…, што вы пазначыце Ñк ненадзейныÑ, тым чаÑам абаранÑючы Ð²Ð°Ñ Ð· дапамогай Ñамых перадавых захадаў бÑÑпекі Ñупраць XSS, Clickjacking, CSRF Ñ– іншых вÑб-пагроз.\n\nÐ’Ñ‹ Ñапраўды хочаце пазбавіцца УСЕЙ абароны NoScript?\n
+removal.no=Ðе, толькі Ñпыніць блакіроўку Ñкрыптоў
+removal.yes=Так, знÑць УСЮ абарону
+incompatibleOptions.title=ПапÑÑ€Ñджанне аб неÑумÑшчальных наладках
+incompatibleOptions="%1$S"\nнеÑумÑÑˆÑ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ð· "%2$S".\bУключыць першую Ñ– адключыць апошнюю?
diff --git a/extensions/noscript/chrome/locale/bg-BG/noscript/about.properties b/extensions/noscript/chrome/locale/bg-BG/noscript/about.properties
new file mode 100644
index 0000000..a46819c
--- /dev/null
+++ b/extensions/noscript/chrome/locale/bg-BG/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Допълнителна защита за Ð²Ð°ÑˆÐ¸Ñ Firefox: NoScript контролира JavaScript, Java (и други добавки) за избрани от Ð²Ð°Ñ Ñайтове (например, вашиÑÑ‚ личен банков Ñайт). ПредотвратÑва използването на "дупки" в ÑигурноÑтта от вÑÑкакъв вид (познати и непознати) без загуба на функционалноÑт… ЕкÑпертите ще Ñе ÑъглаÑÑÑ‚: Ð¡ÑŠÑ NoScript вашиÑÑ‚ браузър е в безопаÑноÑÑ‚ :-)
+aboutTitle=За %S
+extensionContributors=Сътрудници:
+extensionContributors.tip=Хора, на които Ñ‚Ñ€Ñбва да Ñте признателни за тази добавка
+extensionCreatorLabel=Ðвтор:
+changelog=Промени
+changelog.tip=Покажи промените
+license=Лиценз
+license.tip=Прочети на лиценза
+logo.tip=ПоÑети уеб-Ñайта на тази добавка
+sponsor.tip=ПоÑети уеб-Ñайта на ÑпонÑора
+informaction.tip=ПоÑети Ñайта InformAction
+extensionHomepage.tip=ПоÑети уеб-Ñайта на тази добавка
+extensionCreator.tip=ПоÑети уеб-Ñайта на автора
+version=ВерÑÐ¸Ñ %S
diff --git a/extensions/noscript/chrome/locale/bg-BG/noscript/noscript.dtd b/extensions/noscript/chrome/locale/bg-BG/noscript/noscript.dtd
new file mode 100644
index 0000000..6626466
--- /dev/null
+++ b/extensions/noscript/chrome/locale/bg-BG/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "ÐаÑтройки…">
+<!ENTITY noscriptOptions.accesskey "Ð">
+<!ENTITY noscriptOptionsLong "ÐаÑтройки на NoScript">
+<!ENTITY noscriptAbout "За NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Можете да зададете в кои уеб-Ñайтове е позволено да Ñе използват Ñкриптовете. Ðапишете адреÑа или домейна (например &quot;http://www.site.com&quot; или &quot;site.com&quot;) на Ñайта, който иÑкате да разрешите и натиÑнете Разреши.">
+<!ENTITY noscriptWebAddress "ÐÐ´Ñ€ÐµÑ Ð½Ð° уеб-Ñайта:">
+<!ENTITY noscriptAllow "Разреши">
+<!ENTITY noscriptAllow.accesskey "Р">
+<!ENTITY noscriptForbid "Забрани">
+<!ENTITY noscriptForbid.accesskey "З">
+<!ENTITY noscriptTrust "Маркиране като Ðадежден">
+<!ENTITY noscriptTrust.accesskey "Ð">
+<!ENTITY noscriptUntrust "Маркиране като Ðенадежден">
+<!ENTITY noscriptUntrust.accesskey "е">
+<!ENTITY noscriptRemoveSelected "Премахване на избраните Ñайтове">
+<!ENTITY noscriptGloballyEnabled "Скриптовете Ñа напълно разрешени (опаÑно)">
+<!ENTITY noscriptAutoReload "Ðвтоматично презареждай Ñайтовете, когато разрешението бъде променено">
+<!ENTITY noscriptGeneral "Общи">
+<!ENTITY noscriptAppearance "Изглед">
+<!ENTITY noscriptShow "Покажи…">
+<!ENTITY noscriptCtxMenu "КонтекÑтно меню">
+<!ENTITY noscriptStatusIcon "Икона в ÑÑ‚Ð°Ñ‚ÑƒÑ Ð»ÐµÐ½Ñ‚Ð°Ñ‚Ð°">
+<!ENTITY noscriptFullAddr "Пълен Ð°Ð´Ñ€ÐµÑ (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Пълен домейн (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Втори домейн (noscript.net)">
+<!ENTITY noscriptTempCmd "Разреши временно […]">
+<!ENTITY noscriptSound "Звуково извеÑтие при блокиране на Ñкрипт">
+<!ENTITY noscriptImport "ВнаÑÑне">
+<!ENTITY noscriptImport.accesskey "Ð’">
+<!ENTITY noscriptExport "ИзнаÑÑне">
+<!ENTITY noscriptExport.accesskey "И">
+<!ENTITY noscriptNotify "Показвай Ñъобщение за блокираните Ñкриптове">
+<!ENTITY noscriptNotify.bottom "ПоÑтави Ñъобщението в дъното на екрана">
+<!ENTITY noscriptSound.choose "Избери">
+<!ENTITY noscriptSound.choose.accesskey "И">
+<!ENTITY noscriptSound.play "ПроÑлушай">
+<!ENTITY noscriptSound.play.accesskey "Ñ€">
+<!ENTITY noscriptSound.reset "ВъзÑтанови обичайните наÑтройки">
+<!ENTITY noscriptSound.reset.accesskey "о">
+<!ENTITY noscriptAdvanced "Разширени">
+<!ENTITY noscriptAdditionalPermissions "Допълнителни Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð·Ð° доверените Ñайтове">
+<!ENTITY noscriptAllowClipboard "Разрешаване на текÑтово копиране и поÑтавÑне от клипборда">
+<!ENTITY noscriptAdditionalRestrictions "Допълнителни забрани за ненадеждни Ñайтове">
+<!ENTITY noscriptPlugins "ПриÑтавки">
+<!ENTITY noscriptContentBlocker "Прилагане на тези Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¸ към доверените Ñайтове">
+<!ENTITY noscriptForbidJava "Забрани Java™">
+<!ENTITY noscriptForbidXSLT "Забрани XSLT">
+<!ENTITY noscriptForbidSilverlight "Забрани Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Забрани &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Забрани &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Забрани @font-face">
+<!ENTITY noscriptForbidWebGL "Забрани WebGL">
+<!ENTITY noscriptForbidMedia "Забрани &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Забрани Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Забрани други плъгини">
+<!ENTITY noscriptReloadWarn "Тези наÑтройки ще имат ефект на нови или (ръчно) презаредени Ñтраници">
+<!ENTITY noscriptConfirmUnblock "ИÑкане за разрешение преди временно разрешаване на обект">
+<!ENTITY noscriptStatusLabel "Обозначение в ÑÑ‚Ð°Ñ‚ÑƒÑ Ð»ÐµÐ½Ñ‚Ð°Ñ‚Ð°">
+<!ENTITY noscriptForbidBookmarklets "Забрани bookmarklet">
+<!ENTITY noscriptShowPlaceholder "Покажи иконата">
+<!ENTITY noscriptTruncateTitle "Отрежи имената на документите">
+<!ENTITY noscriptFixLinks "Ðаправи опит да поправиш JavaScript линковете">
+<!ENTITY noscriptAllowBookmarks "Разреши вÑички Ñайтове в отметките">
+<!ENTITY noscriptAllowViaBookmarks "Разрешавай Ñайтове отварÑни чрез отметките">
+<!ENTITY noscriptAllowPing "Разрешавай &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Разрешаване на локални връзки">
+<!ENTITY noscriptForbidPing "Забрани &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "ЗабранÑване на META пренаÑÐ¾Ñ‡Ð²Ð°Ð½Ð¸Ñ Ð² &lt;NOSCRIPT&gt; елементи">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "З">
+<!ENTITY noscriptNotifyMeta "Показване на ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð·Ð° блокирани МЕТРпренаÑочваниÑ">
+<!ENTITY noscriptNotifyMeta.accesskey "М">
+<!ENTITY noscriptWhitelist "БÑл ÑпиÑък">
+<!ENTITY noscriptPermissions "РазрешениÑ">
+<!ENTITY noscriptRefresh "ОбновÑване">
+<!ENTITY noscriptNotifications "ИзвеÑтиÑ">
+<!ENTITY noscriptToolbarToggle "Щракване Ñ Ð»Ñв бутон върху иконата на NoScript в лентата превключва разрешениÑта за ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð¸Ñ Ñайт">
+<!ENTITY noscriptTrusted "Ðадеждни">
+<!ENTITY noscriptUntrusted "Ðенадеждни">
+<!ENTITY noscriptUnknown "ÐеизвеÑтни">
+<!ENTITY noscriptAdd "ДобавÑне">
+<!ENTITY noscriptAdd.accesskey "Д">
+<!ENTITY noscriptClose "ЗатварÑне">
+<!ENTITY noscriptSiteManager "Управление на Ñайтове">
+<!ENTITY noscriptSecurityManager "Управление на защитата">
+<!ENTITY noscriptPolicies "УÑловиÑ">
+<!ENTITY noscriptDefaultPolicies "Обичайни уÑловиÑ">
+<!ENTITY noscriptSitePolicies "Специфични уÑловиÑ">
+<!ENTITY noscriptNselNever "Скриване на &lt;NOSCRIPT&gt; елементи">
+<!ENTITY noscriptNselForce "Показване на &lt;NOSCRIPT&gt; елемент, който Ñледва блокиран &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Временно позволи използване на java от вÑички Ñайтове">
+<!ENTITY noscriptDescription "Допълнителна защита за Ð²Ð°ÑˆÐ¸Ñ Firefox: NoScript контролира JavaScript, Java (и други добавки) за избрани от Ð²Ð°Ñ Ñайтове (например, вашиÑÑ‚ личен банков Ñайт). ПредотвратÑва използването на &quot;дупки&quot; в ÑигурноÑтта от вÑÑкакъв вид (познати и непознати) без загуба на функционалноÑт… ЕкÑпертите ще Ñе ÑъглаÑÑÑ‚: Ð¡ÑŠÑ NoScript вашиÑÑ‚ браузър е в безопаÑноÑÑ‚ :-)">
+<!ENTITY noscriptOptBlockCssScanners "Блокиране на CSS-базирани Ñкенери">
+<!ENTITY noscriptOptFilterXGet "ИзчиÑтване на подозрителни кроÑ-Ñайт заÑвки">
+<!ENTITY noscriptOptFilterXPost "Превръщане на POST кроÑ-Ñайт заÑвките в GET заÑвки">
+<!ENTITY noscriptShowConsole "Показване на конзолата…">
+<!ENTITY noscriptShowConsole.accesskey "П">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS ЧЗВ…">
+<!ENTITY noscriptXssFaq.accesskey "Ч">
+<!ENTITY noscriptUnsafeReload "Ðезащитено презареждане">
+<!ENTITY noscriptUnsafeReload.accesskey "п">
+<!ENTITY noscriptXssExceptions "Anti-XSS Защита - изключениÑ">
+<!ENTITY noscriptXssExceptions.description "ÐаправлениÑта Ñъвпадащи Ñ Ñ‚ÐµÐ·Ð¸ обичайни изрази ÐЯМРда бъдат защитени от XSS.">
+<!ENTITY noscriptMatchSample "Пример за Ñъвпадане:">
+<!ENTITY noscriptReset "Ðулиране">
+<!ENTITY noscriptReset.accesskey "Ð">
+<!ENTITY noscriptResetDef "ВъзÑтановÑване на Ñтандартните">
+<!ENTITY noscriptResetDef.accesskey "у">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "ОтменÑне на временните разрешениÑ">
+<!ENTITY noscriptRevokeTemp.accesskey "в">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ðе показвай обекти идващи от Ñайтове маркирани като ненадеждни">
+<!ENTITY noscriptCollapseBlockedObjects "Свиване на блокираните обекти">
+<!ENTITY noscriptExceptions "ИзключениÑ…">
+<!ENTITY noscriptBlockedObjects "Блокирани обекти">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Блокиране на вÑеки обект идващ от Ñайт маркиран като ненадежден">
+<!ENTITY noscriptTempAllowPage "Временно разрешаване на вÑичко за тази Ñтраница">
+<!ENTITY noscriptTempAllowPage.accesskey "Ñ€">
+<!ENTITY noscriptAllowPage "Разрешаване на вÑичко на Ñтраницата">
+<!ENTITY noscriptAllowPage.accesskey "в">
+<!ENTITY noscriptTempToPerm "ЗапомнÑне на разрешениÑта">
+<!ENTITY noscriptTempToPerm.accesskey "м">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS ЧЗВ">
+<!ENTITY noscriptHttpsFaq.accesskey "Ч">
+<!ENTITY noscriptHttps.behavior "ДейÑтвие">
+<!ENTITY noscriptHttps.cookies "БиÑквитки">
+<!ENTITY noscriptHttps.description "ЗабранÑване на активно Ñъдържание, оÑвен ако не идва от защитена (HTTPS) връзка:">
+<!ENTITY noscriptHttps.never "Ðикога">
+<!ENTITY noscriptHttps.proxy "При използване на прокÑи (препоръчително Ñ Tor)">
+<!ENTITY noscriptHttps.always "Винаги">
+<!ENTITY noscriptHttpsForced "Принуждаване на Ñледните Ñайтове да използват защитена (HTTPS) връзка:">
+<!ENTITY noscriptHttpsForcedExceptions "Ðикога да не Ñе използва защитена връзка за Ñледните Ñайтове:">
+<!ENTITY noscriptSecureCookies "Разрешаване на автоматичното управление на защитени биÑквитки">
+<!ENTITY noscriptSecureCookiesForced "Принуждаване за криптиране на вÑички биÑквитки получени от HTTPS, за Ñледните Ñайтове:">
+<!ENTITY noscriptSecureCookiesExceptions "Игнориране на незащитените биÑквитки за Ñледните Ñайтове:">
+<!ENTITY noscriptClearClickTitle "ClearClick предупреждение">
+<!ENTITY noscriptClearClickHeader "Потенциална опаÑноÑÑ‚ от клик-отвличане/опит за пренаÑочване!">
+<!ENTITY noscriptClearClickDescription "NoScript прихвана взаимодейÑтвие между Ñкрит елемент и мишката или клавиатурата. ÐатиÑнете върху картинката отгоре, за да превключите между подозрителната и чиÑтата верÑиÑ.">
+<!ENTITY noscriptClearClickOpt "ClearClick защита на Ñтраници...">
+<!ENTITY noscriptClearClickReport "Доклад">
+<!ENTITY noscriptClearClickReport.accesskey "Д">
+<!ENTITY noscriptClearClickReportId "Доклад №:">
+<!ENTITY noscriptTrustedPagesAdj "надеждни">
+<!ENTITY noscriptUntrustedPagesAdj "ненадеждни">
+<!ENTITY noscriptKeepLocked "ОÑтави този елемент заключен (препоръчително)">
+<!ENTITY noscriptEmbeddings "Вградени обекти">
+<!ENTITY noscriptPrev "Предишен">
+<!ENTITY noscriptNext "Следващ">
+<!ENTITY noscriptFrameOptErr.title "Това Ñъдържание не може да бъде показано в рамка">
+<!ENTITY noscriptFrameOptErr.desc "От ÑÑŠÐ¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð·Ð° ÑигурноÑÑ‚, издателÑÑ‚ на това Ñъдържание не разрешава то да бъде показано в рамка">
+<!ENTITY noscriptFrameOptErr.link "ÐатиÑнете тук, за да отворите Ñъдържанието в нов прозорец">
+<!ENTITY noscriptBookmarkSync "ЗапиÑване на наÑтройките за NoScript като отметка, за по-леÑно Ñинхронизиране">
+<!ENTITY noscriptShowReleaseNotes "Показване на промените в новата верÑиÑ">
+<!ENTITY ABE "ÐВЕ">
+<!ENTITY ABE.accesskey "Ð">
+<!ENTITY ABE.rulesets.label "Правила:">
+<!ENTITY ABE.enabled.label "Разрешаване на ÐВЕ (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Разрешаване на Ñайтовете да прилагат ÑобÑтвени правила">
+<!ENTITY ABE.edit.label "Редактиране">
+<!ENTITY ABE.edit.accesskey "Р">
+<!ENTITY ABE.enable.label "Разрешаване">
+<!ENTITY ABE.enable.accesskey "Ñ€">
+<!ENTITY ABE.disable.label "Изключване">
+<!ENTITY ABE.disable.accesskey "И">
+<!ENTITY ABE.refresh.label "ОбновÑване">
+<!ENTITY ABE.refresh.accesskey "О">
+<!ENTITY noscriptUninstall "ДеинÑталиране">
+<!ENTITY noscriptRecentBlocked "ÐаÑкоро блокирани Ñайтове">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/bg-BG/noscript/noscript.properties b/extensions/noscript/chrome/locale/bg-BG/noscript/noscript.properties
new file mode 100644
index 0000000..a8d91f0
--- /dev/null
+++ b/extensions/noscript/chrome/locale/bg-BG/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Разрешаване на Ñкриптовете изцÑло (опаÑно)
+forbidGlobal=Забрана на Ñкриптовете напълно (препоръчва Ñе)
+allowLocal=Разреши %S
+allowTemp=Временно разреши %S
+forbidLocal=Забрани %S
+allowed.glb=ОпаÑноÑÑ‚! Скриптовете Ñа изцÑло разрешени
+allowed.yes=Скриптовете в момента Ñа разрешени
+allowed.prt=Скриптовете Ñа чаÑтично разрешени.
+allowed.no=Скриптовете в момента Ñа забранени
+global.warning.title=Предупреждение!
+global.warning.text=Скриптовете ще бъдат напълно разрешени (за вÑеки Ñайт).\n Това е потенциално опаÑно дейÑтвие.\n ÐаиÑтина ли иÑкате да продължите?
+audio.samples=Звукови примери
+confirm=Сигурни ли Ñте?
+alwaysAsk=Винаги питай за разрешение
+notifyHide=Скрий Ñлед %S Ñекунди
+trust=Ðадежден %S
+distrust=Маркиране на %S като ненадежден
+untrustedOrigin=ненадежден произход
+xss.notify.generic=NoScript филтрира потенциален опит за кроÑ-Ñайт Ñкрипт (XSS) от %S. ТехничеÑките детайли Ñа запиÑани в Конзолата.
+xss.notify.showConsole=Показване на конзолата…
+xss.notify.showConsole.accessKey=П
+xss.reason.filterXGet=ИзчиÑтена е подозрителна заÑвка. ОригиналниÑÑ‚ Ð°Ð´Ñ€ÐµÑ [%1$S] e заÑвен от [%2$S]. ИзчиÑтен адреÑ: [%3$S].
+xss.reason.filterXGetRef=ИзчиÑтен е подозрителен изпращач на заÑвки. ÐдреÑÑŠÑ‚ [%1$S] е заÑвен от [%2$S]. ИзчиÑтен изпращач: [%3$S].
+xss.reason.filterXPost=ИзчиÑтен е подозрителен ъплоуд към [%1$S] от [%2$S], преобразуван като заÑвка за даунлоуд.
+unsafeReload.warning=ОПÐСÐО зареждане на подозрителниÑ\n\n%1$S [%2$S]\n\nОТ %3$S]\n\nNoScript ÐЕ може да защити тази заÑвка!\n
+metaRefresh.notify=NoScript блокира <META> пренаÑочване в <NOSCRIPT> елемент: %S в %S Ñекунди.
+metaRefresh.notify.follow=Следване на пренаÑочването
+metaRefresh.notify.follow.accessKey=С
+notify.options=ÐаÑтройки
+notify.options.accessKey=Ð
+reset.title=NoScript Ðулиране
+reset.warning=ВСИЧКИ наÑтройки и Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð½Ð° Ñайтове в NoScript ще бъдат върнати до Ñ‚Ñхната първоначална ÑтойноÑÑ‚.\nТова дейÑтвие не може да бъде отменено Ñлед това.\nИÑкате ли да продължите?
+bookmarkSync.title=NoScript отметка Ñ Ð½Ð°Ñтройки
+bookmarkSync.message=Тази отметка ÐЕ е предназначена за отварÑне, а за Ñинхронизиране чрез използването на уÑлуги от добавки като Weave или XMarks.
+bookmarkSync.confirm=NoScript намери конфигурационна отметка, запазена в\n%S.\nÐаиÑтина ли иÑкате да презапишете наÑтройките на NoScript?
+ABE.notify=ЗаÑвка %1$S филтрирана от ÐВЕ: <%2$S> %3$S
+ABE.chooseEditor=МолÑ, изберете текÑтов редактор за ÐВЕ правилата
+allowFrom=Разрешаване на вÑичко от %S
+allowTempFrom=Временно разрешаване на вÑичко от %S
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/bn-IN/noscript/about.properties b/extensions/noscript/chrome/locale/bn-IN/noscript/about.properties
new file mode 100644
index 0000000..6d89d5b
--- /dev/null
+++ b/extensions/noscript/chrome/locale/bn-IN/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=ফায়ারফকà§à¦¸à§‡à¦° জনà§à¦¯ অতিরিকà§à¦¤ সà§à¦°à¦•à§à¦·à¦¾: নোসà§à¦•à§à¦°à¦¿à¦ªà¦Ÿ শà§à¦§à§à¦®à¦¾à¦¤à§à¦° আপনার বিশà§à¦¬à¦¾à¦¸à¦¯à§‹à¦—à§à¦¯ à¦à¦²à¦¾à¦•à¦¾à¦°à¦‡ কাজ করবে (যেমন আপনার বাঙà§à¦•à§‡à¦° ওয়েবসাইট). বিশেষজà§à¦žà¦°à¦¾ রাজি হবে: ফায়ারফকà§à¦¸à§‡à¦° সতà§à¦¯à¦¿à¦‡ নিরাপদ হয় নোসà§à¦•à§à¦°à¦¿à¦ªà¦Ÿà§‡à¦° সঙà§à¦—ে :-)
+aboutTitle=বিষয় %S
+extensionContributors=অবদানকারী
+extensionContributors.tip=আপনি à¦à¦‡ à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨ জনà§à¦¯ ধনà§à¦¯à¦¬à¦¾à¦¦ হবে
+extensionCreatorLabel=লেখক
+changelog=পরিবরà§à¦¤à¦¨à§‡à¦° তালিকা
+changelog.tip=পরিবরà§à¦¤à¦¨à§‡à¦°à¦¤à¦¾à¦²à¦¿à¦•à¦¾ দেখাও
+license=লাইসেনà§à¦¸
+license.tip=শেষ ইউজার লাইসেনà§à¦¸ পড়à§à¦¨
+logo.tip=à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨à§‡à¦° নিজসà§à¦¬à¦“য়েবসাইট দেখà§à¦¨
+sponsor.tip=পৃষà§à¦ à¦ªà§‹à¦·à¦• নিজসà§à¦¬à¦“য়েবসাইট দেখà§à¦¨
+informaction.tip=ইনফরমঅà§à¦¯à¦¾à¦•à¦¶à¦¨à§‡à¦° নিজসà§à¦¬à¦“য়েবসাইট দেখà§à¦¨
+extensionHomepage.tip=à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨à§‡à¦° নিজসà§à¦¬à¦ªà¦¾à¦¤à¦¾ দেখà§à¦¨
+extensionCreator.tip=লেখকের নিজসà§à¦¬à¦ªà¦¾à¦¤à¦¾ দেখà§à¦¨
+version=সংসà§à¦•à¦°à¦£ %S
diff --git a/extensions/noscript/chrome/locale/bn-IN/noscript/noscript.dtd b/extensions/noscript/chrome/locale/bn-IN/noscript/noscript.dtd
new file mode 100644
index 0000000..66a2585
--- /dev/null
+++ b/extensions/noscript/chrome/locale/bn-IN/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "বিকলà§à¦ª ...">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "নোসà§à¦•à§à¦°à¦¿à¦ªà¦Ÿ বিকলà§à¦ª">
+<!ENTITY noscriptAbout "নোসà§à¦•à§à¦°à¦¿à¦ªà¦Ÿà§‡à¦° বিষয়">
+<!ENTITY noscriptPermissionsText "আপনি যে ওয়েব সাইট থেকে সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ চালানো অনà§à¦®à§‹à¦¦à¦¿à¦¤ হয় উলà§à¦²à§‡à¦– করা যাবে. ঠিকানা বা সাইটের ডোমেইন লিখà§à¦¨ (যেমন &quot;http://www.site.com&quot; অথবা &quot;site.com&quot;)à¦à¦¬à¦‚ তারপর মঞà§à¦œà§à¦°à¦¿ কà§à¦²à¦¿à¦• করà§à¦¨à¥¤">
+<!ENTITY noscriptWebAddress "ওয়েবসাইটের ঠিকানাঃ">
+<!ENTITY noscriptAllow "মঞà§à¦œà§à¦°">
+<!ENTITY noscriptAllow.accesskey "l">
+<!ENTITY noscriptForbid "নিষেধ">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "বিশà§à¦¬à¦¸à§à¦¤ হিসাবে চিহà§à¦¨à¦¿à¦¤ করà§à¦¨">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "অনিরà§à¦­à¦°à¦¯à§‹à¦—à§à¦¯ হিসাবে চিহà§à¦¨à¦¿à¦¤ করà§à¦¨">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ সাইট অপসারন">
+<!ENTITY noscriptGloballyEnabled "সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ সরà§à¦¬à¦¤à§à¦° অনà§à¦®à§‹à¦¦à¦¿à¦¤(বিপজà§à¦œà¦¨à¦•)">
+<!ENTITY noscriptAutoReload "অনà§à¦®à¦¤à¦¿ পাওয়ার পর পাতাটি আবার খà§à¦²à¦¬à§‡ সয়ংকà§à¦°à¦¿à§Ÿ হওয়ার জনà§à¦¯">
+<!ENTITY noscriptGeneral "সাধারন">
+<!ENTITY noscriptAppearance "চেহারা">
+<!ENTITY noscriptShow "দেখান ...">
+<!ENTITY noscriptCtxMenu "বরà§à¦£à¦¨à¦¾à¦ªà§à¦°à¦¾à¦¸à¦™à§à¦—িক মেনà§">
+<!ENTITY noscriptStatusIcon "সà§à¦¥à¦¿à¦¤à¦¿ বার আইকন">
+<!ENTITY noscriptFullAddr "সমà§à¦ªà§‚রà§à¦£ ঠিকানা (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "সমà§à¦ªà§‚রà§à¦£ ডোমেইন (www.noscript.net)">
+<!ENTITY noscriptBaseDom "২য় লেভেল ভিতà§à¦¤à¦¿ ডোমেইন (noscript.net)...">
+<!ENTITY noscriptTempCmd "সাময়িকভাবে অনà§à¦®à§‹à¦¦à¦¨ [...]">
+<!ENTITY noscriptSound "অডিও ফিডবà§à¦¯à¦¾à¦• দেওয়া হবে যখন সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ বà§à¦²à¦• করা হবে">
+<!ENTITY noscriptImport "আমদানি">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "রপà§à¦¤à¦¾à¦¨à¦¿">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "বà§à¦²à¦• সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿà§‡à¦° বারà§à¦¤à¦¾ দেখানো">
+<!ENTITY noscriptNotify.bottom "বারà§à¦¤à¦¾ নীচে আসবে">
+<!ENTITY noscriptSound.choose "বাছাই">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "খেলà§à¦¨">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "আগের মত">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "অগà§à¦°à¦¸à¦°">
+<!ENTITY noscriptAdditionalPermissions "বিশà§à¦¬à¦¸à§à¦¤ সাইটের জনà§à¦¯ অতিরিকà§à¦¤ অনà§à¦®à¦¤à¦¿">
+<!ENTITY noscriptAllowClipboard "রিচ টেকà§à¦¸à¦Ÿ বহিরাগত কà§à¦²à¦¿à¦ªà¦¬à§‹à¦°à§à¦¡ থেকে কপি à¦à¦¬à¦‚ পেসà§à¦Ÿ করার অনà§à¦®à¦¤à¦¿ পà§à¦°à¦¦à¦¾à¦¨">
+<!ENTITY noscriptAdditionalRestrictions "অনিরà§à¦­à¦°à¦¯à§‹à¦—à§à¦¯ সাইটের জনà§à¦¯ অতিরিকà§à¦¤ সীমাবদà§à¦§à¦¤à¦¾">
+<!ENTITY noscriptPlugins "পà§à¦²à¦¾à¦—িন">
+<!ENTITY noscriptContentBlocker "বিশà§à¦¬à¦¾à¦¸à¦¯à§‹à¦—à§à¦¯ সাইটেও à¦à¦‡ সীমাবদà§à¦§à¦¤à¦¾ পà§à¦°à¦¯à¦¼à§‹à¦—">
+<!ENTITY noscriptForbidJava "নিষেধ Java™">
+<!ENTITY noscriptForbidXSLT "নিষেধ">
+<!ENTITY noscriptForbidSilverlight "নিষেধ Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "নিষেধ &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "নিষেধ &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "নিষেধ @font-face">
+<!ENTITY noscriptForbidMedia "নিষেধ &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "নিষেধ">
+<!ENTITY noscriptForbidPlugins "নিষেধ অনà§à¦¯à¦¾à¦¨à§à¦¯ plugins">
+<!ENTITY noscriptReloadWarn "à¦à¦‡ অপশনটি নতà§à¦¨ বা à¦à¦‡ পাতাতেই পà§à¦°à¦­à¦¾à¦¬ পরবে">
+<!ENTITY noscriptConfirmUnblock "অসà§à¦¥à¦¾à¦¯à¦¼à§€à¦­à¦¾à¦¬à§‡ à¦à¦•à¦Ÿà¦¿ বসà§à¦¤à§ আনবà§à¦²à¦• করার আগে জিজà§à¦žà§‡à¦¸ করবে">
+<!ENTITY noscriptStatusLabel "সà§à¦¥à¦¿à¦¤à¦¿ বার লেবেল">
+<!ENTITY noscriptForbidBookmarklets "নিষেধ bookmarklets">
+<!ENTITY noscriptShowPlaceholder "সà§à¦¥à¦¾à¦¨à¦§à¦¾à¦°à¦• আইকন দেখাও">
+<!ENTITY noscriptFixLinks "জাভা সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ লিঙà§à¦• ফিকà§à¦¸à§‡à¦° চেষà§à¦Ÿà¦¾">
+<!ENTITY noscriptAllowBookmarks "বà§à¦•à¦®à¦¾à¦°à§à¦• মাধà§à¦¯à¦®à§‡ খোলা সাইটগà§à¦²à¦¿à¦° মঞà§à¦œà§à¦°à¦¿ দিন">
+<!ENTITY noscriptAllowViaBookmarks "বà§à¦•à¦®à¦¾à¦°à§à¦• মাধà§à¦¯à¦®à§‡ খোলা সাইটগà§à¦²à¦¿à¦° মঞà§à¦œà§à¦°à¦¿ দিন">
+<!ENTITY noscriptAllowPing "&lt;A PING…&gt;কে মঞà§à¦œà§à¦°à¦¿">
+<!ENTITY noscriptAllowLocalLinks "লোকাল লিঙà§à¦• মঞà§à¦œà§à¦°à¦¿">
+<!ENTITY noscriptForbidPing "&lt;A PING…&gt; নিষেধ">
+<!ENTITY noscriptForbidMetaRefresh "&lt;NOSCRIPT&gt; উপাদান ভিতরে মেটা redirections নিষেধ">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "মেটা রিডায়রেকশন বà§à¦²à¦•à§‡à¦° বারà§à¦¤à¦¾ দেখান">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "বিশà§à¦¬à¦¾à¦¸à§€à¦¤à¦¾à¦²à¦¿à¦•à¦¾">
+<!ENTITY noscriptPermissions "অনà§à¦®à¦¤à¦¿">
+<!ENTITY noscriptRefresh "পà§à¦¨à¦ƒà¦°à¦¾à§Ÿ">
+<!ENTITY noscriptNotifications "বিজà§à¦žà¦ªà§à¦¤à¦¿">
+<!ENTITY noscriptToolbarToggle "নোসà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ টà§à¦²à¦¬à¦¾à¦° বাটন রেখে কà§à¦²à¦¿à¦• করে বরà§à¦¤à¦®à¦¾à¦¨ শীরà§à¦· সà§à¦¤à¦°à§‡à¦° সাইটের জনà§à¦¯ অনà§à¦®à¦¤à¦¿ টগল">
+<!ENTITY noscriptTrusted "নিরà§à¦­à¦°à¦¯à§‹à¦—à§à¦¯">
+<!ENTITY noscriptUntrusted "অনিরà§à¦­à¦°à¦¯à§‹à¦—à§à¦¯">
+<!ENTITY noscriptUnknown "অচেনা">
+<!ENTITY noscriptAdd "যোগ">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "বনà§à¦§">
+<!ENTITY noscriptSiteManager "সাইট মà§à¦¯à¦¾à¦¨à§‡à¦œà¦¾à¦°">
+<!ENTITY noscriptSecurityManager "নিরাপতà§à¦¤à¦¾ মà§à¦¯à¦¾à¦¨à§‡à¦œà¦¾à¦°">
+<!ENTITY noscriptPolicies "করà§à¦®à¦ªà¦¨à§à¦¥à¦¾">
+<!ENTITY noscriptDefaultPolicies "ডিফলà§à¦Ÿ নীতি">
+<!ENTITY noscriptSitePolicies "সাইট সংকà§à¦°à¦¾à¦¨à§à¦¤ নীতি">
+<!ENTITY noscriptNselNever "&lt;NOSCRIPT&gt; আবহাওয়া লà§à¦•à¦¾à¦¨">
+<!ENTITY noscriptNselForce "&lt;NOSCRIPT&gt; দেখান যেটি &lt;SCRIPT&gt; আটকেছে">
+<!ENTITY noscriptAutoAllowTopLevel "সাময়িকভাবে ডিফলà§à¦Ÿà¦°à§‚পে উপরের সà§à¦¤à¦°à§‡à¦° সাইট অনà§à¦®à§‹à¦¦à¦¨">
+<!ENTITY noscriptDescription "ফায়ারফকà§à¦¸à§‡à¦° জনà§à¦¯ অতিরিকà§à¦¤ সà§à¦°à¦•à§à¦·à¦¾: নোসà§à¦•à§à¦°à¦¿à¦ªà¦Ÿ শà§à¦§à§à¦®à¦¾à¦¤à§à¦° আপনার বিশà§à¦¬à¦¾à¦¸à¦¯à§‹à¦—à§à¦¯ à¦à¦²à¦¾à¦•à¦¾à¦°à¦‡ কাজ করবে (যেমন আপনার বাঙà§à¦•à§‡à¦° ওয়েবসাইট). বিশেষজà§à¦žà¦°à¦¾ রাজি হবে: ফায়ারফকà§à¦¸à§‡à¦° সতà§à¦¯à¦¿à¦‡ নিরাপদ হয় নোসà§à¦•à§à¦°à¦¿à¦ªà¦Ÿà§‡à¦° সঙà§à¦—ে :-)">
+<!ENTITY noscriptOptBlockCssScanners "বà§à¦²à¦• CSS ভিতà§à¦¤à¦¿à¦• সà§à¦•à§à¦¯à¦¾à¦¨à¦¾à¦°">
+<!ENTITY noscriptOptFilterXGet "কà§à¦°à¦¸ সাইট সনà§à¦¦à§‡à¦¹à¦œà¦¨à¦• অনà§à¦°à§‹à¦§ মà§à¦›à§à¦¨">
+<!ENTITY noscriptOptFilterXPost "ডাটা অ অনà§à¦°à§‹à¦§ পাবার মধà§à¦¯à§‡ কà§à¦°à¦¸ সাইটের অনà§à¦°à§‹à¦§ চালà§">
+<!ENTITY noscriptShowConsole "কনসোল দেখান ...">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS পà§à¦°à¦¶à§à¦¨">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "বিপজà§à¦œà¦¨à¦• রিলোড">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "XSSবিরোধী সà§à¦°à¦•à§à¦·à¦¾ বà§à¦¯à¦¤à§€à¦•à§à¦°à¦®">
+<!ENTITY noscriptXssExceptions.description "Destinations matching these regular expressions will NOT be protected against XSS.">
+<!ENTITY noscriptMatchSample "পà§à¦¯à¦¾à¦Ÿà¦¾à¦°à§à¦¨ মà§à¦¯à¦¾à¦šà¦¿à¦‚ নমà§à¦¨à¦¾:">
+<!ENTITY noscriptReset "পà§à¦¨à¦°à¦¾à¦¯à¦¼ বসান">
+<!ENTITY noscriptReset.accesskey "s">
+<!ENTITY noscriptResetDef "ডিফলà§à¦Ÿ রিসেট">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "অসà§à¦¥à¦¾à¦¯à¦¼à§€ অনà§à¦®à¦¤à¦¿ পà§à¦°à¦¤à§à¦¯à¦¾à¦¹à¦¾à¦°">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "অনিরà§à¦­à¦°à¦¯à§‹à¦—à§à¦¯ হিসাবে চিহà§à¦¨à¦¿à¦¤ সাইট থেকে আসছে অবজেকà§à¦Ÿà§‡à¦° জনà§à¦¯ কোন সà§à¦¥à¦¾à¦¨à¦§à¦¾à¦°à¦•">
+<!ENTITY noscriptCollapseBlockedObjects "সঙà§à¦•à§à¦šà¦¿à¦¤ বà§à¦²à¦• বসà§à¦¤à§">
+<!ENTITY noscriptExceptions "বà§à¦¯à¦¤à¦¿à¦•à§à¦°à¦®à¦—à§à¦²à¦¿ ...">
+<!ENTITY noscriptBlockedObjects "অবরà§à¦¦à§à¦§ সামগà§à¦°à§€">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "অনিরà§à¦­à¦°à¦¯à§‹à¦—à§à¦¯ সাইটগà§à¦²à¦¿ থেকে আসা পà§à¦°à¦¤à¦¿à¦Ÿà¦¿ সামগà§à¦°à§€ অবরà§à¦¦à§à¦§ করা হবে">
+<!ENTITY noscriptTempAllowPage "সাময়িকভাবে à¦à¦‡ সাইটের সব মঞà§à¦œà§à¦°">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "à¦à¦‡ সাইটের সব মঞà§à¦œà§à¦°">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "পৃষà§à¦ à¦¾ অনà§à¦®à¦¤à¦¿ সà§à¦¥à¦¾à¦¯à¦¼à§€ করা">
+<!ENTITY noscriptTempToPerm.accesskey "M">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS পà§à¦°à¦¶à§à¦¨à¦¾à¦¬à¦²à§€...">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "আচরণ">
+<!ENTITY noscriptHttps.cookies "কà§à¦•à¦¿">
+<!ENTITY noscriptHttps.description "(HTTPS) সংযোগ ছাড়া সকà§à¦°à¦¿à§Ÿ ওয়েবসাইটের বিষয়বসà§à¦¤à§ নিষিদà§à¦§">
+<!ENTITY noscriptHttps.never "কখনতà§à¦¤ না">
+<!ENTITY noscriptHttps.proxy "যখন à¦à¦•à¦Ÿà¦¿ পà§à¦°à¦•à§à¦¸à¦¿ বà§à¦¯à¦¬à¦¹à¦¾à¦°">
+<!ENTITY noscriptHttps.always "সরà§à¦¬à¦¦à¦¾">
+<!ENTITY noscriptHttpsForced "নিমà§à¦¨à¦²à¦¿à¦–িত সাইটগà§à¦²à¦¿ (HTTPS) সংযোগ বà§à¦¯à¦¾à¦¬à¦¹à¦¾à¦°à§‡à¦° জনà§à¦¯ বাধà§à¦¯ করা">
+<!ENTITY noscriptHttpsForcedExceptions "নিরাপদ নিমà§à¦¨à¦²à¦¿à¦–িত সাইটগà§à¦²à¦¿ জনà§à¦¯ (HTTPS) সংযোগে জোর করা হবেনাঃ">
+<!ENTITY noscriptSecureCookies "সà§à¦¬à¦¯à¦¼à¦‚কà§à¦°à¦¿à¦¯à¦¼ নিরাপদ কà§à¦•à¦¿ মà§à¦¯à¦¾à¦¨à§‡à¦œà¦®à§‡à¦¨à§à¦Ÿ সকà§à¦°à¦¿à¦¯à¦¼">
+<!ENTITY noscriptSecureCookiesForced "বিপজà§à¦œà¦¨à¦• নিমà§à¦¨à¦²à¦¿à¦–িত সাইটগà§à¦²à¦¿à¦° মধà§à¦¯à§‡ HTTPS উপর সেট কà§à¦•à¦¿ উপেকà§à¦·à¦¾ করà§à¦¨à¦ƒ">
+<!ENTITY noscriptSecureCookiesExceptions "বিপজà§à¦œà¦¨à¦• নিমà§à¦¨à¦²à¦¿à¦–িত সাইটগà§à¦²à¦¿à¦° মধà§à¦¯à§‡ HTTPS উপর সেট কà§à¦•à¦¿ উপেকà§à¦·à¦¾ করà§à¦¨:">
+<!ENTITY noscriptClearClickTitle "কà§à¦²à¦¿à§Ÿà¦¾à¦°à¦•à§à¦²à¦¿à¦• সতরà§à¦•à¦¬à¦¾à¦£à§€">
+<!ENTITY noscriptClearClickHeader "সমà§à¦­à¦¾à¦¬à§à¦¯ কà§à¦²à¦¿à¦•à¦œà¦¾à¦• / UI \'তে পà§à¦°à¦šà§‡à¦·à§à¦Ÿà¦¾ নিরাকরণ!">
+<!ENTITY noscriptClearClickDescription "নোসà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ à¦à¦•à¦Ÿà¦¿ আংশিকভাবে গোপন উপাদান দিয়ে à¦à¦•à¦Ÿà¦¿ মাউস বা কিবোরà§à¦¡ যোগাযোগ রূদà§à¦§. আটকান à¦à¦¬à¦‚ সà§à¦ªà¦·à§à¦Ÿ সংসà§à¦•à¦°à¦£à§‡à¦° মধà§à¦¯à§‡ চকà§à¦° নীচের ইমেজে কà§à¦²à¦¿à¦• করà§à¦¨.">
+<!ENTITY noscriptClearClickOpt "পৃষà§à¦ à¦¾ থেকে কà§à¦²à¦¿à§Ÿà¦¾à¦°à¦•à§à¦²à¦¿à¦• রকà§à¦·à¦¾ ...">
+<!ENTITY noscriptClearClickReport "পà§à¦°à¦¤à¦¿à¦¬à§‡à¦¦à¦¨">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "পà§à¦°à¦¤à¦¿à¦¬à§‡à¦¦à¦¨ আইডিঃ">
+<!ENTITY noscriptTrustedPagesAdj "বিশà§à¦¬à¦¾à¦¸à§€">
+<!ENTITY noscriptUntrustedPagesAdj "অনিরà§à¦­à¦°à¦¯à§‹à¦—à§à¦¯">
+<!ENTITY noscriptKeepLocked "à¦à¦‡ উপাদানটি বদà§à¦§ রাখà§à¦¨(পà§à¦°à¦¸à§à¦¤à¦¾à¦¬à¦¿à¦¤)">
+<!ENTITY noscriptEmbeddings "শোয়ান">
+<!ENTITY noscriptPrev "পূরà§à¦¬à¦¬à¦°à§à¦¤à§€">
+<!ENTITY noscriptNext "পরবরà§à¦¤à§€">
+<!ENTITY noscriptFrameOptErr.title "à¦à¦‡ সামগà§à¦°à§€ à¦à¦•à¦Ÿà¦¿ ফà§à¦°à§‡à¦®à§‡ দেখানো যাবে না">
+<!ENTITY noscriptFrameOptErr.desc "আপনার নিরাপতà§à¦¤à¦¾ রকà§à¦·à¦¾, à¦à¦‡ বিষয়বসà§à¦¤à§à¦° পà§à¦°à¦•à¦¾à¦¶à¦• à¦à¦Ÿà¦¿ à¦à¦•à¦Ÿà¦¿ ফà§à¦°à§‡à¦®à§‡ পà§à¦°à¦¦à¦°à§à¦¶à¦¨ করা সমà§à¦­à¦¬ নয়.">
+<!ENTITY noscriptFrameOptErr.link "নতà§à¦® উইনà§à¦¡à§‹à¦¤à§‡ খোলার জন à¦à¦–ানে কà§à¦²à¦¿à¦• করà§à¦¨">
+<!ENTITY noscriptBookmarkSync "নোসà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ কনফিগারেশন জমা করà§à¦¨ বà§à¦•à¦®à¦¾à¦°à§à¦•à§‡ সহজ সà§à¦¸à¦‚গতির জনà§à¦¯">
+<!ENTITY noscriptShowReleaseNotes "আপডেট রিলিজ নোট পà§à¦°à¦¦à¦°à§à¦¶à¦¨">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "নিয়ম সেটঃ">
+<!ENTITY ABE.enabled.label "সকà§à¦°à¦¿à¦¯à¦¼ ABE">
+<!ENTITY ABE.siteEnabled.label "সাইট তাদের নিজসà§à¦¬ বিধি সেট থেকে ধাকà§à¦•à¦¾ মঞà§à¦œà§à¦°">
+<!ENTITY ABE.edit.label "সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ ...">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "সকà§à¦°à¦¿à¦¯à¦¼">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "নিষà§à¦•à§à¦°à¦¿à§Ÿ">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "à¦à¦¾à¦²à¦¾à¦¨">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "মà§à¦›à§à¦¨">
+<!ENTITY noscriptRecentBlocked "সমà§à¦ªà§à¦°à¦¤à¦¿ বà§à¦²à¦• সাইট">
+<!ENTITY noscriptExternalFilters "বাহà§à¦¯à¦¿à¦• ফিলà§à¦Ÿà¦¾à¦°">
+<!ENTITY noscriptEF.enable "বাহà§à¦¯à¦¿à¦• ফিলà§à¦Ÿà¦¾à¦° সকà§à¦°à¦¿à¦¯à¦¼">
+<!ENTITY noscriptEF.add "নতà§à¦¨ ফিলà§à¦Ÿà¦¾à¦°...">
+<!ENTITY noscriptEF.executable "à¦à¦•à§à¦¸à¦¿à¦•à¦¿à¦‰à¦Ÿà§‡à¦¬à¦² ফাইলঃ">
+<!ENTITY noscriptEF.browse "বà§à¦°à¦¾à¦‰à¦œ...">
+<!ENTITY noscriptEF.contentType "বিষয়বসà§à¦¤à§ টাইপ (MIME) ফিলà§à¦Ÿà¦¾à¦° করা হবে (সঠিক মিল বা রেগà§à¦²à¦¾à¦° à¦à¦•à§à¦¸à¦ªà§à¦°à§‡à¦¶à¦¨):">
+<!ENTITY noscriptEF.exceptions "à¦à¦‡ সাইট থেকে আগত বসà§à¦¤à§ ফিলà§à¦Ÿà¦¾à¦° করবেন নাঃ">
+<!ENTITY noscriptEF.remove "অপসারণ">
+<!ENTITY noscriptPreset "নিরাপতà§à¦¤à¦¾à¦° মাতà§à¦°à¦¾">
+<!ENTITY noscriptPreset.off "বনà§à¦§ (আপনি কি গà§à¦°à§à¦¤à¦°?)">
+<!ENTITY noscriptPreset.low "সহজ যাচà§à¦›à§‡ (নিষিদà§à¦§ জিনিসের + ওয়েব নিরাপতà§à¦¤à¦¾)">
+<!ENTITY noscriptPreset.medium "কà§à¦²à¦¾à¦¸à¦¿à¦• (বিশà§à¦¦à§à¦§ + ওয়েব নিরাপতà§à¦¤à¦¾)">
+<!ENTITY noscriptPreset.high "দà§à¦°à§à¦— (সমà§à¦ªà§‚রà§à¦£ লকডাউন)">
+<!ENTITY noscript.hoverUI "অনà§à¦®à¦¤à¦¿ মেনৠখà§à¦²à¦¬à§‡ যখন নোসà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ à¦à¦° আইকনের উপর মাউস নিয়ে যাওয়া হবে">
+<!ENTITY noscriptDonate "সাহাযà§à¦¯ করà§à¦¨">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptForbidWebGL "WebGL পà§à¦°à¦¤à¦¿à¦·à§‡à¦§ করà§à¦¨">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptTruncateTitle "Truncate document titles">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/bn-IN/noscript/noscript.properties b/extensions/noscript/chrome/locale/bn-IN/noscript/noscript.properties
new file mode 100644
index 0000000..2b47fcf
--- /dev/null
+++ b/extensions/noscript/chrome/locale/bn-IN/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ সরà§à¦¬à¦¤à§à¦° অনà§à¦®à§‹à¦¦à¦¿à¦¤(বিপজà§à¦œà¦¨à¦•)
+forbidGlobal=সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ সরà§à¦¬à¦¤à§à¦° নিষেধ(বিপজà§à¦œà¦¨à¦•)
+allowLocal=অনà§à¦®à§‹à¦¦à¦¿à¦¤ %S
+allowTemp=সà§à¦¥à¦¾à§Ÿà§€ অনà§à¦®à§‹à¦¦à¦¿à¦¤ %S
+forbidLocal=নিষেধ %S
+allowed.glb=বিপদ!সà§à¦•à§à¦°à¦¿à¦ªà¦Ÿ সরà§à¦¬à¦¤à§à¦° অনà§à¦®à§‹à¦¦à¦¿à¦¤
+allowed.yes=সà§à¦•à§à¦°à¦¿à¦ªà¦Ÿ à¦à¦–ন অনà§à¦®à§‹à¦¦à¦¿à¦¤
+allowed.prt=সà§à¦•à§à¦°à¦¿à¦ªà¦Ÿ আংশিকভাবে অনà§à¦®à§‹à¦¦à¦¿à¦¤
+allowed.no=সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ à¦à¦–ন নিষেধ
+global.warning.title=সাবধান!
+global.warning.text=Scripts are going to be allowed globally (for every site).\nThis is a potentially dangerous action.\nDo you really want to proceed?
+audio.samples=অডিও নমà§à¦¨à¦¾
+confirm=আপনি কি নিশà§à¦šà¦¿à¦¤?
+alwaysAsk=নিশà§à¦šà¦¿à¦¤à¦•à¦°à¦£ জনà§à¦¯ সরà§à¦¬à¦¦à¦¾ জিজà§à¦žà¦¾à¦¸à¦¾
+notifyHide=%S সেকেনà§à¦¡ পরে লà§à¦•à¦¾à¦“
+trust=%S বিশà§à¦¬à¦¾à¦¸à§€
+distrust=%S কে অনিরà§à¦­à¦°à¦¯à§‹à¦—à§à¦¯ হিসাবে চিহà§à¦¨à¦¿à¦¤
+untrustedOrigin=à¦à¦•à¦Ÿà¦¿ অনিরà§à¦­à¦°à¦¯à§‹à¦—à§à¦¯ উতà§à¦¸
+xss.notify.generic=নোসà§à¦•à§à¦°à¦¿à¦ªà¦Ÿ সমà§à¦­à¦¾à¦¬à§à¦¯ ফিলà§à¦Ÿà¦¾à¦° করেছে কà§à¦°à¦¸ সাইট সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿà¦¿à¦‚ (XSS) %S থেকে।কারিগরী বিবরণ কনসোলে লগ আউট হয়েছেন.
+xss.notify.showConsole=কনসোল দেখà§à¦¨...
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=সনà§à¦¦à§‡à¦¹à¦œà¦¨à¦• অনà§à¦°à§‹à¦§
+xss.reason.filterXGetRef=সনà§à¦¦à§‡à¦¹à¦œà¦¨à¦• অনà§à¦°à§‹à¦§ বিতারিত। ইউআরà¦à¦² [%1$S] [%2$S] থেকে অনà§à¦°à§‹à¦§à¥¤ বিতারন: [%3$S]।
+xss.reason.filterXPost=বিতারিত আপলোড [%1$S] থেকে [%2$S]তে: à¦à¦•à¦Ÿà¦¿ ডাউনলোড শà§à¦§à§à¦®à¦¾à¦¤à§à¦° অনà§à¦°à§‹à¦§ গেট রà§à¦ªà¦¾à¦¨à§à¦¤à¦°à¦¿à¦¤
+unsafeReload.warning=[%3$S] থেকে সনà§à¦¦à§‡à¦¹à¦œà¦¨à¦• রিলোডs\n\n%1$S [%2$S]\n\nনোসà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ à¦à¦‡ অনà§à¦°à§‹à¦§à¦Ÿà¦¿ রকà§à¦·à¦¾ করবে না!\n
+metaRefresh.notify=নোসà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ à¦à¦•à¦Ÿà¦¿ <META> আবরণীকে বà§à¦²à¦• করেছে <NOSCRIPT> উপাদান à¦à¦° মধà§à¦¯à§‡: %S ন %S সেকেনà§à¦¡à¥¤
+metaRefresh.notify.follow=পà§à¦¨à¦ƒ দিকনিরà§à¦¦à§‡à¦¶ অনà§à¦¸à¦°à¦£
+metaRefresh.notify.follow.accessKey=F
+notify.options=বিকলà§à¦ª
+notify.options.accessKey=O
+reset.title=নোসà§à¦•à§à¦°à¦¿à¦ªà¦Ÿ রিসেট
+reset.warning=সব নোসà§à¦•à§à¦°à¦¿à¦ªà¦Ÿ পছনà§à¦¦ à¦à¦¬à¦‚ সাইট অনà§à¦®à¦¤à¦¿ অবিলমà§à¦¬à§‡ তাদের ডিফলà§à¦Ÿ মান রিসেট হবে।\nà¦à¦‡ করà§à¦® পà§à¦°à¦¤à§à¦¯à¦¾à¦¬à¦°à§à¦¤à¦¨ হবে না।\nআপনি à¦à¦Ÿà¦¿ করতে চান?
+bookmarkSync.title=নোসà§à¦•à§à¦°à¦¿à¦ªà¦Ÿ কনফিগারেশন বà§à¦•à¦®à¦¾à¦°à§à¦•
+bookmarkSync.message=à¦à¦‡ বà§à¦•à¦®à¦¾à¦°à§à¦•à¦Ÿà¦¿ খোলা হবে না, কিনà§à¦¤à§‚ সà§à¦¸à¦‚গত করা যাবে Weave বা XMarks à¦à¦° মত à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à§à¦¸à¦¾à¦¨ দà§à¦¬à¦¾à¦°à¦¾à¥¤
+bookmarkSync.confirm=নোসà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ আপাতদৃষà§à¦Ÿà¦¿à¦¤à§‡ à¦à¦•à¦Ÿà¦¿ বà§à¦•à¦®à¦¾à¦°à§à¦• খà§à¦œà§‡ পেয়েছে যেটি রাখা আছে \n%S তে।\nআপনি কি সতà§à¦¯à¦¿à¦‡ à¦à¦‡ বà§à¦•à¦®à¦¾à¦°à§à¦• বিষয়বসà§à¦¤à§ মà§à¦›à§‡ নতà§à¦¨à¦Ÿà¦¿ আপনার সà§à¦¥à¦¾à¦¨à§€à¦“ নোসà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ কনফিগারেশনে রাখতে চান?
+ABE.notify=ABE কে %1$S ফিলà§à¦Ÿà¦¾à¦°à§‡à¦° জনà§à¦¯ অনà§à¦°à§‹à¦§à¦ƒ<%2$S> %3$S
+ABE.chooseEditor=ABE নিয়ম তৈরির জনà§à¦¯ à¦à¦•à¦Ÿà¦¿ টেকà§à¦¸à¦Ÿ à¦à¦¡à¦¿à¦Ÿà¦° নিরà§à¦¬à¦¾à¦šà¦¨ করà§à¦¨
+ABE.syntaxError=ABE নিয়ম তৈরিতে সিনটà§à¦¯à¦¾à¦•à§à¦¸ তà§à¦°à§à¦Ÿà¦¿
+ABE.wanIpAsLocal=ওয়ান আইপি (%S) ∈ LOCAL
+allowFrom=%S à¦à¦° সবকিছৠঅনà§à¦®à§‹à¦¦à¦¨
+allowTempFrom=%S সবকিছৠআপাতত অনà§à¦®à§‹à¦¦à¦¨
+siteInfo.confirm=আপনি \"%1$S\" সাইটটির জানতে চাইছেন\n%2$S কে অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ উপসà§à¦¥à¦¾à¦ªà¦• করতে।\nআপনি কি à¦à¦—িয়ে যেতে চান?
+siteInfo.tooltip=সাইট তথà§à¦¯ জানার জনà§à¦¯ মধà§à¦¯à¦® কà§à¦²à¦¿à¦• করà§à¦¨ অথবা শিফট + কà§à¦²à¦¿à¦• করà§à¦¨ ...
+ef.activate=ফিলà§à¦Ÿà¦¾à¦° %S
+ef.options=%S অপশন...
+ef.newName=নতà§à¦¨ ফিলà§à¦Ÿà¦¾à¦° à¦à¦° নাম লিখà§à¦¨à¦ƒ
+ef.locateExe=%S ফিলà§à¦Ÿà¦¾à¦° জনà§à¦¯ à¦à¦•à§à¦¸à¦¿à¦•à¦¿à¦‰à¦Ÿà§‡à¦¬à¦² ফাইল নিরà§à¦¬à¦¾à¦šà¦¨ করà§à¦¨...
+disable=%S নিষà§à¦•à§à¦°à¦¿à§Ÿ
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/ca-AD/noscript/about.properties b/extensions/noscript/chrome/locale/ca-AD/noscript/about.properties
new file mode 100644
index 0000000..9f662e3
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ca-AD/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Protecció addicional per al teu Firefox...
+aboutTitle=About %S
+extensionContributors=Contribuïdors:
+extensionContributors.tip=Persones a les quals heu d\'agrair aquesta extensió
+extensionCreatorLabel=Autor:
+changelog=Registre de canvis
+changelog.tip=Mostra el registre de canvis
+license=Llicència
+license.tip=Llegeix la llicència d\'usuari final
+logo.tip=Visita la web de l\'extensió
+sponsor.tip=Visita la web del patrocinador
+informaction.tip=Visita la pàgina d\'InformAction
+extensionHomepage.tip=Visita la pàgina de l\'extensió
+extensionCreator.tip=Visita la pàgina de l\'autor
+version=Versió %S
diff --git a/extensions/noscript/chrome/locale/ca-AD/noscript/noscript.dtd b/extensions/noscript/chrome/locale/ca-AD/noscript/noscript.dtd
new file mode 100644
index 0000000..6705ec3
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ca-AD/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opcions...">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Opcions de NoScript">
+<!ENTITY noscriptAbout "Quant a NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Podeu especificar quins llocs web poden executar seqüències. El tipus d&apos;adreça o el domini (p.ex. &quot;http://www.site.com&quot; o &quot;site.com&quot;) del lloc al qual voleu donar permissos i feu clic a Permet.">
+<!ENTITY noscriptWebAddress "Adreça del lloc web:">
+<!ENTITY noscriptAllow "Permet">
+<!ENTITY noscriptAllow.accesskey "A">
+<!ENTITY noscriptForbid "Prohibeix">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Marca com a de confiança">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Marca com a de no confiança">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Suprimeix els llocs seleccionats">
+<!ENTITY noscriptGloballyEnabled "El JavaScript és permès globalment (perillós)">
+<!ENTITY noscriptAutoReload "Recarrega automàticament les pàgines afectades en canviar els permisssos">
+<!ENTITY noscriptGeneral "General">
+<!ENTITY noscriptAppearance "Aparença">
+<!ENTITY noscriptShow "Mostra">
+<!ENTITY noscriptCtxMenu "Menú contextual">
+<!ENTITY noscriptStatusIcon "Icona de la barra d&apos;estat">
+<!ENTITY noscriptFullAddr "Adreces completes (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Dominis complets (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Dominis de segon nivell (noscript.net)">
+<!ENTITY noscriptTempCmd "Permet temporalment [...]">
+<!ENTITY noscriptSound "Reprodueix un so en blocar les seqüències">
+<!ENTITY noscriptImport "Importa">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exporta">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Mostra un missatge amb les seqüències blocades">
+<!ENTITY noscriptNotify.bottom "Col loca el missatge a la part de baix">
+<!ENTITY noscriptSound.choose "Tria">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Reprodueix">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Reinicia allò predeterminat">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Avançades">
+<!ENTITY noscriptAdditionalPermissions "Permissos addicionals per a llocs de confiança">
+<!ENTITY noscriptAllowClipboard "Permet copiar i enganxar text enriquit des d&apos;un porta-retalls extern">
+<!ENTITY noscriptAdditionalRestrictions "Restriccions addicionals per a llocs en què desconfieu">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Apply these restrictions to trusted sites too">
+<!ENTITY noscriptForbidJava "Prohibeix el Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Prohibeix el XSLT">
+<!ENTITY noscriptForbidSilverlight "Prohibeix el Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Prohibeix el &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Prohibeix el &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Prohibeix el @font-face">
+<!ENTITY noscriptForbidWebGL "Prohibeix el WebGL">
+<!ENTITY noscriptForbidMedia "Prohibeix el &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Prohibeix el Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Prohibeix d&apos;altres connectors">
+<!ENTITY noscriptReloadWarn "Aquestes opcions prenen efecte en pàgines noves o recarregades (manualment)">
+<!ENTITY noscriptConfirmUnblock "Demana confirmaci� abans de desblocar un objecte temporalment">
+<!ENTITY noscriptStatusLabel "Etiqueta de la barra d&apos;estat">
+<!ENTITY noscriptForbidBookmarklets "Prohibeix les Adreces d&apos;inter�s">
+<!ENTITY noscriptShowPlaceholder "Mostra-ne les icones">
+<!ENTITY noscriptTruncateTitle "Talla els títols dels documents">
+<!ENTITY noscriptFixLinks "Intenta arreglar els enllaços en JavaScript">
+<!ENTITY noscriptAllowBookmarks "Permet tots els llocs que trobes a les adreces d&apos;interès">
+<!ENTITY noscriptAllowViaBookmarks "Permet els indrets oberts mitjançant les adreces d&apos;interès">
+<!ENTITY noscriptAllowPing "Permet &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Perment enllaços locals">
+<!ENTITY noscriptForbidPing "Prohibeix &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Prohibeix redireccions META dins elements &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptWhitelist "Llista blanca">
+<!ENTITY noscriptPermissions "Permissos">
+<!ENTITY noscriptRefresh "Actualitza">
+<!ENTITY noscriptNotifications "Notificacions">
+<!ENTITY noscriptToolbarToggle "El botó esquerre en la barra de tasques de NoScript alterna els permissos per als llocs de nivell alt">
+<!ENTITY noscriptTrusted "De confiança">
+<!ENTITY noscriptUntrusted "Sense confiança">
+<!ENTITY noscriptUnknown "Desconegut">
+<!ENTITY noscriptAdd "Afegeix">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Tanca">
+<!ENTITY noscriptSiteManager "Gestor de llocs">
+<!ENTITY noscriptSecurityManager "Gestor de seguretat">
+<!ENTITY noscriptPolicies "Política">
+<!ENTITY noscriptDefaultPolicies "Actuació per defecte">
+<!ENTITY noscriptSitePolicies "Actuació per a un lloc específic">
+<!ENTITY noscriptNselNever "Amaga els elements &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Mostra els elements &lt;NOSCRIPT&gt; que segueixen a un &lt;SCRIPT&gt; blocat">
+<!ENTITY noscriptAutoAllowTopLevel "Temporalment permet per defecte el màxim nivell per als llocs web">
+<!ENTITY noscriptDescription "Protecció extra per al vostre Firefox: NoScript permet JavaScript, Java (i d&apos;altres connectors) només per a dominis de confiança de la vostra elecció (p.ex. el lloc web del vostre banc). Aquesta llista blanca de bloqueig preventiu prevé l&apos;explotació de vulnerabilitats de seguretat (les que coneixem i les que no!) sense perdre funcionalitat... Els experts hi estan d&apos;acord: Firefox és realment més segur amb NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Bloca els escanejos basats en CSS">
+<!ENTITY noscriptOptFilterXGet "Saneja les peticions sospitoses a través d&apos;un lloc">
+<!ENTITY noscriptOptFilterXPost "Transforma les peticions POST a través d&apos;un lloc en peticions GET sense tantes dades">
+<!ENTITY noscriptShowConsole "Mostra la Consola...">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS PMF...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "No és segur recarregar">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Excepcions a la protecció anti-XSS">
+<!ENTITY noscriptXssExceptions.description "Les destinations que marquin aquestes expressions regulars NO seran protegides de XSS">
+<!ENTITY noscriptMatchSample "Mostra de patró de marcat:">
+<!ENTITY noscriptReset "Reinicia">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Reinicia a allò per defecte">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revocar els permisos temporals">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "No marcador de posició d&apos;objectes procedents de llocs marcats com a no confiables">
+<!ENTITY noscriptCollapseBlockedObjects "Tancar els objectes bloquejats">
+<!ENTITY noscriptExceptions "Excepcions...">
+<!ENTITY noscriptBlockedObjects "Objectes Bloquejats">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Bloquejar tots els objectes procedents de llocs marcats com a no confiables">
+<!ENTITY noscriptTempAllowPage "Temporalment permet tota aquesta pàgina">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Accepta tot el d&apos;aquesta pàgina">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Dona permisos permanentment">
+<!ENTITY noscriptTempToPerm.accesskey "d">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Comportament">
+<!ENTITY noscriptHttps.cookies "Galetes">
+<!ENTITY noscriptHttps.description "Prohibir contingut web a no ser que es tracti d&apos;una connexió segura (HTTPS):">
+<!ENTITY noscriptHttps.never "Mai">
+<!ENTITY noscriptHttps.proxy "Quan usi un proxy (recomanat amb Tor)">
+<!ENTITY noscriptHttps.always "Sempre">
+<!ENTITY noscriptHttpsForced "Forçar el seguir llocs que usin connexions segures (HTTPS):">
+<!ENTITY noscriptHttpsForcedExceptions "Mai forçar llocs que usin connexions segures (HTTPS):">
+<!ENTITY noscriptSecureCookies "Activar Manegament Automàtic de Galetes Segures">
+<!ENTITY noscriptSecureCookiesForced "Forçar encriptació per totes les galetes creades amb HTTPS pels següents llocs:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignorar galetes insegures creades amb HTTPS pels següents llocs:">
+<!ENTITY noscriptClearClickTitle "Advertència ClearClick">
+<!ENTITY noscriptClearClickHeader "Clickjacking Potencial / Intent de corregir UI">
+<!ENTITY noscriptClearClickDescription "NoScript ha interceptat una interacció de ratolí o reclat amb parcialment element ocult. Clica a la imatge superior per passar de la obstrucció a una versió neta.">
+<!ENTITY noscriptClearClickOpt "Protecció de ClearClick a les pàgines...">
+<!ENTITY noscriptClearClickReport "Reportar">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "de confiança">
+<!ENTITY noscriptUntrustedPagesAdj "de no confiança">
+<!ENTITY noscriptKeepLocked "Mantenir aquest element bloquejat (recomanat)">
+<!ENTITY noscriptEmbeddings "Objectes Incrustats">
+<!ENTITY noscriptPrev "Anterior">
+<!ENTITY noscriptNext "Següent">
+<!ENTITY noscriptFrameOptErr.title "Aquest contingut no pot ser visualitzat en un marc">
+<!ENTITY noscriptFrameOptErr.desc "Per protegir la teva seguretat, l&apos;editor d&apos;aquest contingut no té permís per mostrar-t&apos;ho en un marc.">
+<!ENTITY noscriptFrameOptErr.link "Clica aquí per obrir aquest contingut en una nova finestra">
+<!ENTITY noscriptBookmarkSync "Guarda la configuració de NoScript en una còpia de seguretat per a una major facilitat de sincronització.">
+<!ENTITY noscriptShowReleaseNotes "Mostrar les notes de llançament en les actualitzacions">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Activar ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Permetre que els llocs web proposin les seves normes">
+<!ENTITY ABE.edit.label "Editar...">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Activar">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Desactivar">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Actualitzar">
+<!ENTITY ABE.refresh.accesskey "r">
+<!ENTITY noscriptUninstall "Desinatal·lar">
+<!ENTITY noscriptRecentBlocked "Llocs bloquejats recentment">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/ca-AD/noscript/noscript.properties b/extensions/noscript/chrome/locale/ca-AD/noscript/noscript.properties
new file mode 100644
index 0000000..e30ad49
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ca-AD/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Permet JavaScript totalment (perillós)
+forbidGlobal=Prohibeix JavaScript totalment (aconsellat)
+allowLocal=Permet %S
+allowTemp=Admet %S temporalment
+forbidLocal=Prohibeix %S
+allowed.glb=Alerta! Heu permès JavaScript totalment
+allowed.yes=A hores d\'ara, teniu el JavaScript permès
+allowed.prt=A hores d\'ara, teniu el JavaScript permès parcialment
+allowed.no=A hores d\'ara, teniu el JavaScript prohibit
+global.warning.title=Alerta!
+global.warning.text=Aneu a permetre JavaScript (per a tots els llocs).\n És una acció potencialment perillosa.\nRealment voleu fer-ho?
+audio.samples=Mostres d\'àudio
+confirm=N\'esteu segur?
+alwaysAsk=Demana\'m sempre confirmació
+notifyHide=Amaga-ho després de %S segons
+trust=Confia en %S
+distrust=Desconfia en %S
+untrustedOrigin=Té un origen poc fiable
+xss.notify.generic=He filtrat un intent de travessar el lloc mitjançant un programa (XSS) de des de %S. Els detalls tècnics han estat apuntats a la Consola.
+xss.notify.showConsole=Mostra la Consola
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=He netejat una petició sospitosa. La URL d\'origen és [%1$S], sol·licitada des de [%2$S]. URL sanejada: [%3$S].
+xss.reason.filterXGetRef=He netejat una petició de referència sospitosa. La URL [%1$S] s\'ha demanat des de [%2$S]. Referència sanejada: [%3$S].
+xss.reason.filterXPost=He netejat una càrrega sospitosa cap a [%1$S] des de [%2$S] i l\'he transformada en una petició GET de només baixada.
+unsafeReload.warning=NO ÉS SEGUR recarregar un \n\n%1$S [%2$S]\n\n sospitós des de [%3$S]\n\n . NoScript no protegirà aquesta petició!\n
+metaRefresh.notify=NoScript ha blocat un redireccionament <META> dins un element <NOSCRIPT>: %S en %S segons.
+metaRefresh.notify.follow=Segueix el redireccionament
+metaRefresh.notify.follow.accessKey=F
+notify.options=Opcions
+notify.options.accessKey=O
+reset.title=Reinicia NoScript
+reset.warning=TOTES les preferències de NoScript i els permissos per a tots els llocs seran reiniciats als seus valors tot seguit.\nNo podeu revocar aquesta acció. Voleu continuar?
+bookmarkSync.title=Guardar Configuració de NoScript
+bookmarkSync.message=Aquest marcador no pretén ser obert, sinó que es sincronitza mitjançant un servei com Weave o l\'extensió XMarks.
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark\'s content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Si us plau selecciona un editor de text per a les normes ABE
+allowFrom=Permetre tot de %S
+allowTempFrom=Permet temporalment tot de
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/cs-CZ/noscript/about.properties b/extensions/noscript/chrome/locale/cs-CZ/noscript/about.properties
new file mode 100644
index 0000000..066b2e2
--- /dev/null
+++ b/extensions/noscript/chrome/locale/cs-CZ/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Mimořádná ochrana pro váš Firefox: NoScript povoluje JavaScript, Javu (a další zásuvné moduly) pouze pro důvÄ›ryhodné servery dle vaÅ¡eho výbÄ›ru (napÅ™. vaÅ¡e stránka pro home-banking). Tento seznam důvÄ›ryhodných serverů založený na preventivním blokování přístupu pÅ™edchází zneužití bezpeÄnostních dÄ›r (známých a dokonce i neznámých!) bez jakékoli ztráty na funkÄnosti... Odborníci budou souhlasit: Firefox je skuteÄnÄ› bezpeÄnÄ›jší s rozšířením NoScript :-)
+aboutTitle=O %S
+extensionContributors=Spolupracovníci:
+extensionContributors.tip=Lidé, kterým vdÄ›Äíme za toto rozšíření
+extensionCreatorLabel=Autor:
+changelog=Seznam změn
+changelog.tip=Zobrazit seznam změn
+license=Licence
+license.tip=PÅ™eÄíst licenci pro koncové uživatele
+logo.tip=Navštívit domovskou stránku rozšíření
+sponsor.tip=Navštívit domovskou stránku sponzora
+informaction.tip=Navštívit domovskou stránku InformAction
+extensionHomepage.tip=Navštívit domovskou stránku rozšíření
+extensionCreator.tip=Navštívit domovskou stránku autora
+version=Verze %S
diff --git a/extensions/noscript/chrome/locale/cs-CZ/noscript/noscript.dtd b/extensions/noscript/chrome/locale/cs-CZ/noscript/noscript.dtd
new file mode 100644
index 0000000..0a1889f
--- /dev/null
+++ b/extensions/noscript/chrome/locale/cs-CZ/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Nastavení...">
+<!ENTITY noscriptOptions.accesskey "N">
+<!ENTITY noscriptOptionsLong "Nastavení NoScript">
+<!ENTITY noscriptAbout "O rozšíření NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Můžete si zvolit, které webové stránky mají povoleno spouštět skripty. Zadejte adresu (např. http://www.site.com nebo site.com) na které se nachází stránka, pro kterou chcete skripty povolit a klepněte na Povolit.">
+<!ENTITY noscriptWebAddress "Adresa webové stránky:">
+<!ENTITY noscriptAllow "Povolit">
+<!ENTITY noscriptAllow.accesskey "P">
+<!ENTITY noscriptForbid "Zakázat">
+<!ENTITY noscriptForbid.accesskey "Z">
+<!ENTITY noscriptTrust "OznaÄit jako důvÄ›ryhodný">
+<!ENTITY noscriptTrust.accesskey "d">
+<!ENTITY noscriptUntrust "OznaÄit jako nedůvÄ›ryhodný">
+<!ENTITY noscriptUntrust.accesskey "n">
+<!ENTITY noscriptRemoveSelected "Odstranit vybrané stránky">
+<!ENTITY noscriptGloballyEnabled "JavaScript celkovÄ› povolit (nebezpeÄné)">
+<!ENTITY noscriptAutoReload "Automaticky aktualizovat stránky při změně povolení">
+<!ENTITY noscriptGeneral "Obecné">
+<!ENTITY noscriptAppearance "Zobrazení">
+<!ENTITY noscriptShow "Zobrazit...">
+<!ENTITY noscriptCtxMenu "Místní nabídka">
+<!ENTITY noscriptStatusIcon "Ikona ve stavovém řádku">
+<!ENTITY noscriptFullAddr "Úplné adresy (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Úplné domény (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Domény druhého řádu (noscript.net)">
+<!ENTITY noscriptTempCmd "DoÄasnÄ› povolit [...]">
+<!ENTITY noscriptSound "Přehrát zvuk pokud jsou skripty zablokovány">
+<!ENTITY noscriptImport "Otevřít">
+<!ENTITY noscriptImport.accesskey "O">
+<!ENTITY noscriptExport "Uložit">
+<!ENTITY noscriptExport.accesskey "U">
+<!ENTITY noscriptNotify "Zobrazovat zprávu o blokovaných skriptech">
+<!ENTITY noscriptNotify.bottom "Umístit zprávu do spodní Äásti">
+<!ENTITY noscriptSound.choose "Zvolit">
+<!ENTITY noscriptSound.choose.accesskey "Z">
+<!ENTITY noscriptSound.play "Přehrát">
+<!ENTITY noscriptSound.play.accesskey "h">
+<!ENTITY noscriptSound.reset "Nastavit výchozí">
+<!ENTITY noscriptSound.reset.accesskey "v">
+<!ENTITY noscriptAdvanced "PokroÄilé">
+<!ENTITY noscriptAdditionalPermissions "DodateÄná povolení pro důvÄ›ryhodné stránky">
+<!ENTITY noscriptAllowClipboard "Povolit kopírování a vkládání textu z vnější schránky">
+<!ENTITY noscriptAdditionalRestrictions "DodateÄná omezení pro nedůvÄ›ryhodné stránky">
+<!ENTITY noscriptPlugins "Zásuvné moduly">
+<!ENTITY noscriptContentBlocker "Použít tato omezení i pro důvěryhodné stránky">
+<!ENTITY noscriptForbidJava "Zakázat Java™">
+<!ENTITY noscriptForbidXSLT "Zakázat XSLT">
+<!ENTITY noscriptForbidSilverlight "Zakázat Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Zakázat &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Zakázat &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Zakázat @font-face">
+<!ENTITY noscriptForbidWebGL "Zakázat WebGL">
+<!ENTITY noscriptForbidMedia "Zakázat &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Zakázat Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Zakázat ostatní zásuvné moduly">
+<!ENTITY noscriptReloadWarn "Tato nastavení se projeví u nově otevřených nebo (manuálně) aktualizovaných stránkách">
+<!ENTITY noscriptConfirmUnblock "Požadovat potvrzení pÅ™i doÄasném povolení objektu">
+<!ENTITY noscriptStatusLabel "Zobrazovat popisek ve stavovém řádku">
+<!ENTITY noscriptForbidBookmarklets "Zakázat bookmarklety">
+<!ENTITY noscriptShowPlaceholder "Zobrazovat zástupnou ikonu">
+<!ENTITY noscriptTruncateTitle "Zkrátit titulek stránky">
+<!ENTITY noscriptFixLinks "Pokusit se opravit odkazy tvořené JavaScriptem">
+<!ENTITY noscriptAllowBookmarks "Povolit stránky otevřené ze záložek">
+<!ENTITY noscriptAllowViaBookmarks "Povolit stránky otevřené ze záložek">
+<!ENTITY noscriptAllowPing "Povolit &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Povolit místní odkazy">
+<!ENTITY noscriptForbidPing "Zakázat &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Zakázat META přesměrování uvnitř elementů &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "M">
+<!ENTITY noscriptWhitelist "Výjimky">
+<!ENTITY noscriptPermissions "Povolení">
+<!ENTITY noscriptRefresh "Obnovení">
+<!ENTITY noscriptNotifications "Oznámení">
+<!ENTITY noscriptToolbarToggle "Klepnutí levým tlaÄítkem myÅ¡i na ikonku Noscriptu ve stavovém řádku pÅ™epíná povolení pro doménu nejvyšší úrovnÄ› aktuální stránky">
+<!ENTITY noscriptTrusted "Důvěryhodné">
+<!ENTITY noscriptUntrusted "Nedůvěryhodné">
+<!ENTITY noscriptUnknown "Neznámé">
+<!ENTITY noscriptAdd "Přidat">
+<!ENTITY noscriptAdd.accesskey "P">
+<!ENTITY noscriptClose "Zavřít">
+<!ENTITY noscriptSiteManager "Správce stránek">
+<!ENTITY noscriptSecurityManager "Správce zabezpeÄení">
+<!ENTITY noscriptPolicies "Politika">
+<!ENTITY noscriptDefaultPolicies "Výchozí politika">
+<!ENTITY noscriptSitePolicies "Politika pro specifické stránky">
+<!ENTITY noscriptNselNever "Zakázat prvky &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Zobrazit prvek &lt;NOSCRIPT&gt; následující po zablokovaném prvku &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "DoÄasnÄ› povolit stránky domény nejvyšší úrovnÄ›">
+<!ENTITY noscriptDescription "Mimořádná ochrana pro váš Firefox: NoScript povoluje JavaScript, Javu (a další zásuvné moduly) pouze pro důvÄ›ryhodné servery dle vaÅ¡eho výbÄ›ru (napÅ™. vaÅ¡e stránka pro home-banking). Tento seznam důvÄ›ryhodných serverů založený na preventivním blokování přístupu pÅ™edchází zneužití bezpeÄnostních dÄ›r (známých a dokonce i neznámých!) bez jakékoli ztráty na funkÄnosti... Odborníci budou souhlasit: Firefox je skuteÄnÄ› bezpeÄnÄ›jší s rozšířením NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Blokovat skenery založené na CSS">
+<!ENTITY noscriptOptFilterXGet "Zajistit podezřelé původce požadavku">
+<!ENTITY noscriptOptFilterXPost "PÅ™evést požadavky POST napÅ™Ã­Ä stránkou na požadavky GET neobsahující data.">
+<!ENTITY noscriptShowConsole "Zobrazit konzolu...">
+<!ENTITY noscriptShowConsole.accesskey "k">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS - Äasto kladené otázky">
+<!ENTITY noscriptXssFaq.accesskey "o">
+<!ENTITY noscriptUnsafeReload "Riskantní aktualizace">
+<!ENTITY noscriptUnsafeReload.accesskey "a">
+<!ENTITY noscriptXssExceptions "Ochrana proti XSS - výjimky">
+<!ENTITY noscriptXssExceptions.description "Cíle vyhovující tÄ›mto regulárním výrazům NEBUDOU CHRÃNÄšNY proti XSS">
+<!ENTITY noscriptMatchSample "Ukázka vyhovující vzoru:">
+<!ENTITY noscriptReset "Vynulovat">
+<!ENTITY noscriptReset.accesskey "V">
+<!ENTITY noscriptResetDef "Výchozí nastavení">
+<!ENTITY noscriptResetDef.accesskey "z">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "ZruÅ¡it doÄasná povolení">
+<!ENTITY noscriptRevokeTemp.accesskey "Ä">
+<!ENTITY noscriptNoUntrustedPlaceholder "Nezobrazovat zástupnou ikonu pro objekty pocházející z nedůvěryhodných stránek">
+<!ENTITY noscriptCollapseBlockedObjects "Skrýt zablokované objekty">
+<!ENTITY noscriptExceptions "Výjimky">
+<!ENTITY noscriptBlockedObjects "Blokované objekty">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Blokovat každý objekt pocházející z nedůvěryhodné stránky">
+<!ENTITY noscriptTempAllowPage "DoÄasnÄ› povolit celou stránku">
+<!ENTITY noscriptTempAllowPage.accesskey "D">
+<!ENTITY noscriptAllowPage "Povolit pro celou stránku">
+<!ENTITY noscriptAllowPage.accesskey "s">
+<!ENTITY noscriptTempToPerm "Udělit trvale povolení pro tuto stránku">
+<!ENTITY noscriptTempToPerm.accesskey "t">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behavior">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image above to cycle beetween the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Embedded Objects">
+<!ENTITY noscriptPrev "Previuous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/cs-CZ/noscript/noscript.properties b/extensions/noscript/chrome/locale/cs-CZ/noscript/noscript.properties
new file mode 100644
index 0000000..681ad3d
--- /dev/null
+++ b/extensions/noscript/chrome/locale/cs-CZ/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=JavaScript celkovÄ› povolit (nebezpeÄné)
+forbidGlobal=JavaScript celkovÄ› zakázat (doporuÄeno)
+allowLocal=Povolit %S
+allowTemp=DoÄasnÄ› povolit %S
+forbidLocal=Zakázat %S
+allowed.glb=NebezpeÄí! JavaScript je celkovÄ› povolen
+allowed.yes=JavaScript je aktuálně povolen
+allowed.prt=JavaScript je ÄásteÄnÄ› povolen
+allowed.no=JavaScript je aktuálně zakázán
+global.warning.title=Upozornění!
+global.warning.text=JavaScript bude nyní celkovÄ› povolen (pro vÅ¡echny stránky).\n Toto je potenciálnÄ› nebezpeÄné jednání.\nOpravdu chcete pokraÄovat?
+audio.samples=Zvukové soubory
+confirm=Jste si jist(a)?
+alwaysAsk=Vždy požadovat potvrzení
+notifyHide=Skrýt po %S vteřinách
+trust=Přidat %S mezi důvěryhodné
+distrust=Přidat %S mezi nedůvěryhodné
+untrustedOrigin=nedůvěryhodný původ
+xss.notify.generic=NoScript zachytil možný pokus o narušení webové stránky (tzv. cross-site scripting) od %S. Technické podrobnosti byly zaznamenány do chybové konzoly.
+xss.notify.showConsole=Zobrazit konzolu...
+xss.notify.showConsole.accessKey=k
+xss.reason.filterXGet=Zajištěn podezřelý požadavek. Původní URL [%1$S] bylo vyžádáno od [%2$S]. Zajištěné URL: [%3$S].)
+xss.reason.filterXGetRef=Zajištěn podezřelý původce požadavku. URL [%1$S] bylo vyžádáno od [%2$S]. Zajištěný požadavek: [%3$S].)
+xss.reason.filterXPost=Zajištěn podezřelý upload na [%1$S] z [%2$S]: převeden na požadavek GET pouze pro download.
+unsafeReload.warning=RISKANTNà aktualizování podezřelého\n\n%1$S [%2$S]\n\nZ [%3$S]\n\nNoScript NEBUDE BLOKOVAT tento požadavek!
+metaRefresh.notify=NoScript zablokoval <META> přesměrování uvnitř elementu <NOSCRIPT> %S během %S sekund.
+metaRefresh.notify.follow=UskuteÄnit pÅ™esmÄ›rování
+metaRefresh.notify.follow.accessKey=U
+notify.options=Nastavení
+notify.options.accessKey=N
+reset.title=NoScript - výchozí nastavení
+reset.warning=VeÅ¡kerá nastavení a výjimky stránek NoScriptu budou nyní nastavena na výchozí hodnoty.\nPotvrzení této volby nemůže být vráceno zpÄ›t.\nChcete pokraÄovat?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark's content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/cy-GB/noscript/about.properties b/extensions/noscript/chrome/locale/cy-GB/noscript/about.properties
new file mode 100644
index 0000000..c0372c2
--- /dev/null
+++ b/extensions/noscript/chrome/locale/cy-GB/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Diogelwch ychwanegol ar gyfer Firefox: bydd NoScript yn caniatau JavaScript, Java (ac atodynnau eraill) dim ond ar gyfer y parthau dilys yr ydych chi wedi'u dewis (e.e. eich wefan bancio gartref). Mae'r dull rhwystro rhag blaen seiliedig ar wenrestr hwn yn atal camddefnyddio gwendidau diogelwch (hysbys a hyd yn oed anhysbys) heb golli unrhyw alluoedd... Bydd arbennigwyr yn cydsynio: gwirioneddol safach yw Firefox gyda NoScript :-)
+aboutTitle=Ynghylch %S
+extensionContributors=Cyfrannwyr:
+extensionContributors.tip=Y sawl dylech ddiolch iddynt ar gyfer yr estyniad hwn
+extensionCreatorLabel=Awdur:
+changelog=Log newidiadau
+changelog.tip=Dangos y log newidiadau
+license=Trwydded
+license.tip=Darllen trwydded y defnyddiwr terfynol
+logo.tip=Ymweld â hafan yr atodiad
+sponsor.tip=Ymweld â hafan y noddwr
+informaction.tip=Ymweld â hafan InformAction
+extensionHomepage.tip=Ymweld â hafan yr atodiad
+extensionCreator.tip=Ymweld â hafan yr awdur
+version=Fersiwn %S
diff --git a/extensions/noscript/chrome/locale/cy-GB/noscript/noscript.dtd b/extensions/noscript/chrome/locale/cy-GB/noscript/noscript.dtd
new file mode 100644
index 0000000..c390ef0
--- /dev/null
+++ b/extensions/noscript/chrome/locale/cy-GB/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opsiynau">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Opsiynau NoScript">
+<!ENTITY noscriptAbout "Yngylch NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Cewch enwi pa wefannau sy&apos;n cael rhedeg sgriptiau. Teipiwch gyfeiriad neu barth (e.e. &quot;http://www.site.com&quot; neu &quot;site.com&quot;) y safle rydych eisiau ei ganiatau ac wedyn cliciwch Caniatau.">
+<!ENTITY noscriptWebAddress "Cyfeiriad wefan">
+<!ENTITY noscriptAllow "Caniatau">
+<!ENTITY noscriptAllow.accesskey "I">
+<!ENTITY noscriptForbid "Gwahardd">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Marcio&apos;n Ddilys">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Marcio&apos;n Annilys">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Diddymu&apos;r Wefannau Sydd Wedi&apos;u Dewis">
+<!ENTITY noscriptGloballyEnabled "Caniateir sgriptiau ymhobman (peryglus)">
+<!ENTITY noscriptAutoReload "Ail-lwytho&apos;n awtomatig y tudalennau sydd wedi&apos;u haffeithio wrth fod hawliau&apos;n newid.">
+<!ENTITY noscriptGeneral "Cyffredinol">
+<!ENTITY noscriptAppearance "Ymddangosiad">
+<!ENTITY noscriptShow "Dangos...">
+<!ENTITY noscriptCtxMenu "Dewislen gyd-destunol">
+<!ENTITY noscriptStatusIcon "Eicon y bar statws">
+<!ENTITY noscriptFullAddr "Cyfeiriadau llawn (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Parthau llawn (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Sylfaen Parthau&apos;r 2ail lefel (noscript.net)">
+<!ENTITY noscriptTempCmd "Caniatau dros dro [...]">
+<!ENTITY noscriptSound "Adborth clywedol pan fydd sgriptiau wedi&apos;u rhwystro">
+<!ENTITY noscriptImport "Mewnforio">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Allforio">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Dangos negeseuon am sgriptiau sydd wedi&apos;u rhwystro">
+<!ENTITY noscriptNotify.bottom "Lleoli negeseuon ar y gwaelod">
+<!ENTITY noscriptSound.choose "Dewis">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Chwarae">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Ailosod y diffygwerth">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Uwch">
+<!ENTITY noscriptAdditionalPermissions "Hawliau ychwanegol ar gyfer wefannau dilys">
+<!ENTITY noscriptAllowClipboard "Caniatau copi testun bras o&apos;r clip-fwrdd allanol">
+<!ENTITY noscriptAdditionalRestrictions "Rhwystau ychwanegol ar gyfer wefannau annilys">
+<!ENTITY noscriptPlugins "Atodyn">
+<!ENTITY noscriptContentBlocker "Rhoi&apos;r rhwystrau hyn ar waith ar wefannau dilys hefyd">
+<!ENTITY noscriptForbidJava "Gwahardd Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Gwahardd XSLT">
+<!ENTITY noscriptForbidSilverlight "Gwahardd Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Gwahardd &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Gwahardd &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Gwahardd @font-face">
+<!ENTITY noscriptForbidWebGL "Gwahardd WebGL">
+<!ENTITY noscriptForbidMedia "Gwahardd &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Gwahardd Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Gwahardd atodynnau eraill">
+<!ENTITY noscriptReloadWarn "Daw&apos;r opsiynau hyn i rym ar dudalennau newydd neu&apos;r rhai sydd wedi&apos;u ail-lwytho (trwy waith law)">
+<!ENTITY noscriptConfirmUnblock "Gofyn am gadarnhad cyn datrwystro gwrthrych dros dro">
+<!ENTITY noscriptStatusLabel "Label y bar statws">
+<!ENTITY noscriptForbidBookmarklets "Gwahardd nodau tudalen">
+<!ENTITY noscriptShowPlaceholder "Dangos eicon cadw lle">
+<!ENTITY noscriptTruncateTitle "Blaendorri teitlau dogfennau">
+<!ENTITY noscriptFixLinks "Ceisio trwsio dolennau JavaScript">
+<!ENTITY noscriptAllowBookmarks "Caniatau agor wefannau trwy nodau tudalen">
+<!ENTITY noscriptAllowViaBookmarks "Caniatau wefannau agorwyd trwy nodau tudalen">
+<!ENTITY noscriptAllowPing "Caniatau &lt;PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Caniatau dolennau lleol">
+<!ENTITY noscriptForbidPing "Gwahardd &lt;PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Gwahardd dargyfeiriadau META mewn elfennau &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptWhitelist "Gwenrestr">
+<!ENTITY noscriptPermissions "Hawliau">
+<!ENTITY noscriptRefresh "Adfywio">
+<!ENTITY noscriptNotifications "Hysbysiadau">
+<!ENTITY noscriptToolbarToggle "Clicio chwith ar far offer NoScript yn toglo hawliau ar gyfer y wefan lefel-uchaf presennol">
+<!ENTITY noscriptTrusted "Dilys">
+<!ENTITY noscriptUntrusted "Annilys">
+<!ENTITY noscriptUnknown "Anhysbys">
+<!ENTITY noscriptAdd "Ychwanegu">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Cau">
+<!ENTITY noscriptSiteManager "Rheolwr y wefannau">
+<!ENTITY noscriptSecurityManager "Rheolwr diogelwch">
+<!ENTITY noscriptPolicies "Polisiau">
+<!ENTITY noscriptDefaultPolicies "Polisiau diofyn">
+<!ENTITY noscriptSitePolicies "Polisiau penodol y wefan">
+<!ENTITY noscriptNselNever "Cuddio elfennau &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Dangos yr elfen &lt;NOSCRIPT&gt; sy&apos;n dilyn elfan &lt;SCRIPT&gt; waharddedig">
+<!ENTITY noscriptAutoAllowTopLevel "Caniatau&apos;n ddiofyn dros dro wefannau lefel-uchaf">
+<!ENTITY noscriptDescription "Diogelwch ychwanegol ar gyfer Firefox: bydd NoScript yn caniatau JavaScript, Java (ac atodynnau eraill) dim ond ar gyfer y parthau dilys yr ydych chi wedi&apos;u dewis (e.e. eich wefan bancio gartref). Mae&apos;r dull rhwystro rhag blaen seiliedig ar wenrestr hwn yn atal camddefnyddio gwendidau diogelwch (hysbys a hyd yn oed anhysbys) heb golli unrhyw alluoedd... Bydd arbennigwyr yn cydsynio: gwirioneddol safach yw Firefox gyda NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Rhwystro sganwyr CSS-seiliedig">
+<!ENTITY noscriptOptFilterXGet "Glanhau ceisiadau amheus traws wefannol">
+<!ENTITY noscriptOptFilterXPost "Trawsffurfio ceisiadau POST traws wefannol yn geisiadau GET">
+<!ENTITY noscriptShowConsole "Dangos y Consol...">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Ail-lwytho anniogel">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Eithriadau Amddiffyniad Gwrth-XSS">
+<!ENTITY noscriptXssExceptions.description "NI amddiffynir y cyrchfannau sy&apos;n cyfateb i&apos;r mynegiadau rheolaidd hyn yn erbyn XSS.">
+<!ENTITY noscriptMatchSample "Sampl cyfateb i batrwm:">
+<!ENTITY noscriptReset "Ailosod">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Ailosod y diffygwerthoedd">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Dirymu Hawliau Dros Dro">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "Dim lle i&apos;w gadw ar gyfer gwrthychau a ddaw o wefannau wedi&apos;u marcio&apos;n annilys">
+<!ENTITY noscriptCollapseBlockedObjects "Talfyrru gwrthrychau wedi&apos;u rhwystro">
+<!ENTITY noscriptExceptions "Eithriadau...">
+<!ENTITY noscriptBlockedObjects "Gwrthrychau wedi&apos;u rhywstro">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Rhwystro pob gwrthrych a ddaw o wefan wedi&apos;i marcio&apos;n annilys">
+<!ENTITY noscriptTempAllowPage "Caniatau y dudalen hon dros dro">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Caniatau y dudalen hon i gyd">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Sefydlogi hawliau tudalennau">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behavior">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image above to cycle beetween the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Embedded Objects">
+<!ENTITY noscriptPrev "Previuous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/cy-GB/noscript/noscript.properties b/extensions/noscript/chrome/locale/cy-GB/noscript/noscript.properties
new file mode 100644
index 0000000..9515cc0
--- /dev/null
+++ b/extensions/noscript/chrome/locale/cy-GB/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Caniatáu sgriptiau ymhobman (peryglus)
+forbidGlobal=Gwahardd sgriptiau ymhobman (argymhellwyd)
+allowLocal=Caniatáu %S
+allowTemp=Caniatáu %S dros dro
+forbidLocal=Gwahardd %S
+allowed.glb=Peryg! Caniateir sgriptiau ymhobman
+allowed.yes=Caniateir sgriptiau ar hyn o bryd
+allowed.prt=Caniateir sgriptiau yn rhannol
+allowed.no=Gwaherddir sgriptiau ar hyn o bryd
+global.warning.title=Rhybudd!
+global.warning.text=Ar fin caniatáu sgriptiau ymhobman (ar gyfer pob wefan).\nGweithred beryglus gallai hyn fod.\nYdych chi wir eisiau parhau?
+audio.samples=Samplau clywedol
+confirm=Ydych chi'n sicr?
+alwaysAsk=Gofyn pob tro am gadarnhad
+notifyHide=Cuddio ar ôl %S seconds
+trust=Ymddiried yn %S
+distrust=Marcio %S fel Amheus
+untrustedOrigin=tarddiad amheus
+xss.notify.generic=Hidlodd NoScript gais at sgriptio traws wefannau (XSS) gan %S. Logwyd y manylion technegol ar y Consol.
+xss.notify.showConsole=Dangos y Consol...
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Glanhawyd cais amheus. URL gwreiddiol [%1$S] ceisiwyd o [%2$S]. URL wedi ei lanhau: [%3$S].
+xss.reason.filterXGetRef=Glanhawyd cyfeiriwr cais amheus. URL [%1$S] ceisiwyd o [%2$S]. Cyfeiriwr wedi ei lanhau: [%3$S].
+xss.reason.filterXPost=Glanhawyd mewnlwyth amheus i [%1$S] o [%2$S]: trawsffurfiwyd yn gais GET llawrlwytho yn unig
+unsafeReload.warning=Ail-lwytho'n ANNIOGEL yr amheus\n\n%1$S[%2$S]\n\nO [%3$S]\n\nNI fydd NoScript yn diogelu y cais hwn!\n
+metaRefresh.notify=Rhwystrodd NoScript ddargyfeirio <META> mewn elfen <NOSCRIPT>: %S mewn %S eiliad.
+metaRefresh.notify.follow=Dilyn dargyfeiriad
+metaRefresh.notify.follow.accessKey=F
+notify.options=Opsiynau
+notify.options.accessKey=O
+reset.title=Ailosod NoScript
+reset.warning=Ailosodir yn syth HOLL ddewisiadau a hawliau safle NoScript i'w diffygwerthau.\nNi ellir gwirdroi'r weithred hon.\nYdych chi am barhau?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark's content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/da/noscript/about.properties b/extensions/noscript/chrome/locale/da/noscript/about.properties
new file mode 100644
index 0000000..de314b4
--- /dev/null
+++ b/extensions/noscript/chrome/locale/da/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Ekstra beskyttelse af din Firefox: NoScript tillader kun JavaScript, Java (og andre plugins) fra betroede domæner valgt af dig (f.eks. din netbanks hjemmeside). Denne whitelist-baserede forebyggende metode forhindrer udnyttelse af sikkerhedshuller (såvel kendte som ukendte!) uden tab af funktionalitet… Eksperter er enige: Firefox er mere sikker med NoScript :-)
+aboutTitle=Om %S
+extensionContributors=Bidragydere:
+extensionContributors.tip=Folk du burde takke for denne udvidelse
+extensionCreatorLabel=Udvikler:
+changelog=Ændringslog
+changelog.tip=Vis ændringslog
+license=Licens
+license.tip=Læs slutbrugerlicens
+logo.tip=Besøg udvidelsens hjemmeside
+sponsor.tip=Besøg sponsors hjemmeside
+informaction.tip=Besøg InformAction hjemmeside
+extensionHomepage.tip=Besøg udvidelsens hjemmeside
+extensionCreator.tip=Besøg udviklerens hjemmeside
+version=Version %S
diff --git a/extensions/noscript/chrome/locale/da/noscript/noscript.dtd b/extensions/noscript/chrome/locale/da/noscript/noscript.dtd
new file mode 100644
index 0000000..8eea3fd
--- /dev/null
+++ b/extensions/noscript/chrome/locale/da/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Indstillinger…">
+<!ENTITY noscriptOptions.accesskey "I">
+<!ENTITY noscriptOptionsLong "NoScript Indstillinger">
+<!ENTITY noscriptAbout "Om NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Du kan angive hvilke websteder der må udføre scripts. Indtast adresse eller domæne (f.eks. &quot;http://www.site.com&quot; eller &quot;site.com&quot;) på det websted du ønsker at tillade og klik på Tillad.">
+<!ENTITY noscriptWebAddress "Webstedets adresse:">
+<!ENTITY noscriptAllow "Tillad">
+<!ENTITY noscriptAllow.accesskey "T">
+<!ENTITY noscriptForbid "Forbyd">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Marker som betroet">
+<!ENTITY noscriptTrust.accesskey "B">
+<!ENTITY noscriptUntrust "Marker som ubetroet">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Fjern valgte websteder">
+<!ENTITY noscriptGloballyEnabled "Scripts globalt tilladt (farligt)">
+<!ENTITY noscriptAutoReload "Automatisk genindlæs berørte sider når tilladelser ændres">
+<!ENTITY noscriptGeneral "Generelt">
+<!ENTITY noscriptAppearance "Udseende">
+<!ENTITY noscriptShow "Vis…">
+<!ENTITY noscriptCtxMenu "Genvejsmenu">
+<!ENTITY noscriptStatusIcon "Statuslinjeikon">
+<!ENTITY noscriptFullAddr "Hele adresser (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Hele domæner (www.noscript.net)">
+<!ENTITY noscriptBaseDom "2. niveau domæner (noscript.net)">
+<!ENTITY noscriptTempCmd "Midlertidigt tillad […]">
+<!ENTITY noscriptSound "Audio feedback når scripts bliver blokeret">
+<!ENTITY noscriptImport "Importer">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Eksporter">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Vis meddelelse om blokerede scripts">
+<!ENTITY noscriptNotify.bottom "Placer meddelelsen nederst">
+<!ENTITY noscriptSound.choose "Vælg">
+<!ENTITY noscriptSound.choose.accesskey "V">
+<!ENTITY noscriptSound.play "Afspil">
+<!ENTITY noscriptSound.play.accesskey "A">
+<!ENTITY noscriptSound.reset "Nulstil standard">
+<!ENTITY noscriptSound.reset.accesskey "s">
+<!ENTITY noscriptAdvanced "Avanceret">
+<!ENTITY noscriptAdditionalPermissions "Yderligere tilladelser for betroede websteder">
+<!ENTITY noscriptAllowClipboard "Tillad kopiering af formateret tekst fra ekstern udklipsholder">
+<!ENTITY noscriptAdditionalRestrictions "Yderligere begrænsninger for ubetroede websteder">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Anvend også disse begrænsninger til betroede websteder">
+<!ENTITY noscriptForbidJava "Forbyd Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Forbyd XSLT">
+<!ENTITY noscriptForbidSilverlight "Forbyd Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Forbyd &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Forbyd &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Forbyd @font-face">
+<!ENTITY noscriptForbidWebGL "Forbyd WebGL">
+<!ENTITY noscriptForbidMedia "Forbyd &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Forbyd Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Forbyd andre plugins">
+<!ENTITY noscriptReloadWarn "Disse indstillinger træder i kraft på en ny eller en (manuelt) genindlæst side">
+<!ENTITY noscriptConfirmUnblock "Spørg før en midlertidig blokering af et objekt ophæves">
+<!ENTITY noscriptStatusLabel "Statuslinjeetiket">
+<!ENTITY noscriptForbidBookmarklets "Forbyd bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Vis pladsholderikon">
+<!ENTITY noscriptTruncateTitle "Afkort dokumenttitler">
+<!ENTITY noscriptFixLinks "Forsøg at fikse JavaScript-links">
+<!ENTITY noscriptAllowBookmarks "Tillad websteder åbnet gennem bogmærker">
+<!ENTITY noscriptAllowViaBookmarks "Tillad websteder åbnet gennem bogmærker">
+<!ENTITY noscriptAllowPing "Tillad &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Tillad lokale links">
+<!ENTITY noscriptForbidPing "Forbyd &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Forbyd META omdirigeringer i &lt;NOSCRIPT&gt;-elementer">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "F">
+<!ENTITY noscriptNotifyMeta "Vis meddelelse om blokerede META-omdirigeringer">
+<!ENTITY noscriptNotifyMeta.accesskey "m">
+<!ENTITY noscriptWhitelist "Whitelist">
+<!ENTITY noscriptPermissions "Tilladelser">
+<!ENTITY noscriptRefresh "Genindlæs">
+<!ENTITY noscriptNotifications "Beskeder">
+<!ENTITY noscriptToolbarToggle "Venstreklik på NoScript knappen slår tilladelser for nuværende topniveau-websted til/fra">
+<!ENTITY noscriptTrusted "Betroet">
+<!ENTITY noscriptUntrusted "Ubetroet">
+<!ENTITY noscriptUnknown "Ukendt">
+<!ENTITY noscriptAdd "Tilføj">
+<!ENTITY noscriptAdd.accesskey "T">
+<!ENTITY noscriptClose "Luk">
+<!ENTITY noscriptSiteManager "Webstedshåndtering">
+<!ENTITY noscriptSecurityManager "Sikkerhedshåndtering">
+<!ENTITY noscriptPolicies "Retningslinjer">
+<!ENTITY noscriptDefaultPolicies "Standard retningslinjer">
+<!ENTITY noscriptSitePolicies "Specifikke retningslinjer">
+<!ENTITY noscriptNselNever "Skjul &lt;NOSCRIPT&gt;-elementer">
+<!ENTITY noscriptNselForce "Vis &lt;NOSCRIPT&gt;-elementet som følger et blokeret &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Midlertidig tillad topniveau-websteder som standard">
+<!ENTITY noscriptDescription "Ekstra beskyttelse af din Firefox: NoScript tillader kun JavaScript, Java (og andre plugins) fra betroede domæner valgt af dig (f.eks. din netbanks hjemmeside). Denne whitelist-baserede forebyggende metode forhindrer udnyttelse af sikkerhedshuller (såvel kendte som ukendte!) uden tab af funktionalitet… Eksperter er enige: Firefox er mere sikker med NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Bloker CSS-baserede skannere">
+<!ENTITY noscriptOptFilterXGet "Rens mistænkelige cross-site-forespørgsler">
+<!ENTITY noscriptOptFilterXPost "Omdan cross-site POST-forespørgsler til GET-forespørgsler uden data">
+<!ENTITY noscriptShowConsole "Vis konsol…">
+<!ENTITY noscriptShowConsole.accesskey "V">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS OSS…">
+<!ENTITY noscriptXssFaq.accesskey "X">
+<!ENTITY noscriptUnsafeReload "Usikker genindlæsning">
+<!ENTITY noscriptUnsafeReload.accesskey "U">
+<!ENTITY noscriptXssExceptions "Anti-XSS beskyttelsesundtagelser">
+<!ENTITY noscriptXssExceptions.description "Destinationer, som matcher disse regulære udtryk, vil IKKE blive beskyttet mod XSS">
+<!ENTITY noscriptMatchSample "Eksempel på matchmønster:">
+<!ENTITY noscriptReset "Nulstil">
+<!ENTITY noscriptReset.accesskey "N">
+<!ENTITY noscriptResetDef "Nulstil til standard">
+<!ENTITY noscriptResetDef.accesskey "s">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Tilbagekald midlertidige tilladelser">
+<!ENTITY noscriptRevokeTemp.accesskey "m">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ingen pladsholdere til objekter fra websteder der er markeret som ubetroede">
+<!ENTITY noscriptCollapseBlockedObjects "Sammenfold blokerede objekter">
+<!ENTITY noscriptExceptions "Undtagelser…">
+<!ENTITY noscriptBlockedObjects "Blokerede objekter">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Bloker alle objekter der kommer fra et websted, som er markeret som ubetroet">
+<!ENTITY noscriptTempAllowPage "Midlertidigt tillad hele denne side">
+<!ENTITY noscriptTempAllowPage.accesskey "h">
+<!ENTITY noscriptAllowPage "Tillad hele denne side">
+<!ENTITY noscriptAllowPage.accesskey "T">
+<!ENTITY noscriptTempToPerm "Gør tilladelserne for side permanente">
+<!ENTITY noscriptTempToPerm.accesskey "G">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS OSS…">
+<!ENTITY noscriptHttpsFaq.accesskey "H">
+<!ENTITY noscriptHttps.behavior "Opførsel">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbyd aktiv webindhold med mindre det kommer fra en sikker (HTTPS)-forbindelse:">
+<!ENTITY noscriptHttps.never "Aldrig">
+<!ENTITY noscriptHttps.proxy "NÃ¥r proxy anvendes (anbefales med Tor)">
+<!ENTITY noscriptHttps.always "Altid">
+<!ENTITY noscriptHttpsForced "Tving de følgende websteder til at anvende sikre (HTTPS)-forbindelser:">
+<!ENTITY noscriptHttpsForcedExceptions "Tving aldrig sikre (HTTPS)-forbindelser for de følgende websteder:">
+<!ENTITY noscriptSecureCookies "Aktiver automatisk sikker cookies-håndtering">
+<!ENTITY noscriptSecureCookiesForced "Tving kryptering for alle cookies sat over HTTPS af de følgende websteder:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignorer usikre cookies sat over HTTPS af de følgende websteder:">
+<!ENTITY noscriptClearClickTitle "ClearClick-advarsel">
+<!ENTITY noscriptClearClickHeader "Potentiel klik-kapring/UI Redress forsøg!">
+<!ENTITY noscriptClearClickDescription "NoScript hindrede en muse- eller tastatur-interaktion med et delvist skjult element. Klik på billedet nedenunder for, at veksle mellem den blokerede og den frie version.">
+<!ENTITY noscriptClearClickOpt "ClearClick-beskyttelse på sider markeret som...">
+<!ENTITY noscriptClearClickReport "Rapportér">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Rapport ID:">
+<!ENTITY noscriptTrustedPagesAdj "betroede">
+<!ENTITY noscriptUntrustedPagesAdj "ubetroede">
+<!ENTITY noscriptKeepLocked "Bevar dette element låst (anbefalet)">
+<!ENTITY noscriptEmbeddings "Indlejrede objekter">
+<!ENTITY noscriptPrev "Forrige">
+<!ENTITY noscriptNext "Næste">
+<!ENTITY noscriptFrameOptErr.title "Dette indhold kan ikke vises i en ramme">
+<!ENTITY noscriptFrameOptErr.desc "For at beskytte din sikkerhed, tillader udgiveren af dette indhold ikke, at det vises i en ramme.">
+<!ENTITY noscriptFrameOptErr.link "Klik her for at åbne indholdet i et nyt vindue">
+<!ENTITY noscriptBookmarkSync "Backup NoScript indstillinger i et bogmærke for nem synkronisering">
+<!ENTITY noscriptShowReleaseNotes "Vis udgivelsesnoter ved opdatering">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Regelsæt:">
+<!ENTITY ABE.enabled.label "Aktiver ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Tillad websteder at håndhæve egne regelsæt">
+<!ENTITY ABE.edit.label "Rediger…">
+<!ENTITY ABE.edit.accesskey "R">
+<!ENTITY ABE.enable.label "Aktiver">
+<!ENTITY ABE.enable.accesskey "A">
+<!ENTITY ABE.disable.label "Deaktiver">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Opdatér">
+<!ENTITY ABE.refresh.accesskey "O">
+<!ENTITY noscriptUninstall "Afinstaller">
+<!ENTITY noscriptRecentBlocked "Websteder blokeret for nyligt">
+<!ENTITY noscriptExternalFilters "Eksterne filtre">
+<!ENTITY noscriptEF.enable "Aktiver eksterne filtre">
+<!ENTITY noscriptEF.add "Nyt filter…">
+<!ENTITY noscriptEF.executable "Kørbar fil:">
+<!ENTITY noscriptEF.browse "Gennemse…">
+<!ENTITY noscriptEF.contentType "Indholdstype (MIME) som skal filtreres (eksakt match eller regulært udtryk):">
+<!ENTITY noscriptEF.exceptions "Filtrer ikke objekter der kommer fra disse websteder:">
+<!ENTITY noscriptEF.remove "Fjern">
+<!ENTITY noscriptPreset "Sikkerhedsniveau">
+<!ENTITY noscriptPreset.off "Fra (mener du det?!)">
+<!ENTITY noscriptPreset.low "Medgørlig (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Klassisk (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fæstning (Fuldstændig isolation)">
+<!ENTITY noscript.hoverUI "Åbn tilladelsesmenuen når musen holdes over NoScript-ikonet">
+<!ENTITY noscriptDonate "Donér">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/da/noscript/noscript.properties b/extensions/noscript/chrome/locale/da/noscript/noscript.properties
new file mode 100644
index 0000000..33f8449
--- /dev/null
+++ b/extensions/noscript/chrome/locale/da/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Tillad scripts globalt (farligt)
+forbidGlobal=Forbyd scripts globalt (anbefales)
+allowLocal=Tillad %S
+allowTemp=Midlertidig tillad %S
+forbidLocal=Forbyd %S
+allowed.glb=Pas på! Scripts globalt tilladt
+allowed.yes=Scripts midlertidigt tilladt
+allowed.prt=Scripts delvist tilladt
+allowed.no=Scripts er midlertidigt forbudt
+global.warning.title=Advarsel!
+global.warning.text=Scripts tillades globalt (for alle websteder).\n Dette er en potentiel farlig handling. \nVil du virkelig fortsætte?
+audio.samples=Lydprøver
+confirm=Er du sikker?
+alwaysAsk=Spørg altid om bekræftelse
+notifyHide=Skjul efter %S sekunder
+trust=Betro %S
+distrust=Marker %S som ubetroet
+untrustedOrigin=en ubetroet oprindelse
+xss.notify.generic=NoScript har filtreret et potentielt forsøg på cross-site scripting (XSS) fra %S. Tekniske detaljer kan ses i konsollen.
+xss.notify.showConsole=Vis konsol…
+xss.notify.showConsole.accessKey=V
+xss.reason.filterXGet=Har renset mistænkelig forespørgsel. Original URL [%1$S] forespurgt fra [%2$S]. Renset URL: [%3$S].
+xss.reason.filterXGetRef=Har renset mistænkelig forespørgsels referer. URL [%1$S] forespurgt fra [%2$S]. Renset referrer: [%3$S].
+xss.reason.filterXPost=Har renset mistænkelig upload til [%1$S] fra [%2$S]: omdannede til en GET-forespørgsel, hvor der kun downloades.
+unsafeReload.warning=Genindlæser en mistænkelig %1$S uden sikkerhed\n\n [%2$S]\n\nFRA [%3$S]\n\nNoScript vil IKKE beskytte denne forespørgsel!\n
+metaRefresh.notify=NoScript blokerede en <META>-omdirigering i et <NOSCRIPT>-element: %S på %S sekunder.
+metaRefresh.notify.follow=Følg omdirigering
+metaRefresh.notify.follow.accessKey=F
+notify.options=Indstillinger
+notify.options.accessKey=I
+reset.title=NoScript Nulstil
+reset.warning=ALLE NoScript-indstillinger og tilladelser bliver øjeblikkeligt nulstillet til deres standardværdi.\nDenne handling kan ikke fortrydes.\nVil du fortsætte?
+bookmarkSync.title=NoScript indstillingsbogmærke
+bookmarkSync.message=Dette bogmærke er IKKE beregnet til at åbne, men til at blive synkroniseret med udvidelser som Weave eller XMarks.
+bookmarkSync.confirm=NoScript har fundet et indstillingsbogmærke gemt den\n%S.\nVil du virkelig overskrive dine lokale NoScript-indstillinger med indholdet fra dette bogmærke?
+ABE.notify=Forespørgsel %1$S filtreret af ABE: <%2$S> %3$S
+ABE.chooseEditor=Vælg en teksteditor til ABE regelsæt
+ABE.syntaxError=Syntaksfejl i ABE-regelsæt!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Tillad alle fra %S
+allowTempFrom=Midlertidigt tillad alle fra %S
+siteInfo.confirm=Du er ved at bede om information om webstedet "%1$S"\nved at indsende en forespørgsel til %2$S.\nØnsker du at fortsætte?
+siteInfo.tooltip=Midterklik eller shift+klik for webstedsinfo…
+ef.activate=Filter %S
+ef.options=%S Indstillinger…
+ef.newName=Indtast et navn til det nye filter:
+ef.locateExe=Vælg den kørbare fil til filtret %S
+disable=Deaktiver %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/de/noscript/about.properties b/extensions/noscript/chrome/locale/de/noscript/about.properties
new file mode 100644
index 0000000..ed348a2
--- /dev/null
+++ b/extensions/noscript/chrome/locale/de/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Zusätzlicher Schutz für Ihren Browser: NoScript erlaubt das Ausführen von JavaScript, Java (und anderen Plug-ins) nur bei vertrauenswürdigen Domains Ihrer Wahl (z.B. Ihrer Homebanking-Website). Der auf einer Positivliste basierende präventive Ansatz zum Blockieren von Skripten verhindert das Ausnutzen von (bekannten und unbekannten!) Sicherheitslücken ohne Verlust an Funktionalität.
+aboutTitle=Ãœber %S
+extensionContributors=Mitwirkende:
+extensionContributors.tip=Dank für diese Erweiterung gebührt
+extensionCreatorLabel=Autor:
+changelog=Versionshinweise (engl.)
+changelog.tip=Versionshinweise aufrufen (engl.)
+license=Lizenz (engl.)
+license.tip=Endbenutzerlizenz lesen
+logo.tip=Homepage der Erweiterung besuchen
+sponsor.tip=Sponsoren-Homepage besuchen
+informaction.tip=InformAction-Homepage besuchen
+extensionHomepage.tip=Homepage der Erweiterung besuchen
+extensionCreator.tip=Homepage des Autors besuchen
+version=Version %S
diff --git a/extensions/noscript/chrome/locale/de/noscript/noscript.dtd b/extensions/noscript/chrome/locale/de/noscript/noscript.dtd
new file mode 100644
index 0000000..c54822e
--- /dev/null
+++ b/extensions/noscript/chrome/locale/de/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Einstellungen…">
+<!ENTITY noscriptOptions.accesskey "E">
+<!ENTITY noscriptOptionsLong "NoScript - Einstellungen">
+<!ENTITY noscriptAbout "Über NoScript 5.1.8.5…">
+<!ENTITY noscriptPermissionsText "Sie können festlegen, welchen Websites Sie das Ausführen von Skripten erlauben möchten. Geben Sie bitte die exakte Adresse oder die Domain der Website ein (z.B. &quot;http://www.site.com&quot; oder &quot;site.com&quot;), für die Sie dies zulassen möchten, und klicken Sie dann auf &quot;Erlauben&quot;.">
+<!ENTITY noscriptWebAddress "Adresse der Website:">
+<!ENTITY noscriptAllow "Erlauben">
+<!ENTITY noscriptAllow.accesskey "E">
+<!ENTITY noscriptForbid "Verbieten">
+<!ENTITY noscriptForbid.accesskey "V">
+<!ENTITY noscriptTrust "Als vertrauenswürdig einstufen">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Als nicht vertrauenswürdig einstufen">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Ausgewählte Websites entfernen">
+<!ENTITY noscriptGloballyEnabled "Skripte allgemein erlauben (nicht empfohlen)">
+<!ENTITY noscriptAutoReload "Betroffene Seiten beim Ändern der Berechtigungen automatisch neu laden">
+<!ENTITY noscriptGeneral "Allgemein">
+<!ENTITY noscriptAppearance "Aussehen">
+<!ENTITY noscriptShow "Folgende Menüeinträge anzeigen:">
+<!ENTITY noscriptCtxMenu "Auch im Seitenkontextmenü">
+<!ENTITY noscriptStatusIcon "Symbol in der Statusleiste">
+<!ENTITY noscriptFullAddr "Vollständige Adressen (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Vollständige Domains (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Second-Level-Domains (noscript.net)">
+<!ENTITY noscriptTempCmd "[…] temporär erlauben">
+<!ENTITY noscriptSound "Klang ausgeben, wenn Skripte blockiert werden">
+<!ENTITY noscriptImport "Importieren…">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exportieren…">
+<!ENTITY noscriptExport.accesskey "x">
+<!ENTITY noscriptNotify "Informationsleiste anzeigen, wenn Skripte blockiert werden">
+<!ENTITY noscriptNotify.bottom "Am unteren Rand anzeigen">
+<!ENTITY noscriptSound.choose "Durchsuchen…">
+<!ENTITY noscriptSound.choose.accesskey "D">
+<!ENTITY noscriptSound.play "Anhören">
+<!ENTITY noscriptSound.play.accesskey "A">
+<!ENTITY noscriptSound.reset "Standard wiederherstellen">
+<!ENTITY noscriptSound.reset.accesskey "S">
+<!ENTITY noscriptAdvanced "Erweitert">
+<!ENTITY noscriptAdditionalPermissions "Zusätzliche Berechtigungen für vertrauenswürdige Websites">
+<!ENTITY noscriptAllowClipboard "Kopieren und Einfügen über die Zwischenablage für Rich-Text-Editoren erlauben">
+<!ENTITY noscriptAdditionalRestrictions "Zusätzliche Einschränkungen für nicht vertrauenswürdige Websites">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Diese Einschränkungen auch auf vertrauenswürdige Websites anwenden">
+<!ENTITY noscriptForbidJava "Javaâ„¢ verbieten">
+<!ENTITY noscriptForbidXSLT "XSLT verbieten">
+<!ENTITY noscriptForbidSilverlight "Microsoft® Silverlight™ verbieten">
+<!ENTITY noscriptForbidIFrames "&lt;IFRAME&gt; verbieten">
+<!ENTITY noscriptForbidFrames "&lt;FRAME&gt; verbieten">
+<!ENTITY noscriptForbidFonts "Nachladen von Schriften mittels @font-face verbieten">
+<!ENTITY noscriptForbidWebGL "Nachladen von Schriften mittels WebGL verbieten">
+<!ENTITY noscriptForbidMedia "&lt;AUDIO&gt;/&lt;VIDEO&gt; verbieten">
+<!ENTITY noscriptForbidFlash "Adobe® Flash® verbieten">
+<!ENTITY noscriptForbidPlugins "Andere Plugins verbieten">
+<!ENTITY noscriptReloadWarn "Diese Einstellungen werden erst bei neuen oder (manuell) neu geladenen Seiten wirksam">
+<!ENTITY noscriptConfirmUnblock "Bestätigungsmeldung anzeigen, bevor ein Objekt temporär erlaubt wird">
+<!ENTITY noscriptStatusLabel "Informationstext in der Statusleiste">
+<!ENTITY noscriptForbidBookmarklets "Bookmarklets verbieten">
+<!ENTITY noscriptShowPlaceholder "Platzhaltersymbol anzeigen">
+<!ENTITY noscriptTruncateTitle "Überlangen &quot;document.title&quot; kürzen (siehe Bug 319004)">
+<!ENTITY noscriptFixLinks "Versuchen, JavaScript-Links in normale Links umzuwandeln">
+<!ENTITY noscriptAllowBookmarks "Aus Lesezeichen geöffnete Websites erlauben">
+<!ENTITY noscriptAllowViaBookmarks "Aus Lesezeichen geöffnete Websites erlauben">
+<!ENTITY noscriptAllowPing "Klick-Verfolgung über das PING-Attribut für Links erlauben">
+<!ENTITY noscriptAllowLocalLinks "Links auf lokale Dateien erlauben">
+<!ENTITY noscriptForbidPing "Klick-Verfolgung über das PING-Attribut für Links verbieten">
+<!ENTITY noscriptForbidMetaRefresh "META-Weiterleitungen innerhalb von &lt;NOSCRIPT&gt;-Elementen verbieten">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "W">
+<!ENTITY noscriptNotifyMeta "Meldung bei blockierten META-Weiterleitungen anzeigen">
+<!ENTITY noscriptNotifyMeta.accesskey "W">
+<!ENTITY noscriptWhitelist "Positivliste">
+<!ENTITY noscriptPermissions "Berechtigungen">
+<!ENTITY noscriptRefresh "Aktualisierung">
+<!ENTITY noscriptNotifications "Benachrichtigungen">
+<!ENTITY noscriptToolbarToggle "Berechtigungen für aktuelle Top-Level-Site mit Links-Klick auf die Symbolleisten-Schaltfläche umschalten">
+<!ENTITY noscriptTrusted "Vertrauenswürdig">
+<!ENTITY noscriptUntrusted "Nicht vertrauenswürdig">
+<!ENTITY noscriptUnknown "Unbekannt">
+<!ENTITY noscriptAdd "Hinzufügen">
+<!ENTITY noscriptAdd.accesskey "H">
+<!ENTITY noscriptClose "Schließen">
+<!ENTITY noscriptSiteManager "Site-Manager">
+<!ENTITY noscriptSecurityManager "Sicherheits-Manager">
+<!ENTITY noscriptPolicies "Richtlinien">
+<!ENTITY noscriptDefaultPolicies "Standard-Richtlinien">
+<!ENTITY noscriptSitePolicies "Website-spezifische Richtlinien">
+<!ENTITY noscriptNselNever "&lt;NOSCRIPT&gt;-Elemente ausblenden">
+<!ENTITY noscriptNselForce "&lt;NOSCRIPT&gt;-Element, das einem blockierten &lt;SCRIPT&gt; folgt, anzeigen">
+<!ENTITY noscriptAutoAllowTopLevel "Jeweils aktuelle Top-Level-Site temporär erlauben">
+<!ENTITY noscriptDescription "Zusätzlicher Schutz für Ihren Browser: NoScript erlaubt das Ausführen von JavaScript, Java (und anderen Plugins) nur bei vertrauenswürdigen Domains Ihrer Wahl (z.B. Ihrer Homebanking-Website). Der auf einer Positivliste basierende präventive Ansatz zum Blockieren von Skripten verhindert das Ausnutzen von (bekannten und unbekannten!) Sicherheitslücken ohne Verlust an Funktionalität.">
+<!ENTITY noscriptOptBlockCssScanners "Auf Cross-Site Scripting basierende Scanner blockieren">
+<!ENTITY noscriptOptFilterXGet "Anfragen bei Verdacht auf Cross-Site Scripting bereinigen">
+<!ENTITY noscriptOptFilterXPost "Cross-Site-POST-Anfragen in datenlose GET-Anfragen umwandeln">
+<!ENTITY noscriptShowConsole "Konsole anzeigen…">
+<!ENTITY noscriptShowConsole.accesskey "z">
+<!ENTITY noscriptXss "Cross-Site Scripting (XSS)">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "FAQ (engl.) zu Cross-Site Scripting…">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Unsicheres Nachladen">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Ausnahmen vom XSS-Schutz">
+<!ENTITY noscriptXssExceptions.description "Zieladressen, die mit diesen regulären Ausdrücken übereinstimmen, werden vom XSS-Schutz ausgenommen">
+<!ENTITY noscriptMatchSample "Beispielmuster für Übereinstimmung:">
+<!ENTITY noscriptReset "Zurücksetzen">
+<!ENTITY noscriptReset.accesskey "Z">
+<!ENTITY noscriptResetDef "Auf Standardwerte zurücksetzen">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Temporäre Berechtigungen aufheben">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "Keine Platzhalter anzeigen für Objekte von als nicht vertrauenswürdig eingestuften Sites">
+<!ENTITY noscriptCollapseBlockedObjects "Platz von geblockten Elementen freigeben">
+<!ENTITY noscriptExceptions "Ausnahmen…">
+<!ENTITY noscriptBlockedObjects "Blockierte Objekte">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Jedes Objekt von als nicht vertrauenswürdig eingestuften Sites blockieren">
+<!ENTITY noscriptTempAllowPage "Temporär alle Beschränkungen für diese Seite aufheben">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "Alle Beschränkungen für diese Seite aufheben">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Berechtigungen dieser Seite speichern">
+<!ENTITY noscriptTempToPerm.accesskey "b">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "FAQ (engl.) zu verschlüsselten Verbindungen (HTTPS)…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Verhalten">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Aktive Webinhalte verbieten, es sei denn, sie stammen aus einer verschlüsselten Verbindung (HTTPS):">
+<!ENTITY noscriptHttps.never "Niemals">
+<!ENTITY noscriptHttps.proxy "Bei Verwendung eines Proxy (empfohlen bei Anonymisierungsdiensten wie Tor)">
+<!ENTITY noscriptHttps.always "Immer">
+<!ENTITY noscriptHttpsForced "Verschlüsselte Verbindung (HTTPS) für folgende Adressen erzwingen:">
+<!ENTITY noscriptHttpsForcedExceptions "Für folgende Adressen niemals die Verwendung verschlüsselter Verbindung (HTTPS) erzwingen:">
+<!ENTITY noscriptSecureCookies "Automatisches sicheres Cookie-Management aktivieren">
+<!ENTITY noscriptSecureCookiesForced "Überprüfung der Cookies über verschlüsselte Verbindungen (HTTPS) für folgende Adressen erzwingen:">
+<!ENTITY noscriptSecureCookiesExceptions "Unsichere Cookies bei verschlüsselter Verbindung (HTTPS) bei folgenden Adressen ignorieren:">
+<!ENTITY noscriptClearClickTitle "ClearClick-Warnung">
+<!ENTITY noscriptClearClickHeader "Potentieller Clickjacking-Angriff / Versuch einer UI-Umadressierung!">
+<!ENTITY noscriptClearClickDescription "NoScript wehrte eine Maus- oder Tastatursteuerung durch ein teilweise verstecktes Element ab. Klicken Sie auf die nachfolgende Grafik, um zwischen der gesperrten und der ungesperrten Version zu wechseln.">
+<!ENTITY noscriptClearClickOpt "ClearClick-Schutz anwenden auf…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report-ID:">
+<!ENTITY noscriptTrustedPagesAdj "vertrauenswürdigen Seiten">
+<!ENTITY noscriptUntrustedPagesAdj "nicht vertrauenswürdigen /">
+<!ENTITY noscriptKeepLocked "Element gesperrt halten (empfohlen)">
+<!ENTITY noscriptEmbeddings "Eingebettete Objekte">
+<!ENTITY noscriptPrev "Zurück">
+<!ENTITY noscriptNext "Weiter">
+<!ENTITY noscriptFrameOptErr.title "Der Inhalt kann nicht in einem Frame angezeigt werden">
+<!ENTITY noscriptFrameOptErr.desc "Um Ihre Sicherheit zu gewährleisten, hat der Herausgeber dieses Inhaltes festgelegt, dass er nicht in einem Frame angezeigt werden darf.">
+<!ENTITY noscriptFrameOptErr.link "Hier klicken, um den Inhalt in einem neuen Fenster zu öffnen">
+<!ENTITY noscriptBookmarkSync "Datensicherung der NoScript-Konfiguration in einem Lesezeichen speichern für eine einfache Synchronisation">
+<!ENTITY noscriptShowReleaseNotes "Versionshinweise nach einem Update anzeigen">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Regelsätze:">
+<!ENTITY ABE.enabled.label "ABE (Application Boundaries Enforcer) aktivieren">
+<!ENTITY ABE.siteEnabled.label "Websites das Verwenden ihrer eigenen Regelsätze erlauben">
+<!ENTITY ABE.edit.label "Bearbeiten…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Aktivieren">
+<!ENTITY ABE.enable.accesskey "a">
+<!ENTITY ABE.disable.label "Deaktivieren">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Aktualisieren">
+<!ENTITY ABE.refresh.accesskey "k">
+<!ENTITY noscriptUninstall "Deinstallieren">
+<!ENTITY noscriptRecentBlocked "Kürzlich blockierte Websites">
+<!ENTITY noscriptExternalFilters "Externe Filter">
+<!ENTITY noscriptEF.enable "Externe Filter aktivieren">
+<!ENTITY noscriptEF.add "Neuer Filter…">
+<!ENTITY noscriptEF.executable "Ausführbare Datei:">
+<!ENTITY noscriptEF.browse "Durchsuchen…">
+<!ENTITY noscriptEF.contentType "Zu filternder Content-Type (MIME) (genaue Übereinstimmung oder Regulärer Ausdruck):">
+<!ENTITY noscriptEF.exceptions "Objekte von folgenden Seiten nicht filtern:">
+<!ENTITY noscriptEF.remove "Entfernen">
+<!ENTITY noscriptPreset "Sicherheitsstufe">
+<!ENTITY noscriptPreset.off "Deaktiviert (Ist das Ihr Ernst?!)">
+<!ENTITY noscriptPreset.low "Gelassen (Negativliste + Websicherheit)">
+<!ENTITY noscriptPreset.medium "Klassisch (Positivliste + Websicherheit)">
+<!ENTITY noscriptPreset.high "Festung (Vollständige Sperrung)">
+<!ENTITY noscript.hoverUI "Berechtigungen-Menü öffnen beim Überfahren des NoScript-Symbols mit dem Mauszeiger">
+<!ENTITY noscriptDonate "Spenden">
+<!ENTITY noscriptDonate.accesskey "S">
+<!ENTITY noscriptAutoReload.currentTab "Nur den aktuellen Tab neu laden">
+<!ENTITY noscriptCascadePermissions "Rechte des Hauptdokuments auf alle Unterdokumente und Skripte Dritter anwenden">
+<!ENTITY noscriptRestrictSubdocScripting "Skripte in Unterdokumenten der Positivliste blockieren, die zu Seiten gehören, die nicht in der Positivliste sind">
+<!ENTITY noscriptGlobalHttpsWhitelist "HTTPS Skripte generell bei HTTPS Dokumenten erlauben">
+<!ENTITY noscriptPermanentInPrivate "Permanentes &quot;Zulassen&quot; von Befehle in privaten Fenstern">
+<!ENTITY noscriptCustom "Custom">
diff --git a/extensions/noscript/chrome/locale/de/noscript/noscript.properties b/extensions/noscript/chrome/locale/de/noscript/noscript.properties
new file mode 100644
index 0000000..63b07f7
--- /dev/null
+++ b/extensions/noscript/chrome/locale/de/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Skripte allgemein erlauben (nicht empfohlen)
+forbidGlobal=Skripte allgemein verbieten (empfohlen)
+allowLocal=%S erlauben
+allowTemp=%S temporär erlauben
+forbidLocal=%S verbieten
+allowed.glb=Achtung! Skripte werden allgemein erlaubt.
+allowed.yes=Skripte sind momentan erlaubt
+allowed.prt=Skripte sind teilweise erlaubt
+allowed.no=Skripte sind momentan verboten
+global.warning.title=Warnung!
+global.warning.text=Sie sind im Begriff, Skripte allgemein (für alle Websites) zu erlauben.\nDies stellt ein potenzielles Sicherheitsrisiko dar.\nMöchten Sie wirklich fortfahren?
+audio.samples=Audiodateien
+confirm=Sind Sie sicher?
+alwaysAsk=Diese Meldung immer anzeigen
+notifyHide=Nach %S Sekunden ausblenden
+trust=%S vertrauen
+distrust=%S als nicht vertrauenswürdig einstufen
+untrustedOrigin=nicht vertrauenwürdiger Ursprung
+xss.notify.generic=NoScript hat einen möglichen Cross-Site-Scripting-Versuch (XSS) von %S gefiltert. Technische Details wurden in der Konsole protokolliert.
+xss.notify.showConsole=Konsole anzeigen…
+xss.notify.showConsole.accessKey=z
+xss.reason.filterXGet=Eine verdächtige Anfrage wurde bereinigt. Original-URL [%1$S] angefordert von [%2$S]. Bereinigte URL: [%3$S].
+xss.reason.filterXGetRef=Ein verdächtiger Anfrage-Referer wurde bereinigt. URL [%1$S] angefordert von [%2$S]. Bereinigter Referrer: [%3$S].
+xss.reason.filterXPost=Ein verdächtiger Upload zu [%1$S] von [%2$S] wurde bereinigt und in eine GET-Anfrage (nur Download) umgewandelt.
+unsafeReload.warning=UNSICHERES Nachladen eines verdächtigen\n\n%1$S [%2$S]\n\nvon [%3$S]\n\nNoScript wird diese Anfrage nicht schützen!\n
+metaRefresh.notify=NoScript hat eine META-Weiterleitung innerhalb eines <noscript>-Elements blockiert: %S in %S Sekunden.
+metaRefresh.notify.follow=Der Weiterleitung folgen
+metaRefresh.notify.follow.accessKey=F
+notify.options=Optionen
+notify.options.accessKey=O
+reset.title=NoScript zurücksetzen
+reset.warning=ALLE NoScript-Einstellungen und Website-Berechtigungen werden auf ihre Standardwerte zurückgesetzt.\nDiese Aktion kann nicht rückgängig gemacht werden.\nMöchten Sie wirklich fortfahren?
+bookmarkSync.title=NoScript-Konfigurationslesezeichen
+bookmarkSync.message=Dieses Lesezeichen ist nicht dafür vorgesehen, geöffnet zu werden. Es dient vielmehr dem Zweck, die Konfiguration von NoScript über einen Service wie Firefox-Sync, SyncPlaces oder XMarks zu synchronisieren.
+bookmarkSync.confirm=NoScript hat ein Konfigurationslesezeichen gefunden,\nwelches vermutlich am %S gespeichert wurde.\nMöchten Sie wirklich Ihre aktuellen Einstellungen mit denen aus dem Lesezeichen überschreiben?
+ABE.notify=Die Anfrage %1$S wurde durch ABE gefiltert: <%2$S> %3$S
+ABE.chooseEditor=Bitte einen Texteditor zur Bearbeitung der ABE-Regelsätze auswählen
+ABE.syntaxError=Syntaxfehler in den ABE-Regelsätzen!
+ABE.wanIpAsLocal=WAN-IP (%S) ∈ LOCAL
+allowFrom=Alle Beschränkungen für "%S" aufheben
+allowTempFrom=Temporär alle Beschränkungen für "%S" aufheben
+siteInfo.confirm=Sie haben Informationen über die Site "%1$S"\ndurch Stellen einer Anfrage bei %2$S angefordert.\nSoll dieser Vorgang wirklich fortgesetzt werden?
+siteInfo.tooltip=Mittelklick oder Umschalt+Klick, um die Seiteninformationen aufzurufen…
+ef.activate=Filter %S
+ef.options=%S Einstellungen…
+ef.newName=Einen Namen für den neuen Filter festlegen:
+ef.locateExe=Eine ausführbare Datei für den Filter "%S" auswählen
+disable=%S deaktiviert
+disable.accessKey=d
+allowed.glb-emb=Skripte sind global erlaubt, einige Einbettungen sind jedoch blockiert
+removal.title=Warnung vor Verschlechterung der Sicherheit
+removal.message=Wenn Sie NoScript deaktivieren oder deinstallieren, verzichten Sie auf JEDEN von NoScript angebotenen Schutz.\n\nWenn Sie es überdrüssig sind, Skriptrechte für jede einzelne Website zu verwalten, gibt es eine sicherere Wahl.\n\n NoScript kann das Blockieren von Skripten beenden, außer von denen, die Sie als nicht vertrauenswürdig markieren, während Sie sich weiterhin mit den fortgeschrittensten Sicherheitsmaßnahmen gegen XSS, Clickjacking, CSRF und andere Webbedrohungen schützen.\n\nMöchten sie wirklich jeden Schutz von NoScript entfernen?\n
+removal.no=Nein, Skripte einfach nicht mehr blockieren
+removal.yes=Ja, jeden Schutz entfernen
+incompatibleOptions.title=Warnung vor inkompatiblen Einstellungen
+incompatibleOptions="%1$S"\nist mit "%2$S" inkompatibel.\bMöchten Sie Ersteres aktivieren und Letzteres deaktivieren?
diff --git a/extensions/noscript/chrome/locale/el/noscript/about.properties b/extensions/noscript/chrome/locale/el/noscript/about.properties
new file mode 100644
index 0000000..8b299cd
--- /dev/null
+++ b/extensions/noscript/chrome/locale/el/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=ΠÏόσθετη Ï€Ïοστασία για τον Firefox. Οι ειδικοί συμφωνοÏν: Το Noscript δίνει μεγαλÏτεÏη ασφάλεια στον Firefox :-)
+aboutTitle=ΠεÏί %S
+extensionContributors=Συντελεστές :
+extensionContributors.tip=ΆνθÏωποι τους οποίους θα Ï€Ïέπει να ευγνωμονείτε για αυτή την επέκταση
+extensionCreatorLabel=ΔημιουÏγός :
+changelog=ΙστοÏικό αλλαγών
+changelog.tip=ΠÏοβολή ιστοÏÎ¹ÎºÎ¿Ï Î±Î»Î»Î±Î³ÏŽÎ½
+license=Άδεια χÏήσης
+license.tip=Διαβάστε την άδεια Ï„ÎµÎ»Î¹ÎºÎ¿Ï Ï‡Ïήστη
+logo.tip=Επισκεφθείτε την αÏχική σελίδα της επέκτασης
+sponsor.tip=Επισκεφθείτε τη σελίδα του χοÏηγοÏ
+informaction.tip=Επισκεφθείτε την αÏχική σελίδα του InformAction
+extensionHomepage.tip=Επισκεφτείτε την ιστοσελίδα της επέκτασης
+extensionCreator.tip=Επισκεφτείτε την ιστοσελίδα του δημιουÏγοÏ
+version=Έκδοση %S
diff --git a/extensions/noscript/chrome/locale/el/noscript/noscript.dtd b/extensions/noscript/chrome/locale/el/noscript/noscript.dtd
new file mode 100644
index 0000000..276fa16
--- /dev/null
+++ b/extensions/noscript/chrome/locale/el/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Επιλογές">
+<!ENTITY noscriptOptions.accesskey "Ε">
+<!ENTITY noscriptOptionsLong "Επιλογές NoScript">
+<!ENTITY noscriptAbout "ΠεÏί NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "ΜποÏείτε να καθοÏίσετε για ποιους ιστότοπους θα επιτÏέπεται η εκτέλεση σεναÏίων εντολών. ΠληκτÏολογήστε τη διεÏθυνση τομέα (πχ. &quot;http://www.site.com&quot; or &quot;site.com&quot;) του ιστότοπου που θέλετε και μετά κάντε κλικ στο «Îα επιτÏέπεται»">
+<!ENTITY noscriptWebAddress "ΔιεÏθυνση ιστότοπου">
+<!ENTITY noscriptAllow "Îα επιτÏέπεται">
+<!ENTITY noscriptAllow.accesskey "Î">
+<!ENTITY noscriptForbid "ΑπαγόÏευση">
+<!ENTITY noscriptForbid.accesskey "Α">
+<!ENTITY noscriptTrust "Σημείωση ως έμπιστο">
+<!ENTITY noscriptTrust.accesskey "ε">
+<!ENTITY noscriptUntrust "Σημείωση ως μη έμπιστο">
+<!ENTITY noscriptUntrust.accesskey "μ">
+<!ENTITY noscriptRemoveSelected "ΑφαίÏεση επιλεγμένων ιστότοπων">
+<!ENTITY noscriptGloballyEnabled "Îα επιτÏέπονται τα σενάÏια εντολών γενικά (μη ασφαλές)">
+<!ENTITY noscriptAutoReload "Αυτόματη ανανέωση των σελίδων που επηÏεάζονται από την αλλαγή δικαιωμάτων">
+<!ENTITY noscriptGeneral "Γενικά">
+<!ENTITY noscriptAppearance "Εμφάνιση">
+<!ENTITY noscriptShow "ΠÏοβολή…">
+<!ENTITY noscriptCtxMenu "ÎœÎµÎ½Î¿Ï Ï€ÎµÏιεχομένου">
+<!ENTITY noscriptStatusIcon "Εικονίδιο γÏαμμής κατάστασης">
+<!ENTITY noscriptFullAddr "ΠλήÏεις διευθÏνσεις (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "ΠλήÏεις τομείς (www.noscript.net)">
+<!ENTITY noscriptBaseDom "ΔευτεÏεÏοντες βασικοί τομείς (noscript.net)">
+<!ENTITY noscriptTempCmd "Îα επιτÏέπονται Ï€ÏοσωÏινά […]">
+<!ENTITY noscriptSound "Ηχητική σήμανση όταν μπλοκάÏονται σενάÏια εντολών">
+<!ENTITY noscriptImport "Εισαγωγή">
+<!ENTITY noscriptImport.accesskey "Ε">
+<!ENTITY noscriptExport "Εξαγωγή">
+<!ENTITY noscriptExport.accesskey "ξ">
+<!ENTITY noscriptNotify "ΠÏοβολή μηνÏματος για μπλοκαÏισμένα σενάÏια εντολών">
+<!ENTITY noscriptNotify.bottom "Τοποθέτηση μηνÏματος στο κάτω μέÏος">
+<!ENTITY noscriptSound.choose "Επιλογή">
+<!ENTITY noscriptSound.choose.accesskey "Ï€">
+<!ENTITY noscriptSound.play "ΑναπαÏαγωγή">
+<!ENTITY noscriptSound.play.accesskey "α">
+<!ENTITY noscriptSound.reset "ΕπαναφοÏά αÏχικοÏ">
+<!ENTITY noscriptSound.reset.accesskey "Ï">
+<!ENTITY noscriptAdvanced "Για Ï€ÏοχωÏημένους">
+<!ENTITY noscriptAdditionalPermissions "ΠÏόσθετες εξουσιοδοτήσεις για έμπιστους ιστότοπους">
+<!ENTITY noscriptAllowClipboard "Îα επιτÏέπεται αντιγÏαφή και επικόλληση από το Ï€ÏόχειÏο (εξωτεÏικής εφαÏμογής)">
+<!ENTITY noscriptAdditionalRestrictions "ΠÏόσθετοι πεÏιοÏισμοί για μη έμπιστους ιστότοπους">
+<!ENTITY noscriptPlugins "ΠÏόσθετες λειτουÏγίες">
+<!ENTITY noscriptContentBlocker "ΕφαÏμογή αυτών των πεÏιοÏισμών και σε έμπιστους ιστότοπους">
+<!ENTITY noscriptForbidJava "ΑπαγόÏευση εκτέλεσης Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "ΑπαγόÏευση εκτέλεσης XSLT">
+<!ENTITY noscriptForbidSilverlight "ΑπαγόÏευση εκτέλεσης Microsoft® Silverlightâ„¢">
+<!ENTITY noscriptForbidIFrames "ΑπαγόÏευση εκτέλεσης &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "ΑπαγόÏευση εκτέλεσης &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Îα απαγοÏεÏεται το @font-face">
+<!ENTITY noscriptForbidWebGL "Îα απαγοÏεÏεται το WebGL">
+<!ENTITY noscriptForbidMedia "Îα απαγοÏεÏονται τα &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "ΑπαγόÏευση εκτέλεσης Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "ΑπαγόÏευση εκτέλεσης άλλων Ï€Ïόσθετων λειτουÏγιών">
+<!ENTITY noscriptReloadWarn "Αυτές οι επιλογές θα εφαÏμοστοÏν σε σελίδες που θα ανανεώσετε μόνοι σας ή θα φοÏτώσετε από &apos;δω και πέÏα">
+<!ENTITY noscriptConfirmUnblock "Îα γίνεται εÏώτηση Ï€Ïιν επιτÏαπεί Ï€ÏοσωÏινά ένα αντικείμενο">
+<!ENTITY noscriptStatusLabel "Ετικέτα γÏαμμής κατάστασης">
+<!ENTITY noscriptForbidBookmarklets "ΑπαγόÏευση εκτέλεσης bookmarklets">
+<!ENTITY noscriptShowPlaceholder "ΠÏοβολή εικονιδίου γεμίσματος">
+<!ENTITY noscriptTruncateTitle "ΣÏντμηση τίτλων εγγÏάφων">
+<!ENTITY noscriptFixLinks "Îα γίνεται Ï€Ïοσπάθεια διόÏθωσης δεσμών JavaScript">
+<!ENTITY noscriptAllowBookmarks "Îα επιτÏέπονται για ιστότοπους που υπάÏχουν στους σελιδοδείκτες">
+<!ENTITY noscriptAllowViaBookmarks "Îα επιτÏέπονται για ιστότοπους που υπάÏχουν στους σελιδοδείκτες">
+<!ENTITY noscriptAllowPing "Îα επιτÏέπεται το &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Îα επιτÏέπονται τοπικοί δεσμοί">
+<!ENTITY noscriptForbidPing "Îα απαγοÏεÏεται το &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Îα απαγοÏεÏονται οι ανακατευθÏνσεις META σε στοιχεία &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "θ">
+<!ENTITY noscriptNotifyMeta "ΠÏοβολή μηνÏματος για μπλοκαÏισμένες ανακατευθÏνσεις «ΜΕΤΑ»">
+<!ENTITY noscriptNotifyMeta.accesskey "ν">
+<!ENTITY noscriptWhitelist "Λίστα επιτÏεπομένων">
+<!ENTITY noscriptPermissions "Δικαιώματα">
+<!ENTITY noscriptRefresh "Ανανέωση">
+<!ENTITY noscriptNotifications "Ειδοποιήσεις">
+<!ENTITY noscriptToolbarToggle "Εναλλαγή δικαιωμάτων για τον βασικό ιστότοπο με αÏιστεÏÏŒ κλικ στο εικονίδιο της εÏγαλειοθήκης">
+<!ENTITY noscriptTrusted "Έμπιστο">
+<!ENTITY noscriptUntrusted "Μη έμπιστο">
+<!ENTITY noscriptUnknown "Άγνωστο">
+<!ENTITY noscriptAdd "ΠÏοσθήκη">
+<!ENTITY noscriptAdd.accesskey "Π">
+<!ENTITY noscriptClose "Κλείσιμο">
+<!ENTITY noscriptSiteManager "ΔιαχειÏιστής ιστότοπων">
+<!ENTITY noscriptSecurityManager "ΔιαχειÏιστής ασφαλείας">
+<!ENTITY noscriptPolicies "Πολιτικές συμπεÏιφοÏάς">
+<!ENTITY noscriptDefaultPolicies "ΑÏχικές πολιτικές συμπεÏιφοÏάς">
+<!ENTITY noscriptSitePolicies "Πολιτικές συμπεÏιφοÏάς για συγκεκÏιμένους ιστότοπους">
+<!ENTITY noscriptNselNever "ΑπόκÏυψη στοιχείων &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "ΠÏοβολή του στοιχείου &lt;NOSCRIPT&gt; που ακολουθεί μπλοκαÏισμένα σενάÏια εντολών">
+<!ENTITY noscriptAutoAllowTopLevel "Îα επιτÏέπεται Ï€ÏοσωÏινά για τον βασικό ιστότοπο (ως αÏχική ÏÏθμιση)">
+<!ENTITY noscriptDescription "ΠÏόσθετη Ï€Ïοστασία για τον Firefox. Οι ειδικοί συμφωνοÏν: το NoScript δίνει μεγαλÏτεÏη ασφάλεια στον Firefox. :-)">
+<!ENTITY noscriptOptBlockCssScanners "ΜπλοκάÏισμα ανιχνεÏσεων CSS">
+<!ENTITY noscriptOptFilterXGet "ΕκκαθάÏιση αιτημάτων Ïποπτων ως cross-site scripting">
+<!ENTITY noscriptOptFilterXPost "ΜετατÏοπή αιτημάτων cross-site POST σε κενά πεÏιεχομένου αιτήματα GET">
+<!ENTITY noscriptShowConsole "ΠÏοβολή κονσόλας…">
+<!ENTITY noscriptShowConsole.accesskey "κ">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "Συχνές εÏωτήσεις XSS…">
+<!ENTITY noscriptXssFaq.accesskey "χ">
+<!ENTITY noscriptUnsafeReload "Μη ασφαλής ανανέωση">
+<!ENTITY noscriptUnsafeReload.accesskey "Μ">
+<!ENTITY noscriptXssExceptions "ΕξαιÏέσεις από Ï€Ïοστασία αντι-XSS">
+<!ENTITY noscriptXssExceptions.description "Δεν θα παÏέχεται Ï€Ïοστασία αντί-XSS για Ï€ÏοοÏισμοÏÏ‚ που ταιÏιάζουν με τις κανονικές εκφÏάσεις:">
+<!ENTITY noscriptMatchSample "ΠαÏάδειγμα ταιÏιάσματος μοτίβου:">
+<!ENTITY noscriptReset "ΕπαναφοÏά αÏχικών Ïυθμίσεων">
+<!ENTITY noscriptReset.accesskey "Ε">
+<!ENTITY noscriptResetDef "ΕπαναφοÏά αÏχικών Ïυθμίσεων">
+<!ENTITY noscriptResetDef.accesskey "σ">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "ΑναίÏεση Ï€ÏοσωÏινών αδειοδοτήσεων">
+<!ENTITY noscriptRevokeTemp.accesskey "ν">
+<!ENTITY noscriptNoUntrustedPlaceholder "ΧωÏίς εικονίδια γεμίσματος για αντικείμενα από μη έμπιστους ιστότοπους">
+<!ENTITY noscriptCollapseBlockedObjects "ΣÏμπτυξη μπλοκαÏισμένων αντικειμένων">
+<!ENTITY noscriptExceptions "ΕξαιÏέσεις…">
+<!ENTITY noscriptBlockedObjects "ΜπλοκαÏισμένα αντικείμενα">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "ΜπλοκάÏισμα κάθε αντικειμένου Ï€ÏοεÏχόμενου από ιστότοπο σημειωμένο ως μη έμπιστο">
+<!ENTITY noscriptTempAllowPage "Îα επιτÏέπεται Ï€ÏοσωÏινά γενικά για τη σελίδα">
+<!ENTITY noscriptTempAllowPage.accesskey "σ">
+<!ENTITY noscriptAllowPage "Îα επιτÏέπεται γενικά για τη σελίδα">
+<!ENTITY noscriptAllowPage.accesskey "ε">
+<!ENTITY noscriptTempToPerm "ΜετατÏοπή δικαιωμάτων σελίδας σε μόνιμα">
+<!ENTITY noscriptTempToPerm.accesskey "ν">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "Συχνές εÏωτήσεις HTTPS">
+<!ENTITY noscriptHttpsFaq.accesskey "ε">
+<!ENTITY noscriptHttps.behavior "ΣυμπεÏιφοÏά">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Îα απαγοÏεÏεται ενεÏγό πεÏιεχόμενο εκτός κι αν παÏέχεται μέσω ασφαλοÏÏ‚ (HTTPS) σÏνδεσης:">
+<!ENTITY noscriptHttps.never "Ποτέ">
+<!ENTITY noscriptHttps.proxy "Όταν γίνεται χÏήση διαμεσολαβητή (συνιστάται για το δίκτυο Tor)">
+<!ENTITY noscriptHttps.always "Πάντα">
+<!ENTITY noscriptHttpsForced "Εξαναγκασμός των παÏακάτω ιστότοπων σε χÏήση ασφαλοÏÏ‚ (HTTPS) σÏνδεσης:">
+<!ENTITY noscriptHttpsForcedExceptions "Îα μην γίνεται εξαναγκασμός χÏήσης ασφαλοÏÏ‚ (HTTPS) σÏνδεσης για τους παÏακάτω ιστότοπους:">
+<!ENTITY noscriptSecureCookies "ΕνεÏγοποίηση αυτόματης ασφαλοÏÏ‚ διαχείÏισης cookies">
+<!ENTITY noscriptSecureCookiesForced "Εξαναγκασμός κÏυπτογÏάφησης σε όλα τα cookies που εγκαταστάθηκαν μέσω HTTPS από τους ακόλουθους ιστότοπους:">
+<!ENTITY noscriptSecureCookiesExceptions "Îα αγνοοÏνται μη ασφαλή cookies που εγκαταστάθηκαν μέσω HTTPS από τους ακόλουθους ιστότοπους:">
+<!ENTITY noscriptClearClickTitle "ΠÏοειδοποίηση clearClick">
+<!ENTITY noscriptClearClickHeader "Πιθανή Ï€Ïοσπάθεια επικάλυψης UI / Clickjacking!">
+<!ENTITY noscriptClearClickDescription "Το NoScript εντόπισε αλληλεπίδÏαση του Ï€Î¿Î½Ï„Î¹ÎºÎ¹Î¿Ï Î® του πληκτÏολογίου με ένα μεÏικώς κÏυφό στοιχείο. Κάντε κλικ στην παÏαπάνω εικόνα για εναλλαγή ανάμεσα στην απαγοÏευμένη και την επιτÏεπόμενη εκδοχή.">
+<!ENTITY noscriptClearClickOpt "ΠÏοστασία clearClick σε ιστότοπους...">
+<!ENTITY noscriptClearClickReport "ΑναφοÏά">
+<!ENTITY noscriptClearClickReport.accesskey "α">
+<!ENTITY noscriptClearClickReportId "ΑναγνωÏιστικό αναφοÏάς:">
+<!ENTITY noscriptTrustedPagesAdj "έμπιστους">
+<!ENTITY noscriptUntrustedPagesAdj "μη έμπιστους">
+<!ENTITY noscriptKeepLocked "ΔιατήÏηση κλειδώματος στοιχείου (συνιστάται)">
+<!ENTITY noscriptEmbeddings "Ενσωματωμένα αντικείμενα">
+<!ENTITY noscriptPrev "ΠÏοηγοÏμενο">
+<!ENTITY noscriptNext "Επόμενο">
+<!ENTITY noscriptFrameOptErr.title "Αυτό το πεÏιεχόμενο δεν μποÏεί να παÏουσιαστεί σε πλαίσιο">
+<!ENTITY noscriptFrameOptErr.desc "Για να Ï€ÏοστατεÏσει την ασφάλεια σας, ο εκδότης του πεÏιεχομένου δεν επιτÏέπει την Ï€Ïοβολή σε πλαίσιο">
+<!ENTITY noscriptFrameOptErr.link "Κάντε κλικ εδώ για να ανοίξετε το πεÏιεχόμενο σε νέο παÏάθυÏο">
+<!ENTITY noscriptBookmarkSync "ΑντίγÏαφο Ïυθμίσεων του NoScript σε σελιδοδείκτη για εÏκολο συγχÏονισμό">
+<!ENTITY noscriptShowReleaseNotes "ΠÏοβολή των σημειώσεων έκδοσης μετά από ενημέÏωση">
+<!ENTITY ABE "ΑBE">
+<!ENTITY ABE.accesskey "Α">
+<!ENTITY ABE.rulesets.label "ΣÏνολα κανόνων:">
+<!ENTITY ABE.enabled.label "ΕνεÏγοποίηση ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Îα επιτÏέπεται σε ιστότοπους να επιβάλουν τα δικά τους σÏνολα κανόνων">
+<!ENTITY ABE.edit.label "ΕπεξεÏγασία...">
+<!ENTITY ABE.edit.accesskey "ε">
+<!ENTITY ABE.enable.label "ΕνεÏγοποίηση">
+<!ENTITY ABE.enable.accesskey "ν">
+<!ENTITY ABE.disable.label "ΑπενεÏγοποίηση">
+<!ENTITY ABE.disable.accesskey "ο">
+<!ENTITY ABE.refresh.label "Ανανέωση">
+<!ENTITY ABE.refresh.accesskey "α">
+<!ENTITY noscriptUninstall "Απεγκατάσταση">
+<!ENTITY noscriptRecentBlocked "ΠÏόσφατα απαγοÏευμένοι ιστότοποι">
+<!ENTITY noscriptExternalFilters "ΕξωτεÏικά φίλτÏα">
+<!ENTITY noscriptEF.enable "ΕνεÏγοποίηση εξωτεÏικών φίλτÏων">
+<!ENTITY noscriptEF.add "Îέο φίλτÏο…">
+<!ENTITY noscriptEF.executable "Εκτελέσιμο αÏχείο:">
+<!ENTITY noscriptEF.browse "Εντοπισμός...">
+<!ENTITY noscriptEF.contentType "ΤÏπος πεÏιεχομένου (ΜΙΜΕ) που θα φιλτÏαÏιστεί (ακÏιβές ταίÏιασμα ή κανονική έκφÏαση)">
+<!ENTITY noscriptEF.exceptions "Îα μην φιλτÏάÏονται αντικείμενα από τις παÏακάτω σελίδες:">
+<!ENTITY noscriptEF.remove "ΑφαίÏεση">
+<!ENTITY noscriptPreset "Βαθμός ασφαλείας">
+<!ENTITY noscriptPreset.off "ΑπενεÏγοποιημένο (είστε σίγουÏοι;!)">
+<!ENTITY noscriptPreset.low "ΧαλαÏÏŒ (Λίστα απαγοÏευμένων + Δικτυακή ασφάλεια)">
+<!ENTITY noscriptPreset.medium "Κλασικό (Λίστα επιτÏεπομένων + δικτυακή ασφάλεια)">
+<!ENTITY noscriptPreset.high "ΟχυÏÏŒ (ΠλήÏης αποκλεισμός)">
+<!ENTITY noscript.hoverUI "Άνοιγμα του Î¼ÎµÎ½Î¿Ï Î±Î´ÎµÎ¹Î¿Î´Î¿Ï„Î®ÏƒÎµÏ‰Î½ όταν πεÏνάει το ποντίκι πάνω από το εικονίδιο του NoScript">
+<!ENTITY noscriptDonate "ΔωÏεά">
+<!ENTITY noscriptDonate.accesskey "ω">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/el/noscript/noscript.properties b/extensions/noscript/chrome/locale/el/noscript/noscript.properties
new file mode 100644
index 0000000..85be4b9
--- /dev/null
+++ b/extensions/noscript/chrome/locale/el/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Îα επιτÏέπονται τα σενάÏια εντολών γενικά (επικίνδυνο)
+forbidGlobal=Îα απαγοÏεÏονται τα σενάÏια εντολών γενικά (Ï€Ïοτεινόμενο)
+allowLocal=Îα επιτÏέπεται για %S
+allowTemp=Îα επιτÏέπεται Ï€ÏοσωÏινά για %S
+forbidLocal=Îα απαγοÏεÏεται για %S
+allowed.glb=Κίνδυνος! Τα σενάÏια εντολών επιτÏέπονται γενικά
+allowed.yes=Τα σενάÏια εντολών επιτÏέπονται Ï€Ïος το παÏόν
+allowed.prt=Τα σενάÏια εντολών επιτÏέπονται μεÏικώς
+allowed.no=Τα σενάÏια εντολών δεν επιτÏέπονται Ï€Ïος το παÏόν
+global.warning.title=ΠÏοειδοποίηση!
+global.warning.text=Τα σενάÏια εντολών θα επιτÏέπονται γενικά (σε όλες τις σελίδες).\n Αυτό είναι πιθανότατα επικίνδυνο.\nÎα εφαÏμοστεί;
+audio.samples=Δείγματα ήχου
+confirm=Είστε σίγουÏοι για την επιλογή σας;
+alwaysAsk=Îα γίνεται πάντα εÏώτηση για επιβεβαίωση
+notifyHide=ΑπόκÏυψη μετά από %S δευτεÏόλεπτα
+trust=Îα θεωÏείται έμπιστο το %S
+distrust=Σημείωση του %S ως μη έμπιστου
+untrustedOrigin=μια μη έμπιστη πηγή
+xss.notify.generic=Το NoScript φίλτÏαÏε μια πιθανή απόπειÏα cross-site scripting (XSS) από το %S. Οι λεπτομέÏειες έχουν καταγÏαφεί στην κονσόλα.
+xss.notify.showConsole=ΠÏοβολή κονσόλας…
+xss.notify.showConsole.accessKey=κ
+xss.reason.filterXGet=Έγινε εκκαθάÏιση Ïποπτου αιτήματος. ΥπήÏχε αίτημα για το αÏχικό URL [%1$S] από το [%2$S]. ΕκκαθαÏίστηκε το URL: [%3$S].
+xss.reason.filterXGetRef=Έγινε εκκαθάÏιση Ïποπτου αιτήματος referer. ΥπήÏχε αίτημα για το URL [%1$S] από το [%2$S]. ΕκκαθαÏίστηκε ο Referer: [%3$S].
+xss.reason.filterXPost=Έγινε εκκαθάÏιση Ïποπτης αποστολής από το [%2$S] στο [%1$S]. ΜετατÏάπηκε σε αίτημα GET λήψης.
+unsafeReload.warning=ΜΗ ΑΣΦΑΛΗΣ ανανέωση Ïποπτου\n\n%1$S [%2$S]\n\nΑπό[%3$S]\n\nΤο NoScript δεν παÏέχει Ï€Ïοστασία γι' αυτό το αίτημα!\n
+metaRefresh.notify=Το NoScript μπλόκαÏε μια ανακατεÏθυνση <META> εντός ενός στοιχείου <NOSCRIPT>: %S σε %S δευτεÏόλεπτα.
+metaRefresh.notify.follow=ΑκολοÏθηση ανακατεÏθυνσης
+metaRefresh.notify.follow.accessKey=Α
+notify.options=Επιλογές
+notify.options.accessKey=Ε
+reset.title=ΕπαναφοÏά αÏχικών Ïυθμίσεων του NoScript
+reset.warning=Θα γίνει επαναφοÏά στις αÏχικές Ïυθμίσεις όλων των επιλογών του NoScript και των δικαιωμάτων ιστότοπων..\n Αυτή η ενέÏγεια δεν είναι αναστÏέψιμη.\n Συνέχεια;
+bookmarkSync.title=Σελιδοδείκτης Ïυθμίσεων NoScript
+bookmarkSync.message=Αυτός ο σελιδοδείκτης δεν Ï€ÏοοÏίζεται για άνοιγμα αλλά για συγχÏονισμό Ïυθμίσεων με υπηÏεσίες όπως το Weave ή η επέκταση XMarks
+bookmarkSync.confirm=Το NoScript εντόπισε ένα σελιδοδείκτη συγχÏÎ¿Î½Î¹ÏƒÎ¼Î¿Ï Ïυθμίσεων αποθηκευμένο στο\n%S.\nΘέλετε σίγουÏα να αντικαταστήσετε τις τοπικές σας Ïυθμίσεις του NoScript με τα πεÏιεχόμενα Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… σελιδοδείκτη;
+ABE.notify=Το αίτημα %1$S φιλτÏαÏίστηκε από τον κανόνα ABE: <%2$S> %3$S
+ABE.chooseEditor=ΠαÏακαλοÏμε επιλέξτε επεξεÏγαστή κειμένου για σÏνολα κανόνων ΑΒΕ
+ABE.syntaxError=Σφάλμα σÏνταξης κανόνα ΑΒΕ
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Îα επιτÏέπονται όλα από %S
+allowTempFrom=Îα επιτÏέπονται Ï€ÏοσωÏινά όλα από %S
+siteInfo.confirm=ΠÏόκειται να ζητήσετε πληÏοφοÏίες για τον ιστότοπο «%1$S»\nυποβάλλοντας αίτημα στο %2$S.\nΘέλετε να συνεχίσετε;
+siteInfo.tooltip=Πατήστε μεσαίο ή shift + κλικ για πληÏοφοÏίες ιστότοπου...
+ef.activate=ΦίλτÏο %S
+ef.options=%S επιλογές...
+ef.newName=Εισάγετε όνομα για το νέο φίλτÏο:
+ef.locateExe=Επιλέξτε εκτελέσιμο αÏχείο για το φίλτÏο %S
+disable=ΑπενεÏγοποίηση %S
+disable.accessKey=Ï€
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/en-GB/noscript/about.properties b/extensions/noscript/chrome/locale/en-GB/noscript/about.properties
new file mode 100644
index 0000000..fb09c56
--- /dev/null
+++ b/extensions/noscript/chrome/locale/en-GB/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality… Experts will agree: Firefox is really safer with NoScript :-)
+aboutTitle=About %S
+extensionContributors=Contributors:
+extensionContributors.tip=People you should thank for this extension
+extensionCreatorLabel=Author:
+changelog=Changelog
+changelog.tip=Show changelog
+license=Licence
+license.tip=Read end-user licence
+logo.tip=Visit extension home page
+sponsor.tip=Visit sponsor home page
+informaction.tip=Visit InformAction home page
+extensionHomepage.tip=Visit extension home page
+extensionCreator.tip=Visit author home page
+version=Version %S
diff --git a/extensions/noscript/chrome/locale/en-GB/noscript/noscript.dtd b/extensions/noscript/chrome/locale/en-GB/noscript/noscript.dtd
new file mode 100644
index 0000000..713b81d
--- /dev/null
+++ b/extensions/noscript/chrome/locale/en-GB/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Options…">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript Options">
+<!ENTITY noscriptAbout "About NoScript 5.1.8.5…">
+<!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. &quot;http://www.site.com&quot; or &quot;site.com&quot;) of the site you want to allow and then click Allow.">
+<!ENTITY noscriptWebAddress "Address of web site:">
+<!ENTITY noscriptAllow "Allow">
+<!ENTITY noscriptAllow.accesskey "l">
+<!ENTITY noscriptForbid "Forbid">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Mark as Trusted">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Mark as Untrusted">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Remove Selected Sites">
+<!ENTITY noscriptGloballyEnabled "Scripts Globally Allowed (dangerous)">
+<!ENTITY noscriptAutoReload "Automatically reload affected pages when permissions change">
+<!ENTITY noscriptGeneral "General">
+<!ENTITY noscriptAppearance "Appearance">
+<!ENTITY noscriptShow "Show…">
+<!ENTITY noscriptCtxMenu "Contextual menu">
+<!ENTITY noscriptStatusIcon "Status bar icon">
+<!ENTITY noscriptFullAddr "Full Addresses (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Full Domains (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Base 2nd level Domains (noscript.net)">
+<!ENTITY noscriptTempCmd "Temporarily allow […]">
+<!ENTITY noscriptSound "Audio feedback when scripts are blocked">
+<!ENTITY noscriptImport "Import">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Export">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Show message about blocked scripts">
+<!ENTITY noscriptNotify.bottom "Place message at the bottom">
+<!ENTITY noscriptSound.choose "Choose">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Play">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Reset default">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Advanced">
+<!ENTITY noscriptAdditionalPermissions "Additional permissions for trusted sites">
+<!ENTITY noscriptAllowClipboard "Allow rich text copy and paste from external clipboard">
+<!ENTITY noscriptAdditionalRestrictions "Additional restrictions for untrusted sites">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Apply these restrictions to whitelisted sites too">
+<!ENTITY noscriptForbidJava "Forbid Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Forbid XSLT">
+<!ENTITY noscriptForbidSilverlight "Forbid Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Forbid &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Forbid &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Forbid @font-face">
+<!ENTITY noscriptForbidMedia "Forbid &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Forbid Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Forbid other plugins">
+<!ENTITY noscriptReloadWarn "These options will take effect on new or (manually) reloaded pages">
+<!ENTITY noscriptConfirmUnblock "Ask for confirmation before temporarily unblocking an object">
+<!ENTITY noscriptStatusLabel "Status bar label">
+<!ENTITY noscriptForbidBookmarklets "Forbid bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Show placeholder icon">
+<!ENTITY noscriptTruncateTitle "Truncate document titles">
+<!ENTITY noscriptFixLinks "Attempt to fix JavaScript links">
+<!ENTITY noscriptAllowBookmarks "Allow sites opened through bookmarks">
+<!ENTITY noscriptAllowViaBookmarks "Allow sites opened through bookmarks">
+<!ENTITY noscriptAllowPing "Allow &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Allow local links">
+<!ENTITY noscriptForbidPing "Forbid &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Forbid META redirections inside &lt;NOSCRIPT&gt; elements">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "Whitelist">
+<!ENTITY noscriptPermissions "Permissions">
+<!ENTITY noscriptRefresh "Refresh">
+<!ENTITY noscriptNotifications "Notifications">
+<!ENTITY noscriptToolbarToggle "Left clicking on NoScript toolbar button toggles permissions for current top-level site">
+<!ENTITY noscriptTrusted "Trusted">
+<!ENTITY noscriptUntrusted "Untrusted">
+<!ENTITY noscriptUnknown "Unknown">
+<!ENTITY noscriptAdd "Add">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Close">
+<!ENTITY noscriptSiteManager "Site Manager">
+<!ENTITY noscriptSecurityManager "Security Manager">
+<!ENTITY noscriptPolicies "Policies">
+<!ENTITY noscriptDefaultPolicies "Default Policies">
+<!ENTITY noscriptSitePolicies "Site Specific Policies">
+<!ENTITY noscriptNselNever "Hide &lt;NOSCRIPT&gt; elements">
+<!ENTITY noscriptNselForce "Show the &lt;NOSCRIPT&gt; element which follows a blocked &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Temporarily allow top-level sites by default">
+<!ENTITY noscriptDescription "Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality… Experts will agree: Firefox is really safer with NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Block CSS-based scanners">
+<!ENTITY noscriptOptFilterXGet "Sanitise cross-site suspicious requests">
+<!ENTITY noscriptOptFilterXPost "Turn cross-site POST requests into data-less GET requests">
+<!ENTITY noscriptShowConsole "Show Console…">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ…">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Unsafe Reload">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Anti-XSS Protection Exceptions">
+<!ENTITY noscriptXssExceptions.description "Destinations matching these regular expressions will NOT be protected against XSS.">
+<!ENTITY noscriptMatchSample "Pattern matching sample:">
+<!ENTITY noscriptReset "Reset">
+<!ENTITY noscriptReset.accesskey "s">
+<!ENTITY noscriptResetDef "Reset to defaults">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revoke Temporary Permissions">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "No placeholder for objects coming from sites marked as untrusted">
+<!ENTITY noscriptCollapseBlockedObjects "Collapse blocked objects">
+<!ENTITY noscriptExceptions "Exceptions…">
+<!ENTITY noscriptBlockedObjects "Blocked Objects">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Block every object coming from a site marked as untrusted">
+<!ENTITY noscriptTempAllowPage "Temporarily allow all this page">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "Allow all this page">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Make page permissions permanent">
+<!ENTITY noscriptTempToPerm.accesskey "M">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behaviour">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image below to cycle between the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Embeddings">
+<!ENTITY noscriptPrev "Previous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronisation">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript\'s icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptForbidWebGL "Forbid WebGL">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/en-GB/noscript/noscript.properties b/extensions/noscript/chrome/locale/en-GB/noscript/noscript.properties
new file mode 100644
index 0000000..35e928f
--- /dev/null
+++ b/extensions/noscript/chrome/locale/en-GB/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Allow Scripts Globally (dangerous)
+forbidGlobal=Forbid Scripts Globally (advised)
+allowLocal=Allow %S
+allowTemp=Temporarily allow %S
+forbidLocal=Forbid %S
+allowed.glb=Danger! Scripts Globally Allowed
+allowed.yes=Scripts Currently Allowed
+allowed.prt=Scripts Partially Allowed
+allowed.no=Scripts Currently Forbidden
+global.warning.title=Warning!
+global.warning.text=Scripts are going to be allowed globally (for every site).\nThis is a potentially dangerous action.\nDo you really want to proceed?
+audio.samples=Audio samples
+confirm=Are you sure?
+alwaysAsk=Always ask for confirmation
+notifyHide=Hide after %S seconds
+trust=Trust %S
+distrust=Mark %S as Untrusted
+untrustedOrigin=an untrusted origin
+xss.notify.generic=NoScript filtered a potential cross-site scripting (XSS) attempt from %S. Technical details have been logged to the Console.
+xss.notify.showConsole=Show Console…
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Sanitized suspicious request. Original URL [%1$S] requested from [%2$S]. Sanitized URL: [%3$S].
+xss.reason.filterXGetRef=Sanitized suspicious request referer. URL [%1$S] requested from [%2$S]. Sanitized Referrer: [%3$S].
+xss.reason.filterXPost=Sanitized suspicious upload to [%1$S] from [%2$S]: transformed into a download-only GET request.
+unsafeReload.warning=UNSAFELY reloading a suspicious\n\n%1$S [%2$S]\n\nFROM [%3$S]\n\nNoScript will NOT protect this request!\n
+metaRefresh.notify=NoScript blocked a <META> redirection inside a <NOSCRIPT> element: %S in %S seconds.
+metaRefresh.notify.follow=Follow Redirection
+metaRefresh.notify.follow.accessKey=F
+notify.options=Options
+notify.options.accessKey=O
+reset.title=NoScript Reset
+reset.warning=ALL the NoScript preferences and site permissions will be reset to their default values immediately.\nThis action cannot be reverted.\nDo you want to continue?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark\'s content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You\'re about to ask for information about the \"%1$S\" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/en-US/noscript/about.properties b/extensions/noscript/chrome/locale/en-US/noscript/about.properties
new file mode 100644
index 0000000..9aa6835
--- /dev/null
+++ b/extensions/noscript/chrome/locale/en-US/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality… Experts will agree: Firefox is really safer with NoScript :-)
+aboutTitle=About %S
+extensionContributors=Contributors:
+extensionContributors.tip=People you should thank for this extension
+extensionCreatorLabel=Author:
+changelog=Changelog
+changelog.tip=Show changelog
+license=License
+license.tip=Read end-user license
+logo.tip=Visit extension home page
+sponsor.tip=Visit sponsor home page
+informaction.tip=Visit InformAction home page
+extensionHomepage.tip=Visit extension home page
+extensionCreator.tip=Visit author home page
+version=Version %S
diff --git a/extensions/noscript/chrome/locale/en-US/noscript/noscript.dtd b/extensions/noscript/chrome/locale/en-US/noscript/noscript.dtd
new file mode 100644
index 0000000..efb7ff7
--- /dev/null
+++ b/extensions/noscript/chrome/locale/en-US/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Options…">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript Options">
+<!ENTITY noscriptAbout "About NoScript 5.1.8.5…">
+<!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. &quot;http://www.site.com&quot; or &quot;site.com&quot;) of the site you want to allow and then click Allow.">
+<!ENTITY noscriptWebAddress "Address of web site:">
+<!ENTITY noscriptAllow "Allow">
+<!ENTITY noscriptAllow.accesskey "l">
+<!ENTITY noscriptForbid "Forbid">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Mark as Trusted">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Mark as Untrusted">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Remove Selected Sites">
+<!ENTITY noscriptGloballyEnabled "Scripts Globally Allowed (dangerous)">
+<!ENTITY noscriptAutoReload "Automatically reload affected pages when permissions change">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptGeneral "General">
+<!ENTITY noscriptAppearance "Appearance">
+<!ENTITY noscriptShow "Show…">
+<!ENTITY noscriptCtxMenu "Contextual menu">
+<!ENTITY noscriptStatusIcon "Status bar icon">
+<!ENTITY noscriptFullAddr "Full Addresses (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Full Domains (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Base 2nd level Domains (noscript.net)">
+<!ENTITY noscriptTempCmd "Temporarily allow […]">
+<!ENTITY noscriptSound "Audio feedback when scripts are blocked">
+<!ENTITY noscriptImport "Import">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Export">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Show message about blocked scripts">
+<!ENTITY noscriptNotify.bottom "Place message at the bottom">
+<!ENTITY noscriptSound.choose "Choose">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Play">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Reset default">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Advanced">
+<!ENTITY noscriptAdditionalPermissions "Additional permissions for trusted sites">
+<!ENTITY noscriptAllowClipboard "Allow rich text copy and paste from external clipboard">
+<!ENTITY noscriptAdditionalRestrictions "Additional restrictions for untrusted sites">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Apply these restrictions to whitelisted sites too">
+<!ENTITY noscriptForbidJava "Forbid Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Forbid XSLT">
+<!ENTITY noscriptForbidSilverlight "Forbid Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Forbid &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Forbid &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Forbid @font-face">
+<!ENTITY noscriptForbidWebGL "Forbid WebGL">
+<!ENTITY noscriptForbidMedia "Forbid &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Forbid Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Forbid other plugins">
+<!ENTITY noscriptReloadWarn "These options will take effect on new or (manually) reloaded pages">
+<!ENTITY noscriptConfirmUnblock "Ask for confirmation before temporarily unblocking an object">
+<!ENTITY noscriptStatusLabel "Status bar label">
+<!ENTITY noscriptForbidBookmarklets "Forbid bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Show placeholder icon">
+<!ENTITY noscriptTruncateTitle "Truncate document titles">
+<!ENTITY noscriptFixLinks "Attempt to fix JavaScript links">
+<!ENTITY noscriptAllowBookmarks "Allow sites opened through bookmarks">
+<!ENTITY noscriptAllowViaBookmarks "Allow sites opened through bookmarks">
+<!ENTITY noscriptAllowPing "Allow &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Allow local links">
+<!ENTITY noscriptForbidPing "Forbid &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Forbid META redirections inside &lt;NOSCRIPT&gt; elements">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "Whitelist">
+<!ENTITY noscriptPermissions "Permissions">
+<!ENTITY noscriptRefresh "Refresh">
+<!ENTITY noscriptNotifications "Notifications">
+<!ENTITY noscriptToolbarToggle "Left clicking on NoScript toolbar button toggles permissions for current top-level site">
+<!ENTITY noscriptTrusted "Trusted">
+<!ENTITY noscriptUntrusted "Untrusted">
+<!ENTITY noscriptUnknown "Unknown">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptAdd "Add">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Close">
+<!ENTITY noscriptSiteManager "Site Manager">
+<!ENTITY noscriptSecurityManager "Security Manager">
+<!ENTITY noscriptPolicies "Policies">
+<!ENTITY noscriptDefaultPolicies "Default Policies">
+<!ENTITY noscriptSitePolicies "Site Specific Policies">
+<!ENTITY noscriptNselNever "Hide &lt;NOSCRIPT&gt; elements">
+<!ENTITY noscriptNselForce "Show the &lt;NOSCRIPT&gt; element which follows a blocked &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Temporarily allow top-level sites by default">
+<!ENTITY noscriptDescription "Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality… Experts will agree: Firefox is really safer with NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Block CSS-based scanners">
+<!ENTITY noscriptOptFilterXGet "Sanitize cross-site suspicious requests">
+<!ENTITY noscriptOptFilterXPost "Turn cross-site POST requests into data-less GET requests">
+<!ENTITY noscriptShowConsole "Show Console…">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ…">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Unsafe Reload">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Anti-XSS Protection Exceptions">
+<!ENTITY noscriptXssExceptions.description "Destinations matching these regular expressions will NOT be protected against XSS.">
+<!ENTITY noscriptMatchSample "Pattern matching sample:">
+<!ENTITY noscriptReset "Reset">
+<!ENTITY noscriptReset.accesskey "s">
+<!ENTITY noscriptResetDef "Reset to defaults">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revoke Temporary Permissions">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "No placeholder for objects coming from sites marked as untrusted">
+<!ENTITY noscriptCollapseBlockedObjects "Collapse blocked objects">
+<!ENTITY noscriptExceptions "Exceptions…">
+<!ENTITY noscriptBlockedObjects "Blocked Objects">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Block every object coming from a site marked as untrusted">
+<!ENTITY noscriptTempAllowPage "Temporarily allow all this page">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "Allow all this page">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Make page permissions permanent">
+<!ENTITY noscriptTempToPerm.accesskey "M">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behavior">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image below to cycle between the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Embeddings">
+<!ENTITY noscriptPrev "Previous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/en-US/noscript/noscript.properties b/extensions/noscript/chrome/locale/en-US/noscript/noscript.properties
new file mode 100644
index 0000000..31fb6d3
--- /dev/null
+++ b/extensions/noscript/chrome/locale/en-US/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Allow Scripts Globally (dangerous)
+forbidGlobal=Forbid Scripts Globally (advised)
+allowLocal=Allow %S
+allowTemp=Temporarily allow %S
+forbidLocal=Forbid %S
+allowed.glb=Danger! Scripts Globally Allowed
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+allowed.yes=Scripts Currently Allowed
+allowed.prt=Scripts Partially Allowed
+allowed.no=Scripts Currently Forbidden
+global.warning.title=Warning!
+global.warning.text=Scripts are going to be allowed globally (for every site).\n This is a potentially dangerous action.\nDo you really want to proceed?
+audio.samples=Audio samples
+confirm=Are you sure?
+alwaysAsk=Always ask for confirmation
+notifyHide=Hide after %S seconds
+trust=Trust %S
+distrust=Mark %S as Untrusted
+untrustedOrigin=an untrusted origin
+xss.notify.generic=NoScript filtered a potential cross-site scripting (XSS) attempt from %S. Technical details have been logged to the Console.
+xss.notify.showConsole=Show Console…
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Sanitized suspicious request. Original URL [%1$S] requested from [%2$S]. Sanitized URL: [%3$S].
+xss.reason.filterXGetRef=Sanitized suspicious request referer. URL [%1$S] requested from [%2$S]. Sanitized Referrer: [%3$S].
+xss.reason.filterXPost=Sanitized suspicious upload to [%1$S] from [%2$S]: transformed into a download-only GET request.
+unsafeReload.warning=UNSAFELY reloading a suspicious\n\n%1$S [%2$S]\n\nFROM [%3$S]\n\nNoScript will NOT protect this request!\n
+metaRefresh.notify=NoScript blocked a <META> redirection inside a <NOSCRIPT> element: %S in %S seconds.
+metaRefresh.notify.follow=Follow Redirection
+metaRefresh.notify.follow.accessKey=F
+notify.options=Options
+notify.options.accessKey=O
+reset.title=NoScript Reset
+reset.warning=ALL the NoScript preferences and site permissions will be reset to their default values immediately.\nThis action cannot be reverted.\nDo you want to continue?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark's content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/eo/noscript/about.properties b/extensions/noscript/chrome/locale/eo/noscript/about.properties
new file mode 100644
index 0000000..f4b6fdf
--- /dev/null
+++ b/extensions/noscript/chrome/locale/eo/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Plia protekto por via Firefox: NoScript permesas uzon de JavaSkripto, Javo kc nur al fidataj retejoj de vi elektitaj (ekzemple via retbankejo). Tiu ĉi laŭblanklista anticipa blokado malhelpas misuzadon de malsekuroj (konataj kaj eĉ nekonataj!) sen funkcikripligo… Kompetentuloj jesos: Firefox vere estas pli sekura kun NoScript :-)
+aboutTitle=Pri %S
+extensionContributors=Kontribuantoj:
+extensionContributors.tip=Tiuj, kiujn vi devus danki por ĉi-tiu etendoprogramo
+extensionCreatorLabel=AÅ­toro:
+changelog=ÅœanÄoprotokolo
+changelog.tip=Vidigi ÅanÄoprotokolon
+license=Permesilo
+license.tip=Legu la permesilon por la uzanto
+logo.tip=Vizitu la retejon de la etendoprogramo
+sponsor.tip=Vizitu la mecenatan retejon
+informaction.tip=Vizitu la retejon de InformAction
+extensionHomepage.tip=Vizitu la retejon de la etendoprogramo
+extensionCreator.tip=Vizitu la retejon de la aÅ­toro
+version=Versio %S
diff --git a/extensions/noscript/chrome/locale/eo/noscript/noscript.dtd b/extensions/noscript/chrome/locale/eo/noscript/noscript.dtd
new file mode 100644
index 0000000..9e03364
--- /dev/null
+++ b/extensions/noscript/chrome/locale/eo/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opcioj…">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Opcioj de NoScript">
+<!ENTITY noscriptAbout "Pri NoScript 5.1.8.5…">
+<!ENTITY noscriptPermissionsText "Vi povas specifi, kiuj ttt-ejoj rajtu plenumigi skriptojn. Entajpu la adreson aÅ­ la domajnonomon (ekz. “http://www.retejo.org†aÅ­ “retejo.orgâ€) de la ttt-ejo, kiun vi volas rajtigi, kaj poste alklaku “Rajtigiâ€.">
+<!ENTITY noscriptWebAddress "Adreso de retpaÄaro:">
+<!ENTITY noscriptAllow "Rajtigi">
+<!ENTITY noscriptAllow.accesskey "R">
+<!ENTITY noscriptForbid "Malrajtigi">
+<!ENTITY noscriptForbid.accesskey "M">
+<!ENTITY noscriptTrust "Marki kiel fidata">
+<!ENTITY noscriptTrust.accesskey "F">
+<!ENTITY noscriptUntrust "Marki kiel nefidata">
+<!ENTITY noscriptUntrust.accesskey "N">
+<!ENTITY noscriptRemoveSelected "Forigi la elektitajn ttt-ejojn">
+<!ENTITY noscriptGloballyEnabled "DefaÅ­lte rajtigi ĉiujn retejojn (danÄere)">
+<!ENTITY noscriptAutoReload "AÅ­tomate reÅargi koncernatajn paÄojn ĉe ÅanÄo de permesoj">
+<!ENTITY noscriptGeneral "Äœeneralaj">
+<!ENTITY noscriptAppearance "Aspekto">
+<!ENTITY noscriptShow "Vidigi…">
+<!ENTITY noscriptCtxMenu "Kunteksta menuo">
+<!ENTITY noscriptStatusIcon "Statstrian bildeton">
+<!ENTITY noscriptFullAddr "Tutaj adresoj (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Tutaj domajnoj (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Bazaj duanivelaj domajnoj (noscript.net)">
+<!ENTITY noscriptTempCmd "Dumtempe rajtigi […]">
+<!ENTITY noscriptSound "Sona atentigo pri blokateco de skriptoj">
+<!ENTITY noscriptImport "Importi">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Eksporti">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Montri mesaÄon pri blokitaj skriptoj">
+<!ENTITY noscriptNotify.bottom "Meti la mesaÄon malsupren">
+<!ENTITY noscriptSound.choose "Elekti">
+<!ENTITY noscriptSound.choose.accesskey "E">
+<!ENTITY noscriptSound.play "Ludi">
+<!ENTITY noscriptSound.play.accesskey "L">
+<!ENTITY noscriptSound.reset "RedefaÅ­ltigi">
+<!ENTITY noscriptSound.reset.accesskey "D">
+<!ENTITY noscriptAdvanced "Spertulaj">
+<!ENTITY noscriptAdditionalPermissions "Pliaj permesoj por fidataj retejoj">
+<!ENTITY noscriptAllowClipboard "Permesi kopiadon kaj enmetadon de aranÄita (&quot;riĉa&quot;) teksto je la ekstera tondujo">
+<!ENTITY noscriptAdditionalRestrictions "Pliaj limigoj por nefidataj retejoj">
+<!ENTITY noscriptPlugins "Kromaĵoj">
+<!ENTITY noscriptContentBlocker "Apliki ĉi tiujn limigojn ankaŭ al fidataj retejoj">
+<!ENTITY noscriptForbidJava "Malpermesi Äœavon (Javaâ„¢)">
+<!ENTITY noscriptForbidXSLT "Malpermesi XSLT-on">
+<!ENTITY noscriptForbidSilverlight "Malpermesi Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Malpermesi 〈IFRAME〉">
+<!ENTITY noscriptForbidFrames "Malpermesi 〈FRAME〉">
+<!ENTITY noscriptForbidFonts "Malpermesi @font-face">
+<!ENTITY noscriptForbidWebGL "Malpermesi WebGL">
+<!ENTITY noscriptForbidMedia "Malpermesi 〈AUDIO〉 / 〈VIDEO〉">
+<!ENTITY noscriptForbidFlash "Malpermesi Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Malpermesi aliajn kromaĵojn">
+<!ENTITY noscriptReloadWarn "Tiuj ĉi agordoj efikos nur por paÄoj novÅargotaj aÅ­ reÅargotaj de vi">
+<!ENTITY noscriptConfirmUnblock "Peti konfirmon antaÅ­ ol provizore malbloki objekton">
+<!ENTITY noscriptStatusLabel "Statstrian tekston">
+<!ENTITY noscriptForbidBookmarklets "Malpermesi skriptajn “paÄosignojn†(bookmarklets)">
+<!ENTITY noscriptShowPlaceholder "Montri lokokupan bildeton">
+<!ENTITY noscriptTruncateTitle "Truncate document titles">
+<!ENTITY noscriptFixLinks "Provi normaligi JavaSkriptajn ligilojn">
+<!ENTITY noscriptAllowBookmarks "Rajtigi retejojn Åargatajn per paÄosignoj">
+<!ENTITY noscriptAllowViaBookmarks "Rajtigi retejojn Åargitajn per paÄosignoj">
+<!ENTITY noscriptAllowPing "Permesi 〈A PING…〉">
+<!ENTITY noscriptAllowLocalLinks "Permesi lokajn ligojn">
+<!ENTITY noscriptForbidPing "Malpermesi 〈A PING…〉">
+<!ENTITY noscriptForbidMetaRefresh "Malpermesi META-alidirektojn ene de elementoj 〈NOSCRIPT〉">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "Montri mesaÄon pri blokitaj META-alidirektoj">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "Blanklisto">
+<!ENTITY noscriptPermissions "Rajtoj">
+<!ENTITY noscriptRefresh "ReÅargi">
+<!ENTITY noscriptNotifications "Sciigoj">
+<!ENTITY noscriptToolbarToggle "Maldekstr-alklako de la ilarstria bildo de NoScript baskuligu rajtigon de la montrata senpere Åargita retejo.">
+<!ENTITY noscriptTrusted "Fidataj">
+<!ENTITY noscriptUntrusted "Nefidataj">
+<!ENTITY noscriptUnknown "Nekonata">
+<!ENTITY noscriptAdd "Aldoni">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Fermi">
+<!ENTITY noscriptSiteManager "Site Manager">
+<!ENTITY noscriptSecurityManager "Security Manager">
+<!ENTITY noscriptPolicies "Policies">
+<!ENTITY noscriptDefaultPolicies "Default Policies">
+<!ENTITY noscriptSitePolicies "Site Specific Policies">
+<!ENTITY noscriptNselNever "KaÅi erojn 〈NOSCRIPT〉">
+<!ENTITY noscriptNselForce "Vidigi la eron 〈NOSCRIPT〉, kiu sekvas baritan 〈SCRIPT〉">
+<!ENTITY noscriptAutoAllowTopLevel "Provizore rajtigi ĉiujn senpere (ne en kadro ks) vizitatajn retejojn">
+<!ENTITY noscriptDescription "Plia protekto por via Firefox: NoScript permesas uzon de JavaSkripto, Javo kc nur al fidataj retejoj de vi elektitaj (ekzemple via retbankejo). Tiu ĉi laŭblanklista anticipa blokado malhelpas misuzadon de malsekuroj (konataj kaj eĉ nekonataj!) sen funkcikripligo… Kompetentuloj jesos: Firefox vere estas pli sekura kun NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Bloki per-CSS-ajn skanilojn">
+<!ENTITY noscriptOptFilterXGet "Purigi suspektajn interretejajn petojn">
+<!ENTITY noscriptOptFilterXPost "Transformu inter-retejajn POST-petojn en sendatenajn GET-petojn.">
+<!ENTITY noscriptShowConsole "Vidigi konzolon…">
+<!ENTITY noscriptShowConsole.accesskey "K">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "Respondaro pri XSS (angle)…">
+<!ENTITY noscriptXssFaq.accesskey "R">
+<!ENTITY noscriptUnsafeReload "Nesekura reÅargo">
+<!ENTITY noscriptUnsafeReload.accesskey "N">
+<!ENTITY noscriptXssExceptions "Esceptoj el kontraÅ­-XSS-a protekto">
+<!ENTITY noscriptXssExceptions.description "Celadresoj konformaj al ĉi tiuj regulesprimoj NE protektatos kontraŭ XSS.">
+<!ENTITY noscriptMatchSample "Ekzempla Åablono:">
+<!ENTITY noscriptReset "ReÅargi">
+<!ENTITY noscriptReset.accesskey "s">
+<!ENTITY noscriptResetDef "DefaÅ­ltigi">
+<!ENTITY noscriptResetDef.accesskey "D">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Retiri la provizorajn permesojn">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ne montri lokokupilojn por objektoj el Nefidataj retejoj">
+<!ENTITY noscriptCollapseBlockedObjects "Maletendi blokitajn objektojn">
+<!ENTITY noscriptExceptions "Esceptoj…">
+<!ENTITY noscriptBlockedObjects "Blokitaj objektoj">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Bloki ĉiujn objektojn venantajn de retejoj markitaj kiel Nefidataj">
+<!ENTITY noscriptTempAllowPage "Dumtempe rajtigi tutan ĉi tiun paÄon">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "Rajtigi la tutan tiun ĉi paÄon">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Konservi la provizorajn permesojn por la paÄo">
+<!ENTITY noscriptTempToPerm.accesskey "M">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Konduto">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Malpermesi aktivan TTT-enhavon venantan ne tra sekura (HTTPS) konekto:">
+<!ENTITY noscriptHttps.never "Neniam">
+<!ENTITY noscriptHttps.proxy "Dum uzado de prokura servilo (rekomendita kun Tor)">
+<!ENTITY noscriptHttps.always "Ĉiam">
+<!ENTITY noscriptHttpsForced "Devigi la sekvantajn retejojn uzi sekurajn (HTTPS) konektojn:">
+<!ENTITY noscriptHttpsForcedExceptions "Neniam postuli sekurajn (HTTPS) konektojn por la sekvantaj retejoj:">
+<!ENTITY noscriptSecureCookies "Åœalti aÅ­tomatan plisekurigan traktadon de kuketoj">
+<!ENTITY noscriptSecureCookiesForced "Devigi ĉifradon de ĉiuj kuketoj difinitaj tra HTTPS de la jenaj retejoj:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignori nesekurajn kuketojn difinitajn tra HTTPS de la jenaj retejoj:">
+<!ENTITY noscriptClearClickTitle "ClearClick-a averto">
+<!ENTITY noscriptClearClickHeader "Ebla provo misklakigi per trompa ÅanÄo de aspekto!">
+<!ENTITY noscriptClearClickDescription "NoScript haltigis musan aÅ­ klavan agon kun parte kaÅita elemento. Alklaku la bildon sube por ÅanÄi inter montro de la kaÅita kaj la malkaÅita aspektoj.">
+<!ENTITY noscriptClearClickOpt "ClearClick-a protekto sur paÄoj…">
+<!ENTITY noscriptClearClickReport "Raporti">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Identigilo de la raporto:">
+<!ENTITY noscriptTrustedPagesAdj "fidataj">
+<!ENTITY noscriptUntrustedPagesAdj "nefidataj">
+<!ENTITY noscriptKeepLocked "Teni tiun eron Ålosita (admonata)">
+<!ENTITY noscriptEmbeddings "Enkonstruaĵoj">
+<!ENTITY noscriptPrev "AntaÅ­e">
+<!ENTITY noscriptNext "Sekve">
+<!ENTITY noscriptFrameOptErr.title "Ne videbla enkadre">
+<!ENTITY noscriptFrameOptErr.desc "Por protekti vian sekurecon, la eldonisto de tiu ĉi enhavo malpermesas vidigi Äin enkadre.">
+<!ENTITY noscriptFrameOptErr.link "Klaku ĉi tie por malfermi enhavon en nova fenestro">
+<!ENTITY noscriptBookmarkSync "Kopii NoScript-ajn agordojn en paÄosignon por facila sinkronigo">
+<!ENTITY noscriptShowReleaseNotes "Vidigi eldonajn notojn ĉe Äisdatigo">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Regularo:">
+<!ENTITY ABE.enabled.label "Åœalti ABE-on (obeigilon de interpaÄaraj limoj)">
+<!ENTITY ABE.siteEnabled.label "Rajtigi ttt-ejojn puÅi siajn regularojn">
+<!ENTITY ABE.edit.label "Redakti…">
+<!ENTITY ABE.edit.accesskey "R">
+<!ENTITY ABE.enable.label "Åœalti">
+<!ENTITY ABE.enable.accesskey "a">
+<!ENTITY ABE.disable.label "MalÅalti">
+<!ENTITY ABE.disable.accesskey "M">
+<!ENTITY ABE.refresh.label "ReÅargi">
+<!ENTITY ABE.refresh.accesskey "e">
+<!ENTITY noscriptUninstall "Malinstali">
+<!ENTITY noscriptRecentBlocked "FreÅe baritaj ttt-ejoj">
+<!ENTITY noscriptExternalFilters "Eksteraj filtriloj">
+<!ENTITY noscriptEF.enable "Åœalti eksterajn filtrilojn">
+<!ENTITY noscriptEF.add "Nova filtrilo…">
+<!ENTITY noscriptEF.executable "Programdosiero:">
+<!ENTITY noscriptEF.browse "Elekti…">
+<!ENTITY noscriptEF.contentType "MIME-tipo de filtrotaĵoj (specifu ekzakte aŭ per regulesprimo):">
+<!ENTITY noscriptEF.exceptions "Ne filtri objektojn de la jenaj retejoj:">
+<!ENTITY noscriptEF.remove "Forigi">
+<!ENTITY noscriptPreset "Protektonivelo">
+<!ENTITY noscriptPreset.off "MalÅaltita (ĉu serioze?!)">
+<!ENTITY noscriptPreset.low "Facila (Nigra listo + TTT-sekurigo)">
+<!ENTITY noscriptPreset.medium "Klasika (Blanka listo + TTT-sekurigo)">
+<!ENTITY noscriptPreset.high "Fortikaĵo (Maksimuma protekto)">
+<!ENTITY noscript.hoverUI "Aperigi la rajtigmenuon kiam la musmontrilo estas sur bildsimbolo de NoScript">
+<!ENTITY noscriptDonate "Donaci">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/eo/noscript/noscript.properties b/extensions/noscript/chrome/locale/eo/noscript/noscript.properties
new file mode 100644
index 0000000..bfc672a
--- /dev/null
+++ b/extensions/noscript/chrome/locale/eo/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=DefaÅ­lte rajtigi ĉiujn retejojn (danÄere)
+forbidGlobal=Defaŭlte malrajtigi ĉiujn retejojn (rekomendate)
+allowLocal=Rajtigi %S
+allowTemp=Dumtempe rajtigi %S
+forbidLocal=Malrajtigi %S
+allowed.glb=DanÄero! Ĉiuj retejoj estas defaÅ­lte rajtigataj!
+allowed.yes=Skriptoj aktuale permesitas
+allowed.prt=Skriptoj parte permesitas
+allowed.no=Skriptoj aktuale malpermesitas
+global.warning.title=Averto!
+global.warning.text=Skriptoj estos defaÅ­lte permesitaj (por ĉiuj ttt-ejoj).\nTio estas eble danÄera ago.\nĈu vi vere daÅ­rigas ?
+audio.samples=Sonaĵetoj
+confirm=Ĉu vi certigas ?
+alwaysAsk=Ĉiam peti konfirmon
+notifyHide=KaÅi post %S sekundoj
+trust=Fidi %S
+distrust=Marki %S kiel nefidatan
+untrustedOrigin=nefidata origino
+xss.notify.generic=NoScript filtris eblan inter-ttt-ejan skriptan (XSS) provon de %S. Teknikaj informoj estas enprotokolitaj en la konzolo.
+xss.notify.showConsole=Vidigi konzolon...
+xss.notify.showConsole.accessKey=K
+xss.reason.filterXGet=Purigis suspektan peton. Originala URL [%1$S] petis de [%2$S]. Purigita URL : [%3$S].
+xss.reason.filterXGetRef=Purigis suspektan petanton. URL [%1$S] petis de [%2$S]. Purigita petanto : [%3$S].
+xss.reason.filterXPost=Purigis suspektan alÅuton al [%1$S] de [%2$S]: transformis al nur-elÅuta GET peto.
+unsafeReload.warning=DANÄœERE reÅargas suspektan\n\n%1$S [%2$S]\n\nDE [%3$S]\n\nNoScript NE protektos tiun peton !\n
+metaRefresh.notify=NoScript baris 〈META〉-alidirekton ene de 〈NOSCRIPT〉-elemento: %S en %S sekundoj.
+metaRefresh.notify.follow=Sekvi alidirekton
+metaRefresh.notify.follow.accessKey=A
+notify.options=Opcioj
+notify.options.accessKey=O
+reset.title=Restarigi agordojn de NoScript
+reset.warning=ĈIUJ NoScript-aj agordoj kaj ttt-ejaj rajtoj tuj anstataÅ­iÄos per la defaÅ­ltaj.\nTio ne malfareblas.\nĈu vi daÅ­rigas?
+bookmarkSync.title=Agorda paÄosigno de NoScript
+bookmarkSync.message=Tiu ĉi paÄosigno estas NE por malfermi Äin, sed por sinkronigi Äin per servo kiel Weave aÅ­ la etendoprogramo XMarks.
+bookmarkSync.confirm=NoScript trovis agordan paÄosignon verÅajne konservitan en\n%S.\nĈu vi volas superskribi viajn lokajn NoScript-ajn agordojn per la enhavo de tiu paÄosigno ?
+ABE.notify=Peto %1$S filtritas de ABE: 〈%2$S〉 %3$S
+ABE.chooseEditor=Bonvolu elekti tekstredaktilon por ABE-a regularo
+ABE.syntaxError=Sintaksa eraro en regularo de ABE!
+allowFrom=Rajtigi ĉion de %S
+allowTempFrom=Dumtempe rajtigi ĉion de %S
+siteInfo.confirm=Vi estas petonta informojn pri la retejo «%1$S»\nper sendo de peto al %2$S.\nĈu vi volas fari tion?
+siteInfo.tooltip=Mez-alklaku aŭ shift+alklaku por ricevi informojn pri la retejo…
+ef.newName=Enigu nomon por la nova filtrilo:
+ef.activate=Filtrilo %S
+ef.options=%S opcioj...
+ef.locateExe=Elektu la plenumeblan dosieron por la filtrilo %S
+disable=Malebligi %S
+disable.accessKey=M
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+removal.title=Averto pri malpromociado de sekureco
+removal.message=Malebligante aÅ­ malinstalante NoScript, vi rezignas pri la TUTA protekto, kiun NoScript disponigas.\n\nSe vi nur estas tedita de la manipulado de skriptaj permesoj retejo post retejo, estas pli sekura ebleco.\n\nNoScript povas ĉesigi bloki skriptojn, escepte de tiuj, kiujn vi markas kiel nefidindajn, dum Äi ankoraÅ­ protektas vin per la plej progresintaj sekurecaj kontraÅ­rimedoj kontraÅ­ XSS, Clickjacking, CSRF kaj aliaj retminacoj.\n\nĈu vi vere volas forigi la TUTAN protekton per NoScript?\n
+removal.no=Ne, ĉesu nur bloki skriptojn
+removal.yes=Jes, forigu la TUTAN protekton
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/es-AR/noscript/about.properties b/extensions/noscript/chrome/locale/es-AR/noscript/about.properties
new file mode 100644
index 0000000..af5b6f7
--- /dev/null
+++ b/extensions/noscript/chrome/locale/es-AR/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Protección adicional para su Firefox: NoScript permite JavaScript, Java (y otros plugins) sólo para los dominios de confianza que usted elija (por ejemplo, el sitio web de su banco). Este enfoque de bloqueo preventivo basado en una lista blanca evita la explotación de vulnerabilidades de seguridad (conocidas e incluso desconocidas) sin pérdida de funcionalidad… Los expertos estarán de acuerdo: Firefox es realmente más seguro con NoScript :-)
+aboutTitle=Acerca de %S
+extensionContributors=Colaboradores:
+extensionContributors.tip=Personas a las que se debe agradecer por esta extensión
+extensionCreatorLabel=Autor:
+changelog=Registro de cambios
+changelog.tip=Mostrar el registro de cambios
+license=Licencia
+license.tip=Leer la licencia de usuario final
+logo.tip=Visitar la página principal de la extensión
+sponsor.tip=Visitar la página principal del patrocinador
+informaction.tip=Visitar la página principal de InformAction
+extensionHomepage.tip=Visitar la página principal de la extensión
+extensionCreator.tip=Visitar la página principal del autor
+version=Versión %S
diff --git a/extensions/noscript/chrome/locale/es-AR/noscript/noscript.dtd b/extensions/noscript/chrome/locale/es-AR/noscript/noscript.dtd
new file mode 100644
index 0000000..c077437
--- /dev/null
+++ b/extensions/noscript/chrome/locale/es-AR/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opciones…">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Opciones de NoScript">
+<!ENTITY noscriptAbout "Acerca de NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Puede especificar a cuáles sitios web le permitirá ejecutar scripts. Escriba la dirección o el dominio (por ejemplo, &quot;http://www.sitio.com&quot; o &quot;sitio.com&quot;) del sitio y luego haga clic en Permitir.">
+<!ENTITY noscriptWebAddress "Dirección del sitio web:">
+<!ENTITY noscriptAllow "Permitir">
+<!ENTITY noscriptAllow.accesskey "P">
+<!ENTITY noscriptForbid "Prohibir">
+<!ENTITY noscriptForbid.accesskey "h">
+<!ENTITY noscriptTrust "Marcar como Fiable">
+<!ENTITY noscriptTrust.accesskey "F">
+<!ENTITY noscriptUntrust "Marcar como No fiable">
+<!ENTITY noscriptUntrust.accesskey "N">
+<!ENTITY noscriptRemoveSelected "Quitar los sitios seleccionados">
+<!ENTITY noscriptGloballyEnabled "Scripts permitidos globalmente (peligroso)">
+<!ENTITY noscriptAutoReload "Recargar automáticamente las páginas afectadas cuando cambie los permisos">
+<!ENTITY noscriptGeneral "General">
+<!ENTITY noscriptAppearance "Apariencia">
+<!ENTITY noscriptShow "Mostrar…">
+<!ENTITY noscriptCtxMenu "Menú contextual">
+<!ENTITY noscriptStatusIcon "Icono en la barra de estado">
+<!ENTITY noscriptFullAddr "Direcciones completas (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Dominios completos (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Dominios de segundo nivel (noscript.net)">
+<!ENTITY noscriptTempCmd "Permitir temporalmente […]">
+<!ENTITY noscriptSound "Aviso acústico cuando los scripts son bloqueados">
+<!ENTITY noscriptImport "Importar">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exportar">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Mostrar mensaje referente a scripts bloqueados">
+<!ENTITY noscriptNotify.bottom "Colocar el mensaje en la parte inferior">
+<!ENTITY noscriptSound.choose "Elegir">
+<!ENTITY noscriptSound.choose.accesskey "E">
+<!ENTITY noscriptSound.play "Reproducir">
+<!ENTITY noscriptSound.play.accesskey "o">
+<!ENTITY noscriptSound.reset "Restablecer predeterminado">
+<!ENTITY noscriptSound.reset.accesskey "s">
+<!ENTITY noscriptAdvanced "Avanzado">
+<!ENTITY noscriptAdditionalPermissions "Permisos adicionales para sitios fiables">
+<!ENTITY noscriptAllowClipboard "Permitir copiar y pegar texto enriquecido desde portapapeles externo">
+<!ENTITY noscriptAdditionalRestrictions "Restricciones adicionales para sitios no fiables">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Aplicar estas restricciones también a los sitios fiables">
+<!ENTITY noscriptForbidJava "Prohibir Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Prohibir XSLT">
+<!ENTITY noscriptForbidSilverlight "Prohibir Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Prohibir &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Prohibir &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Prohibir @font-face">
+<!ENTITY noscriptForbidWebGL "Prohibir WebGL">
+<!ENTITY noscriptForbidMedia "Prohibir &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Prohibir Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Prohibir otros plugins">
+<!ENTITY noscriptReloadWarn "Estas opciones tendrán efecto en páginas nuevas o (manualmente) recargadas">
+<!ENTITY noscriptConfirmUnblock "Pedir confirmación antes de desbloquear temporalmente un objeto">
+<!ENTITY noscriptStatusLabel "Etiqueta en la barra de estado">
+<!ENTITY noscriptForbidBookmarklets "Prohibir marcadores JavaScript">
+<!ENTITY noscriptShowPlaceholder "Mostrar icono de objeto bloqueado">
+<!ENTITY noscriptTruncateTitle "Truncar títulos de documentos">
+<!ENTITY noscriptFixLinks "Intentar corregir enlaces JavaScript">
+<!ENTITY noscriptAllowBookmarks "Permitir todos los sitios de marcadores">
+<!ENTITY noscriptAllowViaBookmarks "Permitir la apertura de sitios a través de marcadores">
+<!ENTITY noscriptAllowPing "Permitir &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Permitir enlaces locales">
+<!ENTITY noscriptForbidPing "Prohibir &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Prohibir META redireccionamientos dentro de elementos &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "N">
+<!ENTITY noscriptWhitelist "Lista blanca">
+<!ENTITY noscriptPermissions "Permisos">
+<!ENTITY noscriptRefresh "Actualizar">
+<!ENTITY noscriptNotifications "Notificaciones">
+<!ENTITY noscriptToolbarToggle "Clic en botón NoScript de barra de navegación alterna permisos para actual máximo nivel del sitio">
+<!ENTITY noscriptTrusted "Fiable">
+<!ENTITY noscriptUntrusted "No fiable">
+<!ENTITY noscriptUnknown "Desconocida">
+<!ENTITY noscriptAdd "Agregar">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Cerrar">
+<!ENTITY noscriptSiteManager "Administrador de sitios">
+<!ENTITY noscriptSecurityManager "Administrador de seguridad">
+<!ENTITY noscriptPolicies "Políticas">
+<!ENTITY noscriptDefaultPolicies "Políticas predeterminadas">
+<!ENTITY noscriptSitePolicies "Políticas específicas por sitio">
+<!ENTITY noscriptNselNever "Ocultar los elementos &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Mostrar el elemento &lt;NOSCRIPT&gt; que sigue a un &lt;SCRIPT&gt; bloqueado">
+<!ENTITY noscriptAutoAllowTopLevel "Permitir temporalmente por defecto los sitios de máximo nivel">
+<!ENTITY noscriptDescription "Protección adicional para su Firefox: NoScript permite JavaScript, Java (y otros plugins) sólo para los dominios de confianza que usted elija (por ejemplo, el sitio web de su banco). Este enfoque de bloqueo preventivo basado en una lista blanca evita la explotación de vulnerabilidades de seguridad (conocidas e incluso desconocidas) sin pérdida de funcionalidad… Los expertos estarán de acuerdo: Firefox es realmente más seguro con NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Bloquear scanners basados en CSS">
+<!ENTITY noscriptOptFilterXGet "Depurar peticiones cross-site sospechosas">
+<!ENTITY noscriptOptFilterXPost "Convertir peticiones POST cross-site en peticiones GET sin datos">
+<!ENTITY noscriptShowConsole "Mostrar Consola…">
+<!ENTITY noscriptShowConsole.accesskey "M">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "Preguntas frecuentes sobre XSS…">
+<!ENTITY noscriptXssFaq.accesskey "P">
+<!ENTITY noscriptUnsafeReload "Recargar sin protección">
+<!ENTITY noscriptUnsafeReload.accesskey "c">
+<!ENTITY noscriptXssExceptions "Excepciones a la protección anti-XSS">
+<!ENTITY noscriptXssExceptions.description "Los destinos coincidentes con estas expresiones regulares NO estarán protegidos contra XSS.">
+<!ENTITY noscriptMatchSample "Ejemplo de patrones coincidentes:">
+<!ENTITY noscriptReset "Restablecer">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Restablecer a predeterminados">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revocar los permisos temporales">
+<!ENTITY noscriptRevokeTemp.accesskey "t">
+<!ENTITY noscriptNoUntrustedPlaceholder "No reservar lugar para objetos procedentes de sitios marcados como no fiables">
+<!ENTITY noscriptCollapseBlockedObjects "Contraer objetos bloqueados">
+<!ENTITY noscriptExceptions "Excepciones…">
+<!ENTITY noscriptBlockedObjects "Objetos bloqueados">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Bloquear todos los objetos procedentes de un sitio marcado como no fiable">
+<!ENTITY noscriptTempAllowPage "Permitir temporalmente toda esta página">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Admitir toda esta página">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Hacer permanentes los permisos de la página">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behavior">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image above to cycle beetween the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Embedded Objects">
+<!ENTITY noscriptPrev "Previuous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/es-AR/noscript/noscript.properties b/extensions/noscript/chrome/locale/es-AR/noscript/noscript.properties
new file mode 100644
index 0000000..fff06bf
--- /dev/null
+++ b/extensions/noscript/chrome/locale/es-AR/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Permitir scripts globalmente (peligroso)
+forbidGlobal=Prohibir scripts globalmente (recomendado)
+allowLocal=Permitir %S
+allowTemp=Permitir temporalmente %S
+forbidLocal=Prohibir %S
+allowed.glb=¡Peligro! Scripts permitidos globalmente
+allowed.yes=Scripts actualmente permitidos
+allowed.prt=Scripts parcialmente permitidos
+allowed.no=Scripts actualmente prohibidos
+global.warning.title=¡Advertencia!
+global.warning.text=Los scripts serán permitidos globalmente (para todos los sitios).\nEsta es una acción potencialmente peligrosa.\n¿Realmente desea continuar?
+audio.samples=Muestras de sonido
+confirm=¿Está seguro?
+alwaysAsk=Pedir confirmación siempre
+notifyHide=Ocultar después de %S segundos
+trust=Fiable %S
+distrust=Marcar %S como no fiable
+untrustedOrigin=un origen no fiable
+xss.notify.generic=NoScript ha filtrado un potencial intento de cross-site scripting (XSS) desde %S. Los detalles técnicos puede verlos en la Consola.
+xss.notify.showConsole=Mostrar Consola…
+xss.notify.showConsole.accessKey=M
+xss.reason.filterXGet=Depurada petición sospechosa. URL original: [%1$S] solicitada desde: [%2$S]. URL depurada: [%3$S].
+xss.reason.filterXGetRef=Depurada petición sospechosa de referencia. URL [%1$S] solicitada desde [%2$S]. Referencia depurada: [%3$S].
+xss.reason.filterXPost=Depurada carga sospechosa a [%1$S] desde [%2$S]: transformada en una petición GET de sólo descarga.
+unsafeReload.warning=Recargando DE MODO INSEGURO una sospechosa\n\n%1$S [%2$S]\n\n DESDE [%3$S]\n\n¡NoScript NO le protegerá de esta petición!\n
+metaRefresh.notify=NoScript bloqueó una <META> redirección dentro de un elemento <NOSCRIPT>: %S en %S segundos.
+metaRefresh.notify.follow=Seguir redirección
+metaRefresh.notify.follow.accessKey=S
+notify.options=Opciones
+notify.options.accessKey=O
+reset.title=Restablecer NoScript
+reset.warning=TODAS las preferencias y permisos de NoScript se restablecerán de inmediato a sus valores predeterminados.\nEsta acción no podrá deshacerse.\n¿Desea continuar?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark's content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/es-CL/noscript/about.properties b/extensions/noscript/chrome/locale/es-CL/noscript/about.properties
new file mode 100644
index 0000000..ff2f61f
--- /dev/null
+++ b/extensions/noscript/chrome/locale/es-CL/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality… Experts will agree: Firefox is really safer with NoScript :-)
+aboutTitle=Acerca de %S
+extensionContributors=Colaboradores:
+extensionContributors.tip=Gente a la que deberías agradecer por esta extensión
+extensionCreatorLabel=Autor:
+changelog=Changelog
+changelog.tip=Show changelog
+license=Licencia
+license.tip=Read end-user license
+logo.tip=Visit extension home page
+sponsor.tip=Visit sponsor home page
+informaction.tip=Visit InformAction home page
+extensionHomepage.tip=Visit extension home page
+extensionCreator.tip=Visit author home page
+version=Version %S
diff --git a/extensions/noscript/chrome/locale/es-CL/noscript/noscript.dtd b/extensions/noscript/chrome/locale/es-CL/noscript/noscript.dtd
new file mode 100644
index 0000000..1f81af0
--- /dev/null
+++ b/extensions/noscript/chrome/locale/es-CL/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Options…">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Opciones de NoScript">
+<!ENTITY noscriptAbout "About NoScript 5.1.8.5…">
+<!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. &quot;http://www.site.com&quot; or &quot;site.com&quot;) of the site you want to allow and then click Allow.">
+<!ENTITY noscriptWebAddress "Address of web site:">
+<!ENTITY noscriptAllow "Allow">
+<!ENTITY noscriptAllow.accesskey "l">
+<!ENTITY noscriptForbid "Forbid">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Mark as Trusted">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Mark as Untrusted">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Remove Selected Sites">
+<!ENTITY noscriptGloballyEnabled "Scripts Globally Allowed (dangerous)">
+<!ENTITY noscriptAutoReload "Automatically reload affected pages when permissions change">
+<!ENTITY noscriptGeneral "General">
+<!ENTITY noscriptAppearance "Appearance">
+<!ENTITY noscriptShow "Show…">
+<!ENTITY noscriptCtxMenu "Contextual menu">
+<!ENTITY noscriptStatusIcon "Status bar icon">
+<!ENTITY noscriptFullAddr "Full Addresses (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Full Domains (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Base 2nd level Domains (noscript.net)">
+<!ENTITY noscriptTempCmd "Temporarily allow […]">
+<!ENTITY noscriptSound "Audio feedback when scripts are blocked">
+<!ENTITY noscriptImport "Import">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Export">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Show message about blocked scripts">
+<!ENTITY noscriptNotify.bottom "Place message at the bottom">
+<!ENTITY noscriptSound.choose "Choose">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Play">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Reset default">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Advanced">
+<!ENTITY noscriptAdditionalPermissions "Additional permissions for trusted sites">
+<!ENTITY noscriptAllowClipboard "Allow rich text copy and paste from external clipboard">
+<!ENTITY noscriptAdditionalRestrictions "Additional restrictions for untrusted sites">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Apply these restrictions to trusted sites too">
+<!ENTITY noscriptForbidJava "Forbid Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Forbid XSLT">
+<!ENTITY noscriptForbidSilverlight "Forbid Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Forbid &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Forbid &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Forbid @font-face">
+<!ENTITY noscriptForbidWebGL "Forbid WebGL">
+<!ENTITY noscriptForbidMedia "Forbid &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Forbid Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Forbid other plugins">
+<!ENTITY noscriptReloadWarn "These options will take effect on new or (manually) reloaded pages">
+<!ENTITY noscriptConfirmUnblock "Ask for confirmation before temporarily unblocking an object">
+<!ENTITY noscriptStatusLabel "Status bar label">
+<!ENTITY noscriptForbidBookmarklets "Forbid bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Show placeholder icon">
+<!ENTITY noscriptTruncateTitle "Truncate document titles">
+<!ENTITY noscriptFixLinks "Attempt to fix JavaScript links">
+<!ENTITY noscriptAllowBookmarks "Allow sites opened through bookmarks">
+<!ENTITY noscriptAllowViaBookmarks "Allow sites opened through bookmarks">
+<!ENTITY noscriptAllowPing "Allow &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Allow local links">
+<!ENTITY noscriptForbidPing "Forbid &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Forbid META redirections inside &lt;NOSCRIPT&gt; elements">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptWhitelist "Whitelist">
+<!ENTITY noscriptPermissions "Permissions">
+<!ENTITY noscriptRefresh "Refresh">
+<!ENTITY noscriptNotifications "Notifications">
+<!ENTITY noscriptToolbarToggle "Left clicking on NoScript toolbar button toggles permissions for current top-level site">
+<!ENTITY noscriptTrusted "Trusted">
+<!ENTITY noscriptUntrusted "Untrusted">
+<!ENTITY noscriptUnknown "Unknown">
+<!ENTITY noscriptAdd "Add">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Close">
+<!ENTITY noscriptSiteManager "Site Manager">
+<!ENTITY noscriptSecurityManager "Security Manager">
+<!ENTITY noscriptPolicies "Policies">
+<!ENTITY noscriptDefaultPolicies "Default Policies">
+<!ENTITY noscriptSitePolicies "Site Specific Policies">
+<!ENTITY noscriptNselNever "Hide &lt;NOSCRIPT&gt; elements">
+<!ENTITY noscriptNselForce "Show the &lt;NOSCRIPT&gt; element which follows a blocked &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Temporarily allow top-level sites by default">
+<!ENTITY noscriptDescription "Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality… Experts will agree: Firefox is really safer with NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Block CSS-based scanners">
+<!ENTITY noscriptOptFilterXGet "Sanitize cross-site suspicious requests">
+<!ENTITY noscriptOptFilterXPost "Turn cross-site POST requests into data-less GET requests">
+<!ENTITY noscriptShowConsole "Show Console…">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ…">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Unsafe Reload">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Anti-XSS Protection Exceptions">
+<!ENTITY noscriptXssExceptions.description "Destinations matching these regular expressions will NOT be protected against XSS.">
+<!ENTITY noscriptMatchSample "Pattern matching sample:">
+<!ENTITY noscriptReset "Reset">
+<!ENTITY noscriptReset.accesskey "s">
+<!ENTITY noscriptResetDef "Reset to defaults">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revoke Temporary Permissions">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "No placeholder for objects coming from sites marked as untrusted">
+<!ENTITY noscriptCollapseBlockedObjects "Collapse blocked objects">
+<!ENTITY noscriptExceptions "Exceptions…">
+<!ENTITY noscriptBlockedObjects "Blocked Objects">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Block every object coming from a site marked as untrusted">
+<!ENTITY noscriptTempAllowPage "Temporarily allow all this page">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "Allow all this page">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Make page permissions permanent">
+<!ENTITY noscriptTempToPerm.accesskey "M">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behavior">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image below to cycle between the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Embedded Objects">
+<!ENTITY noscriptPrev "Previous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/es-CL/noscript/noscript.properties b/extensions/noscript/chrome/locale/es-CL/noscript/noscript.properties
new file mode 100644
index 0000000..35e928f
--- /dev/null
+++ b/extensions/noscript/chrome/locale/es-CL/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Allow Scripts Globally (dangerous)
+forbidGlobal=Forbid Scripts Globally (advised)
+allowLocal=Allow %S
+allowTemp=Temporarily allow %S
+forbidLocal=Forbid %S
+allowed.glb=Danger! Scripts Globally Allowed
+allowed.yes=Scripts Currently Allowed
+allowed.prt=Scripts Partially Allowed
+allowed.no=Scripts Currently Forbidden
+global.warning.title=Warning!
+global.warning.text=Scripts are going to be allowed globally (for every site).\nThis is a potentially dangerous action.\nDo you really want to proceed?
+audio.samples=Audio samples
+confirm=Are you sure?
+alwaysAsk=Always ask for confirmation
+notifyHide=Hide after %S seconds
+trust=Trust %S
+distrust=Mark %S as Untrusted
+untrustedOrigin=an untrusted origin
+xss.notify.generic=NoScript filtered a potential cross-site scripting (XSS) attempt from %S. Technical details have been logged to the Console.
+xss.notify.showConsole=Show Console…
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Sanitized suspicious request. Original URL [%1$S] requested from [%2$S]. Sanitized URL: [%3$S].
+xss.reason.filterXGetRef=Sanitized suspicious request referer. URL [%1$S] requested from [%2$S]. Sanitized Referrer: [%3$S].
+xss.reason.filterXPost=Sanitized suspicious upload to [%1$S] from [%2$S]: transformed into a download-only GET request.
+unsafeReload.warning=UNSAFELY reloading a suspicious\n\n%1$S [%2$S]\n\nFROM [%3$S]\n\nNoScript will NOT protect this request!\n
+metaRefresh.notify=NoScript blocked a <META> redirection inside a <NOSCRIPT> element: %S in %S seconds.
+metaRefresh.notify.follow=Follow Redirection
+metaRefresh.notify.follow.accessKey=F
+notify.options=Options
+notify.options.accessKey=O
+reset.title=NoScript Reset
+reset.warning=ALL the NoScript preferences and site permissions will be reset to their default values immediately.\nThis action cannot be reverted.\nDo you want to continue?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark\'s content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You\'re about to ask for information about the \"%1$S\" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/es-ES/noscript/about.properties b/extensions/noscript/chrome/locale/es-ES/noscript/about.properties
new file mode 100644
index 0000000..aa9dc0d
--- /dev/null
+++ b/extensions/noscript/chrome/locale/es-ES/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Protección extra para su Firefox: NoScript sólo permite JavaScript, Java y otros plugins en los sitios web de confianza que Ud. elija (como la web de su banco). Este planteamiento preventivo basado en una lista blanca evita que se puedan explotar vulnerabilidades (conocidas o incluso desconocidas) sin pérdida de funcionalidad… Los expertos lo confirmarán: Firefox es realmente más seguro con NoScript :-)
+aboutTitle=Acerca de %S
+extensionContributors=Colaboradores:
+extensionContributors.tip=Personas a las que debe de agradecer esta extensión
+extensionCreatorLabel=Autor:
+changelog=Historial de cambios
+changelog.tip=Mostrar historial de cambios
+license=Licencia
+license.tip=Leer licencia de usuario final
+logo.tip=Visitar página web de la extensión
+sponsor.tip=Visitar página web del patrocinador
+informaction.tip=Visitar página web de InformAction
+extensionHomepage.tip=Visitar página web de la extensión
+extensionCreator.tip=Visitar página web del autor
+version=Versión %S
diff --git a/extensions/noscript/chrome/locale/es-ES/noscript/noscript.dtd b/extensions/noscript/chrome/locale/es-ES/noscript/noscript.dtd
new file mode 100644
index 0000000..3b05bb5
--- /dev/null
+++ b/extensions/noscript/chrome/locale/es-ES/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opciones…">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Configuración de NoScript">
+<!ENTITY noscriptAbout "Acerca de NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Aquí puede especificar las páginas web a las que va a permitir ejecutar código JavaScript. Escriba la dirección de la web que quiera incluir (ej. &quot;http://www.paginaweb.com&quot; o &quot;paginaweb.com&quot;) y después pulse &quot;Permitir&quot;.">
+<!ENTITY noscriptWebAddress "Dirección de la página web:">
+<!ENTITY noscriptAllow "Permitir">
+<!ENTITY noscriptAllow.accesskey "P">
+<!ENTITY noscriptForbid "Prohibir">
+<!ENTITY noscriptForbid.accesskey "r">
+<!ENTITY noscriptTrust "Marcar como fiable">
+<!ENTITY noscriptTrust.accesskey "f">
+<!ENTITY noscriptUntrust "Marcar como no fiable">
+<!ENTITY noscriptUntrust.accesskey "n">
+<!ENTITY noscriptRemoveSelected "Eliminar sitio(s) web seleccionado(s)">
+<!ENTITY noscriptGloballyEnabled "Permitir JavaScript globalmente (peligroso)">
+<!ENTITY noscriptAutoReload "Recargar página automáticamente tras cambiar permisos">
+<!ENTITY noscriptGeneral "General">
+<!ENTITY noscriptAppearance "Presentación">
+<!ENTITY noscriptShow "Mostrar…">
+<!ENTITY noscriptCtxMenu "Menú contextual">
+<!ENTITY noscriptStatusIcon "Icono en la barra de estado">
+<!ENTITY noscriptFullAddr "Direcciones completas (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Dominios completos (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Dominios de segundo nivel (noscript.net)">
+<!ENTITY noscriptTempCmd "Permitir temporalmente […]">
+<!ENTITY noscriptSound "Aviso acústico al bloquear scripts">
+<!ENTITY noscriptImport "Importar">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exportar">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Mostrar alertas de scripts bloqueados">
+<!ENTITY noscriptNotify.bottom "Mostrar alertas en la parte inferior">
+<!ENTITY noscriptSound.choose "Examinar">
+<!ENTITY noscriptSound.choose.accesskey "x">
+<!ENTITY noscriptSound.play "Reproducir">
+<!ENTITY noscriptSound.play.accesskey "p">
+<!ENTITY noscriptSound.reset "Restaurar predeterminado">
+<!ENTITY noscriptSound.reset.accesskey "d">
+<!ENTITY noscriptAdvanced "Avanzado">
+<!ENTITY noscriptAdditionalPermissions "Permisos adicionales para sitios fiables">
+<!ENTITY noscriptAllowClipboard "Permitir copiar y pegar texto enriquecido desde otro programa">
+<!ENTITY noscriptAdditionalRestrictions "Restricciones adicionales para sitios no fiables">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Aplicar estas restricciones también a los sitios fiables">
+<!ENTITY noscriptForbidJava "Prohibir Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Prohibir XSLT">
+<!ENTITY noscriptForbidSilverlight "Prohibir Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Prohibir &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Prohibir &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Prohibir @font-face">
+<!ENTITY noscriptForbidWebGL "Prohibir WebGL">
+<!ENTITY noscriptForbidMedia "Prohibir &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Prohibir Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Prohibir otros plugins">
+<!ENTITY noscriptReloadWarn "Estas opciones tendrán efecto en páginas nuevas o tras recargar manualmente">
+<!ENTITY noscriptConfirmUnblock "Pedir confirmación antes de desbloquear temporalmente un objeto">
+<!ENTITY noscriptStatusLabel "Etiqueta informativa en la barra de estado">
+<!ENTITY noscriptForbidBookmarklets "Prohibir Bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Mostrar indicador de objeto bloqueado (placeholder)">
+<!ENTITY noscriptTruncateTitle "Truncar títulos de documentos">
+<!ENTITY noscriptFixLinks "Intentar corregir enlaces JavaScript">
+<!ENTITY noscriptAllowBookmarks "Permitir todos los sitios de marcadores">
+<!ENTITY noscriptAllowViaBookmarks "Permitir sitios abiertos desde marcadores">
+<!ENTITY noscriptAllowPing "Permitir &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Permitir enlaces locales">
+<!ENTITY noscriptForbidPing "Prohibir &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Prohibir META redireccionamientos dentro de elementos &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "h">
+<!ENTITY noscriptNotifyMeta "Mostrar mensaje sobre META redireccionamientos bloqueados">
+<!ENTITY noscriptNotifyMeta.accesskey "M">
+<!ENTITY noscriptWhitelist "Lista blanca">
+<!ENTITY noscriptPermissions "Permisos">
+<!ENTITY noscriptRefresh "Recargar">
+<!ENTITY noscriptNotifications "Notificaciones">
+<!ENTITY noscriptToolbarToggle "Con clic izquierdo en icono de la barra de herramientas se conmutan los permisos para el sitio web">
+<!ENTITY noscriptTrusted "Fiable">
+<!ENTITY noscriptUntrusted "No fiable">
+<!ENTITY noscriptUnknown "Desconocida">
+<!ENTITY noscriptAdd "Añadir">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Cerrar">
+<!ENTITY noscriptSiteManager "Administrador de sitios">
+<!ENTITY noscriptSecurityManager "Administrador de seguridad">
+<!ENTITY noscriptPolicies "Normas a aplicar">
+<!ENTITY noscriptDefaultPolicies "Normas predeterminadas">
+<!ENTITY noscriptSitePolicies "Normas específicas por sitio">
+<!ENTITY noscriptNselNever "Ocultar los elementos &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Mostrar el elemento &lt;NOSCRIPT&gt; que sigue a un &lt;SCRIPT&gt; bloqueado">
+<!ENTITY noscriptAutoAllowTopLevel "Permitir por defecto de forma temporal los dominios de máximo nivel">
+<!ENTITY noscriptDescription "Protección extra para su Firefox: NoScript sólo permite JavaScript, Java y otros plugins en los sitios web de confianza que Ud. elija (como la web de su banco). Este planteamiento preventivo basado en una lista blanca evita que se puedan explotar vulnerabilidades (conocidas o incluso desconocidas) sin pérdida de funcionalidad… Los expertos lo confirmarán: Firefox es realmente más seguro con NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Bloquear escáners basados en CSS">
+<!ENTITY noscriptOptFilterXGet "Depurar peticiones cross-site sospechosas">
+<!ENTITY noscriptOptFilterXPost "Convertir peticiones POST cross-site en peticiones GET sin datos">
+<!ENTITY noscriptShowConsole "Mostrar Consola de error…">
+<!ENTITY noscriptShowConsole.accesskey "C">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "FAQ sobre XSS…">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Recarga en modo inseguro">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Excepciones a la protección anti XSS">
+<!ENTITY noscriptXssExceptions.description "Los destinos que coincidan con estas expresiones regulares NO estarán protegidos frente a XSS">
+<!ENTITY noscriptMatchSample "Ejemplo de coincidencia con las expresiones:">
+<!ENTITY noscriptReset "Restaurar">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Restaurar predeterminados">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "50em">
+<!ENTITY noscriptRevokeTemp "Revocar permisos temporales">
+<!ENTITY noscriptRevokeTemp.accesskey "t">
+<!ENTITY noscriptNoUntrustedPlaceholder "No mostrar indicadores de objetos bloqueados provenientes de sitios marcados como no fiables">
+<!ENTITY noscriptCollapseBlockedObjects "Colapsar objetos bloqueados">
+<!ENTITY noscriptExceptions "Excepciones…">
+<!ENTITY noscriptBlockedObjects "Objetos bloqueados">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Bloquear todos los objetos provenientes de sitios no fiables">
+<!ENTITY noscriptTempAllowPage "Permitir temporalmente toda la página">
+<!ENTITY noscriptTempAllowPage.accesskey "g">
+<!ENTITY noscriptAllowPage "Permitir toda esta página">
+<!ENTITY noscriptAllowPage.accesskey "P">
+<!ENTITY noscriptTempToPerm "Hacer permanentes los permisos de la página">
+<!ENTITY noscriptTempToPerm.accesskey "H">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "FAQ HTTPS">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Comportamiento">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Prohibir contenidos web activos salvo que provengan de una conexión segura (HTTPS)">
+<!ENTITY noscriptHttps.never "Nunca">
+<!ENTITY noscriptHttps.proxy "Al usar un proxy (recomendado con Tor)">
+<!ENTITY noscriptHttps.always "Siempre">
+<!ENTITY noscriptHttpsForced "Obligar a usar conexiones seguras (HTTPS) a los siguientes sitios:">
+<!ENTITY noscriptHttpsForcedExceptions "No obligar nunca a usar conexiones seguras (HTTPS) a los siguientes sitios:">
+<!ENTITY noscriptSecureCookies "Activar la gestión automática segura de cookies">
+<!ENTITY noscriptSecureCookiesForced "Obligar a cifrar todas las cookies recibidas por HTTPS en los siguientes sitios:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignorar cookies no seguras recibidas por HTTPS de los siguientes sitios:">
+<!ENTITY noscriptClearClickTitle "Aviso de ClearClick">
+<!ENTITY noscriptClearClickHeader "¡Posible intento de clickjacking / camuflaje de UI!">
+<!ENTITY noscriptClearClickDescription "NoScript interceptó una interacción de ratón o teclado con un elemento parcialmente oculto. Pulse en la imagen superior para comparar la versión oculta y la ya revelada.">
+<!ENTITY noscriptClearClickOpt "Usar la protección ClearClick en páginas…">
+<!ENTITY noscriptClearClickReport "Informe">
+<!ENTITY noscriptClearClickReport.accesskey "I">
+<!ENTITY noscriptClearClickReportId "ID del informe:">
+<!ENTITY noscriptTrustedPagesAdj "fiables">
+<!ENTITY noscriptUntrustedPagesAdj "no fiables">
+<!ENTITY noscriptKeepLocked "Mantener bloqueado ese elemento (recomendado)">
+<!ENTITY noscriptEmbeddings "Objetos incrustados">
+<!ENTITY noscriptPrev "Anterior">
+<!ENTITY noscriptNext "Siguiente">
+<!ENTITY noscriptFrameOptErr.title "Este contenido no puede mostrarse en un frame (marco)">
+<!ENTITY noscriptFrameOptErr.desc "Para proteger su seguridad, el proveedor de ese contenido no permite que se muestre en un frame.">
+<!ENTITY noscriptFrameOptErr.link "Pulse aquí para abrirlo en una nueva ventana">
+<!ENTITY noscriptBookmarkSync "Guardar una copia de la configuración de NoScript para facilitar la sincronización">
+<!ENTITY noscriptShowReleaseNotes "Mostrar las notas de versión cuando se actualice">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Reglas:">
+<!ENTITY ABE.enabled.label "Habilitar ABE (Guardián de límites de aplicación)">
+<!ENTITY ABE.siteEnabled.label "Permitir que los sitios apliquen sus propias reglas">
+<!ENTITY ABE.edit.label "Editar…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Habilitar">
+<!ENTITY ABE.enable.accesskey "H">
+<!ENTITY ABE.disable.label "Deshabilitar">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Recargar">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Desinstalar">
+<!ENTITY noscriptRecentBlocked "Últimos sitios bloqueados">
+<!ENTITY noscriptExternalFilters "Filtros externos">
+<!ENTITY noscriptEF.enable "Activar filtros externos">
+<!ENTITY noscriptEF.add "Nuevo filtro…">
+<!ENTITY noscriptEF.executable "Archivo ejecutable:">
+<!ENTITY noscriptEF.browse "Examinar…">
+<!ENTITY noscriptEF.contentType "Tipo de contenido (MIME) a filtrar (coincidencia exacta o expresión regular):">
+<!ENTITY noscriptEF.exceptions "No filtrar objetos provenientes de estos sitios:">
+<!ENTITY noscriptEF.remove "Eliminar">
+<!ENTITY noscriptPreset "Nivel de seguridad">
+<!ENTITY noscriptPreset.off "Desactivado (¿lo dice en serio?)">
+<!ENTITY noscriptPreset.low "Relajado (Lista negra + Seguridad web)">
+<!ENTITY noscriptPreset.medium "Clásico (Lista blanca + Seguridad web)">
+<!ENTITY noscriptPreset.high "Fuerte (Bloqueo completo)">
+<!ENTITY noscript.hoverUI "Abrir menú de permisos cuando el ratón se sitúa sobre el icono de NosScript">
+<!ENTITY noscriptDonate "Donar">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/es-ES/noscript/noscript.properties b/extensions/noscript/chrome/locale/es-ES/noscript/noscript.properties
new file mode 100644
index 0000000..d962c17
--- /dev/null
+++ b/extensions/noscript/chrome/locale/es-ES/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Permitir JavaScript globalmente (peligroso)
+forbidGlobal=Bloquear JavaScript globalmente (recomendado)
+allowLocal=Permitir %S
+allowTemp=Permitir temporalmente %S
+forbidLocal=Bloquear %S
+allowed.glb=¡Atención! JavaScript permitidos globalmente
+allowed.yes=JavaScripts actualmente permitidos
+allowed.prt=JavaScripts parcialmente permitidos
+allowed.no=JavaScripts actualmente prohibidos
+global.warning.title=¡Atención!
+global.warning.text=Se va a activar JavaScript globalmente (para todas las páginas web).\n Hacerlo es potencialmente peligroso.\n ¿Está seguro de querer continuar?
+audio.samples=Muestras de sonido
+confirm=¿Está seguro?
+alwaysAsk=Pedir confirmación siempre
+notifyHide=Ocultar automáticamente tras %S segundos
+trust=Considerar fiable %S
+distrust=Marcar %S como no fiable
+untrustedOrigin=un origen no fiable
+xss.notify.generic=NoScript ha filtrado un posible intento de cross-site scripting (XSS) desde %S. Los detalles técnicos pueden visualizarse en la Consola de error.
+xss.notify.showConsole=Mostrar Consola de error…
+xss.notify.showConsole.accessKey=C
+xss.reason.filterXGet=Depurada una petición sospechosa. URL original: [%1$S] solicitada desde: [%2$S]. URL depurada: [%3$S].
+xss.reason.filterXGetRef=Depurado el referer de una petición sospechosa. URL [%1$S] solicitada desde [%2$S]. Referrer depurado: [%3$S].
+xss.reason.filterXPost=Depurada una carga sospechosa a [%1$S] desde [%2$S]: convertida en una petición GET de sólo descarga.
+unsafeReload.warning=Recargando EN MODO NO SEGURO una petición sospechosa\n\n%1$S [%2$S]\n\n DESDE [%3$S]\n\n¡NoScript NO le protegerá ante esta petición!\n
+metaRefresh.notify=NoScript bloqueó un <META>; redireccionamiento dentro de un elemento <NOSCRIPT>: %S en %S segundos.
+metaRefresh.notify.follow=Seguir redireccionamiento
+metaRefresh.notify.follow.accessKey=S
+notify.options=Opciones
+notify.options.accessKey=O
+reset.title=Restaurar NoScript
+reset.warning=TODAS las preferencias y permisos de NoScript se restaurarán de inmediato a sus valores predeterminados.\nEsta acción no podrá deshacerse.\n¿Desea continuar?
+bookmarkSync.title=Marcador de configuración de NoScript
+bookmarkSync.message=Este marcador NO se usa para acceder a una página, sino para que se sincronice utilizando un servicio como el que ofrecen las extensiones Weave o XMarks.
+bookmarkSync.confirm=NoScript ha encontrado un marcador de configuración aparentemente guardado en\n%S.\n¿Está seguro de querer reemplazar su configuración local de NoScript con el contenido de ese marcador?
+ABE.notify=La petición %1$S ha sido filtrada por ABE: <%2$S> %3$S
+ABE.chooseEditor=Por favor elija un editor de texto para las reglas de ABE
+ABE.syntaxError=Error de sintaxis en las reglas de ABE
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Permitir todo de %S
+allowTempFrom=Permitir temporalmente todo de %S
+siteInfo.confirm=Va a solicitar información sobre el sitio "%1$S"\nal enviar una petición a %2$S.\n¿Quiere continuar?
+siteInfo.tooltip=Haga clic intermedio o MAYÚS+clic para información del sitio…
+ef.activate=Filtro %S
+ef.options=Opciones de %S…
+ef.newName=Introduzca el nombre del nuevo filtro:
+ef.locateExe=Seleccionar el archivo ejecutable para el filtro %S
+disable=Desactivar %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/et-EE/noscript/about.properties b/extensions/noscript/chrome/locale/et-EE/noscript/about.properties
new file mode 100644
index 0000000..439a71e
--- /dev/null
+++ b/extensions/noscript/chrome/locale/et-EE/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Lisakaitse Firefoxile: NoScript lubab JavaSkripti, Javat (ja teisi pluginaid) ainult usaldusväärsetest domeenidest sinu valikul (nt kodupanga veebilehel). Antud nn valgel nimekirjal põhinev blokeerimine hoiab ära tuntud ja isegi tundmatute turvaaukude kuritahtlikku ärakasutamist ilma funktsionaalsust kaotamata… Eksperdid nõustuvad, et Firefox on turvalisem koos NoScriptiga :-)
+aboutTitle=Täpsemalt lisast %S
+extensionContributors=Kaasaaitajad:
+extensionContributors.tip=Keda peaksid tänama antud laienduse eest
+extensionCreatorLabel=Autor:
+changelog=Muutuste logi
+changelog.tip=Näita muutuste logi
+license=Litsents
+license.tip=Loe lõppkasutaja litsentsi
+logo.tip=Külasta laienduse kodulehte
+sponsor.tip=Külasta sponsori kodulehte
+informaction.tip=Külasta InformActioni kodulehte
+extensionHomepage.tip=Külasta laienduse kodulehte
+extensionCreator.tip=Külasta autori kodulehte
+version=Versioon %S
diff --git a/extensions/noscript/chrome/locale/et-EE/noscript/noscript.dtd b/extensions/noscript/chrome/locale/et-EE/noscript/noscript.dtd
new file mode 100644
index 0000000..8ec66c1
--- /dev/null
+++ b/extensions/noscript/chrome/locale/et-EE/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Sätted…">
+<!ENTITY noscriptOptions.accesskey "S">
+<!ENTITY noscriptOptionsLong "NoScripti sätted">
+<!ENTITY noscriptAbout "Täpsemalt lisast NoScript 5.1.8.5…">
+<!ENTITY noscriptPermissionsText "Sa saad määrata, millistel veebilehtedel lubatakse skripte käivitada. Kirjuta veebilehe aadress või domeeni, mida soovid lubada (nt &quot;http://www.site.com&quot; või &quot;site.com&quot;) ja klõpsa Luba nuppu">
+<!ENTITY noscriptWebAddress "Veebilehe aadress:">
+<!ENTITY noscriptAllow "Luba">
+<!ENTITY noscriptAllow.accesskey "L">
+<!ENTITY noscriptForbid "Keela">
+<!ENTITY noscriptForbid.accesskey "K">
+<!ENTITY noscriptTrust "Märgi usaldusväärseks">
+<!ENTITY noscriptTrust.accesskey "u">
+<!ENTITY noscriptUntrust "Märgi ebausaldusväärseks">
+<!ENTITY noscriptUntrust.accesskey "m">
+<!ENTITY noscriptRemoveSelected "Kustuta valitud veebilehed">
+<!ENTITY noscriptGloballyEnabled "Skriptid on lubatud (ohtlik)">
+<!ENTITY noscriptAutoReload "Õiguste muutumisel laetakse mõjustatud lehed automaatselt uuesti">
+<!ENTITY noscriptGeneral "Ãœldine">
+<!ENTITY noscriptAppearance "Välimus">
+<!ENTITY noscriptShow "Näita…">
+<!ENTITY noscriptCtxMenu "Kontekstimenüü">
+<!ENTITY noscriptStatusIcon "Ikoon olekuribal">
+<!ENTITY noscriptFullAddr "Täisaadressid (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Täisdomeenid (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Teise taseme domeenid (noscript.net)">
+<!ENTITY noscriptTempCmd "Luba ajutiselt […]">
+<!ENTITY noscriptSound "Teata heliga skriptide blokeerimisest">
+<!ENTITY noscriptImport "Impordi">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Ekspordi">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Näita teadet blokeeritud skriptide kohta">
+<!ENTITY noscriptNotify.bottom "Aseta sõnum allserva">
+<!ENTITY noscriptSound.choose "Vali">
+<!ENTITY noscriptSound.choose.accesskey "V">
+<!ENTITY noscriptSound.play "Mängi">
+<!ENTITY noscriptSound.play.accesskey "M">
+<!ENTITY noscriptSound.reset "Lähtesta">
+<!ENTITY noscriptSound.reset.accesskey "h">
+<!ENTITY noscriptAdvanced "Muud">
+<!ENTITY noscriptAdditionalPermissions "Lisaõigused usaldusväärsetele veebilehtedele">
+<!ENTITY noscriptAllowClipboard "Luba vormindatud teksti kopeerimist ja asetamist välisest lõikepuhvrist">
+<!ENTITY noscriptAdditionalRestrictions "Lisapiirangud ebausaldusväärsetele veebilehtedele">
+<!ENTITY noscriptPlugins "Pluginad">
+<!ENTITY noscriptContentBlocker "Kehtesta antud piirangud ka usaldusväärsete veebilehtede jaoks">
+<!ENTITY noscriptForbidJava "Keela Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Keela XSLT">
+<!ENTITY noscriptForbidSilverlight "Keela Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Keela &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Keela &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Keela @font-face">
+<!ENTITY noscriptForbidWebGL "Keela WebGL">
+<!ENTITY noscriptForbidMedia "Keela &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Keela Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Keela teised pluginad">
+<!ENTITY noscriptReloadWarn "Need valikud jõustuvad uutel või (käsitsi) uuesti laetud lehtedel">
+<!ENTITY noscriptConfirmUnblock "Küsi kinnitust enne objekti ajutist blokeerimist">
+<!ENTITY noscriptStatusLabel "Pealdis olekuribal">
+<!ENTITY noscriptForbidBookmarklets "Keela funktsionaaljärjehoidjad">
+<!ENTITY noscriptShowPlaceholder "Näita kohatäitja ikooni">
+<!ENTITY noscriptTruncateTitle "Lühenda dokumendi päiseid">
+<!ENTITY noscriptFixLinks "Ãœrita parandada JavaScripti linke">
+<!ENTITY noscriptAllowBookmarks "Luba veebilehed, mis on avatud järjehoidjate kaudu">
+<!ENTITY noscriptAllowViaBookmarks "Luba veebilehed, mis on avatud järjehoidjate kaudu">
+<!ENTITY noscriptAllowPing "Luba &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Luba kohalikke linke">
+<!ENTITY noscriptForbidPing "Keela &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Keela META ümbersuunamised &lt;NOSCRIPT&gt; elementide sees">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "m">
+<!ENTITY noscriptNotifyMeta "Teata META ümbersuunamiste blokeerimistest">
+<!ENTITY noscriptNotifyMeta.accesskey "T">
+<!ENTITY noscriptWhitelist "Valge nimekiri">
+<!ENTITY noscriptPermissions "Õigused">
+<!ENTITY noscriptRefresh "Värskenda">
+<!ENTITY noscriptNotifications "Märguanded">
+<!ENTITY noscriptToolbarToggle "Vasak hiireklõps NoScript tööriistaribal lülitab ümber praeguse tipptaseme veebilehe õigused">
+<!ENTITY noscriptTrusted "Usaldusväärsed">
+<!ENTITY noscriptUntrusted "Ebausaldusväärsed">
+<!ENTITY noscriptUnknown "Teadmata">
+<!ENTITY noscriptAdd "Lisa">
+<!ENTITY noscriptAdd.accesskey "L">
+<!ENTITY noscriptClose "Sulge">
+<!ENTITY noscriptSiteManager "Veebilehtede haldur">
+<!ENTITY noscriptSecurityManager "Turvalisuse haldur">
+<!ENTITY noscriptPolicies "Reeglid">
+<!ENTITY noscriptDefaultPolicies "Vaikereeglid">
+<!ENTITY noscriptSitePolicies "Veebilehe-spetsiifilised reeglid">
+<!ENTITY noscriptNselNever "Peida &lt;NOSCRIPT&gt; elemendid">
+<!ENTITY noscriptNselForce "Näita &lt;NOSCRIPT&gt; elementi, mis järgneb blokeeritud &lt;SCRIPT&gt; elemendile">
+<!ENTITY noscriptAutoAllowTopLevel "Luba ajutiselt vaikimisi tipptaseme veebilehed">
+<!ENTITY noscriptDescription "Lisakaitse Firefoxile: NoScript lubab JavaSkripti, Javat (ja teisi pluginaid) ainult usaldusväärsetest domeenidest sinu valikul (nt kodupanga veebilehel). Antud nn valgel nimekirjal põhinev blokeerimine hoiab ära tuntud ja isegi tundmatute turvaaukude kuritahtlikku ärakasutamist ilma funktsionaalsust kaotamata… Eksperdid nõustuvad, et Firefox on turvalisem koos NoScriptiga :-)">
+<!ENTITY noscriptOptBlockCssScanners "Blokeeri CSS-põhinevad skannerid">
+<!ENTITY noscriptOptFilterXGet "Puhasta kahtlased päringud teistelt veebilehtedelt">
+<!ENTITY noscriptOptFilterXPost "Muuda POST-päringud teistelt veebilehtedelt andmevabadeks GET-päringuteks">
+<!ENTITY noscriptShowConsole "Näita konsooli…">
+<!ENTITY noscriptShowConsole.accesskey "k">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "Murdskriptimise KKK">
+<!ENTITY noscriptXssFaq.accesskey "K">
+<!ENTITY noscriptUnsafeReload "Mitteturvaline uuestilaadimine">
+<!ENTITY noscriptUnsafeReload.accesskey "M">
+<!ENTITY noscriptXssExceptions "Erandid murdskriptimise vastases kaitses">
+<!ENTITY noscriptXssExceptions.description "Sihtkohti, mis sobivad järgnevate regulaaravaldistega, ei kaitsta murdskriptimise suhtes">
+<!ENTITY noscriptMatchSample "Mallvõrdluse näide">
+<!ENTITY noscriptReset "Lähtesta">
+<!ENTITY noscriptReset.accesskey "L">
+<!ENTITY noscriptResetDef "Taasta algsätted">
+<!ENTITY noscriptResetDef.accesskey "a">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Tühista ajutised õigused">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "Kohatäitjaid ei näidata objektidel, mis tulevad ebausaldusväärsetelt veebilehtedelt">
+<!ENTITY noscriptCollapseBlockedObjects "Blokeeritud objektid ahendatakse">
+<!ENTITY noscriptExceptions "Erandid…">
+<!ENTITY noscriptBlockedObjects "Blokeeritud objektid">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Blokeeri kõik ebausaldusväärsetelt veebilehtedelt pärinevad objektid">
+<!ENTITY noscriptTempAllowPage "Luba ajutiselt kõik sellel lehel">
+<!ENTITY noscriptTempAllowPage.accesskey "a">
+<!ENTITY noscriptAllowPage "Luba kõik sellel lehel">
+<!ENTITY noscriptAllowPage.accesskey "K">
+<!ENTITY noscriptTempToPerm "Sea lehe õigused püsivaks">
+<!ENTITY noscriptTempToPerm.accesskey "p">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS KKK">
+<!ENTITY noscriptHttpsFaq.accesskey "K">
+<!ENTITY noscriptHttps.behavior "Käitumine">
+<!ENTITY noscriptHttps.cookies "Küpsised">
+<!ENTITY noscriptHttps.description "Aktiivse veebilehe sisu keelatakse kui see ei tule turvalise (HTTPS) ühenduse kaudu:">
+<!ENTITY noscriptHttps.never "Mitte kunagi">
+<!ENTITY noscriptHttps.proxy "Puhverserverit kasutades (soovitatav torrenti puhul)">
+<!ENTITY noscriptHttps.always "Alati">
+<!ENTITY noscriptHttpsForced "Sunni järgnevaid veebilehti kasutama turvalist (HTTPS) ühendust:">
+<!ENTITY noscriptHttpsForcedExceptions "Turvalist (HTTPS) ühendust ei sunnita kunagi järgnevate veebilehtede korral:">
+<!ENTITY noscriptSecureCookies "Automaatne turvaküpsiste haldamine lubatud">
+<!ENTITY noscriptSecureCookiesForced "Kõik järgnevate veebilehtede poolt HTTPS kaudu loodud küpsised krüpteeritakse">
+<!ENTITY noscriptSecureCookiesExceptions "Kõiki järgnevate veebilehtede poolt HTTPS kaudu loodud mitteturvalisi küpsiseid eiratakse">
+<!ENTITY noscriptClearClickTitle "ClearClick hoiatus">
+<!ENTITY noscriptClearClickHeader "Võimalik kliki röövimise/kasutajaliidese muutmise katse!">
+<!ENTITY noscriptClearClickDescription "NoScript pidas kinni hiire või klaviatuuri interaktsiooni osaliselt varjatud elemendiga. Hiireklõps alloleval pildil lülitab ümber tõkestatud ja puhastatud versiooni vahel">
+<!ENTITY noscriptClearClickOpt "ClearClick kaitse lehtedel...">
+<!ENTITY noscriptClearClickReport "Aruanne">
+<!ENTITY noscriptClearClickReport.accesskey "A">
+<!ENTITY noscriptClearClickReportId "Aruande ID:">
+<!ENTITY noscriptTrustedPagesAdj "usaldatavad">
+<!ENTITY noscriptUntrustedPagesAdj "mitteusaldatavad">
+<!ENTITY noscriptKeepLocked "Lukusta antud element (soovitatav)">
+<!ENTITY noscriptEmbeddings "Manusobjektid">
+<!ENTITY noscriptPrev "Eelmine">
+<!ENTITY noscriptNext "Järgmine">
+<!ENTITY noscriptFrameOptErr.title "Antud sisu ei saa esitada raami sees">
+<!ENTITY noscriptFrameOptErr.desc "Sinu turvalisuse huvides ei luba antud sisu avaldaja seda esitada raami sees">
+<!ENTITY noscriptFrameOptErr.link "Kliki siia, et avada antud sisu uues aknas">
+<!ENTITY noscriptBookmarkSync "Varunda NoScript'i sätted järjehoidjana, et hõlbustada sünkroniseerimist">
+<!ENTITY noscriptShowReleaseNotes "Näita uuenduste väljalaske märkmeid">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Reeglid:">
+<!ENTITY ABE.enabled.label "Luba ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Luba veebilehtedel kehtestada enda reegleid">
+<!ENTITY ABE.edit.label "Muuda...">
+<!ENTITY ABE.edit.accesskey "M">
+<!ENTITY ABE.enable.label "Luba">
+<!ENTITY ABE.enable.accesskey "L">
+<!ENTITY ABE.disable.label "Keela">
+<!ENTITY ABE.disable.accesskey "K">
+<!ENTITY ABE.refresh.label "Värskenda">
+<!ENTITY ABE.refresh.accesskey "V">
+<!ENTITY noscriptUninstall "Eemalda">
+<!ENTITY noscriptRecentBlocked "Viimati blokeeritud veebilehed">
+<!ENTITY noscriptExternalFilters "Välised filtrid">
+<!ENTITY noscriptEF.enable "Luba välised filtrid">
+<!ENTITY noscriptEF.add "Uus filter…">
+<!ENTITY noscriptEF.executable "Käsufail:">
+<!ENTITY noscriptEF.browse "Sirvi…">
+<!ENTITY noscriptEF.contentType "Filtreeritav sisu tüüp (MIME) (täpne nimi või regulaaravaldis):">
+<!ENTITY noscriptEF.exceptions "Nendelt saitidelt saabuvaid objekte ei filtreerita:">
+<!ENTITY noscriptEF.remove "Eemalda">
+<!ENTITY noscriptPreset "Turvalisuse tase">
+<!ENTITY noscriptPreset.off "Väljas (Kas oled kindel?)">
+<!ENTITY noscriptPreset.low "Pingevaba (Must nimekiri + Veebi turvalisus)">
+<!ENTITY noscriptPreset.medium "Klassikaline (Valge nimekiri + Veebi turvalisus)">
+<!ENTITY noscriptPreset.high "Kindlus (Täiskaitse)">
+<!ENTITY noscript.hoverUI "Hiire viimine NoScript ikooni peale avab õiguste menüü">
+<!ENTITY noscriptDonate "Anneta">
+<!ENTITY noscriptDonate.accesskey "n">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/et-EE/noscript/noscript.properties b/extensions/noscript/chrome/locale/et-EE/noscript/noscript.properties
new file mode 100644
index 0000000..577b495
--- /dev/null
+++ b/extensions/noscript/chrome/locale/et-EE/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Skriptid lubatud (ohtlik)
+forbidGlobal=Skriptid keelatud (soovitatav)
+allowLocal=Luba %S
+allowTemp=Luba ajutiselt %S
+forbidLocal=Keela %S
+allowed.glb=Tähelepanu! Skriptid on lubatud
+allowed.yes=Skriptid praegu lubatud
+allowed.prt=Skriptid osaliselt lubatud
+allowed.no=Skriptid praegu keelatud
+global.warning.title=Hoiatus!
+global.warning.text=Skriptid lubatakse kõikjal (kõikide veebilehtede puhul).\nSee võib olla ohtlik.\nKas soovid tõesti seda teha?
+audio.samples=Helisämplid
+confirm=Oled kindel?
+alwaysAsk=Küsi alati kinnitust
+notifyHide=Peida peale %S sekundit
+trust=Usalda %S
+distrust=Märgista %S ebausaldusväärseks
+untrustedOrigin=ebausaldusväärne lähtekoht
+xss.notify.generic=NoScript filtreeris võimaliku murdskriptimise (XSS) katse asukohast %S. Tehnilised üksikasjad on näha konsoolil.
+xss.notify.showConsole=Näita konsooli…
+xss.notify.showConsole.accessKey=N
+xss.reason.filterXGet=Puhastati kahtlane päring. Algset aadressi [%1$S] küsiti kohast [%2$S]. Puhastatud aadress: [%3$S].
+xss.reason.filterXGetRef=Puhastati kahtlane päringu suunang. Aadressi [%1$S] küsiti kohast [%2$S]. Puhastatud suunang: [%3$S].
+xss.reason.filterXPost=Puhastati kahtlane üleslaadimine aadressile [%1$S] kohast [%2$S]: muudeti ainult allalaetavaks GET-päringuks.
+unsafeReload.warning=MITTETURVALINE uuestilaadmine\n\n%1$S [%2$S]\n\nAsukohast [%3$S]\n\nNoScript EI KAITSE seda päringut!\n
+metaRefresh.notify=NoScript blokeeris <META> ümbersuunamise <NOSCRIPT> elemendi sees: %S peale %S sekundit.
+metaRefresh.notify.follow=Järgi ümbersuunamist
+metaRefresh.notify.follow.accessKey=J
+notify.options=Sätted
+notify.options.accessKey=S
+reset.title=Lähtesta NoScript
+reset.warning=KÕIK NoScripti eelistused ja saitide õigused lähtestatakse kohe vaikeväärtustele.\nAntud tegevust ei saa tagasi võtta.\nKas soovid jätkata?
+bookmarkSync.title=NoScript sätete järjehoidja
+bookmarkSync.message=See järjehoidja ei ole mõeldud avamiseks vaid sünkroniseerimiseks, kasutades Weave või XMarks laiendust.
+bookmarkSync.confirm=NoScript leidis sätete järjehoidja\n%S.\nKas soovid NoScript kohalikud sätted üle kirjutada antud järjehoidja sisuga?
+ABE.notify=Päring %1$S filtreeriti ABE poolt: <%2$S> %3$S
+ABE.chooseEditor=Vali ABE reeglite jaoks tekstiredaktor
+ABE.syntaxError=Süntaksi viga ABE reeglites.
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Luba kõik veebilehel %S
+allowTempFrom=Luba ajutiselt kõik veebilehel %S
+siteInfo.confirm=Oled küsimas informatsiooni "%1$S" saidi kohta,\n esitades päringu %2$S.\nKas soovid jätkata?
+siteInfo.tooltip=Saidi infot näeb hiire keskmist klahvi vajutades või vajutades shift+paremklõps...
+ef.activate=Filtreeri %S
+ef.options=%S sätted...
+ef.newName=Uue filtri nimi:
+ef.locateExe=Vali käsufail %S filtri jaoks
+disable=Keela %S
+disable.accessKey=K
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/eu/noscript/about.properties b/extensions/noscript/chrome/locale/eu/noscript/about.properties
new file mode 100644
index 0000000..d92cbb6
--- /dev/null
+++ b/extensions/noscript/chrome/locale/eu/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Babes gehigarria zure firefoxentzat: NoScript-ek JavaScript (eta beste pluginak= onartzen ditu bakarrik zure aukerako konfiantzako guneetan (adib zure bankuko webgunean). Zerrenda-zurian oinarritutako lehentasunezko blokeoak segurtasun zuloen (ezagun eta ezezagunen) probetxuzko esplotazioa saihesten du. Adituak ados daude: Firefox seguruagoa da NoScript erabiliaz :-)
+aboutTitle=%S-ri buruz
+extensionContributors=Laguntzaileak:
+extensionContributors.tip=Hedapen honegatik eskerrak emateko pertsonak
+extensionCreatorLabel=Egilea:
+changelog=Aldaketa-erregistroa
+changelog.tip=Ikusi aldaketa-erregistroa
+license=Lizentzia
+license.tip=Irakurri erabiltzaile lizentzia
+logo.tip=Joan hedapenaren etxe orrialdera
+sponsor.tip=Joan babeslearen etxe orrialdera
+informaction.tip=Joan InformAction etxe orrialdera
+extensionHomepage.tip=Joan hedapenaren etxe orrialdera
+extensionCreator.tip=Joan garatzailearen etxe orrialdera
+version=%S bertsioa
diff --git a/extensions/noscript/chrome/locale/eu/noscript/noscript.dtd b/extensions/noscript/chrome/locale/eu/noscript/noscript.dtd
new file mode 100644
index 0000000..937e161
--- /dev/null
+++ b/extensions/noscript/chrome/locale/eu/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Aukerak:">
+<!ENTITY noscriptOptions.accesskey "A">
+<!ENTITY noscriptOptionsLong "NoScript aukerak">
+<!ENTITY noscriptAbout "NoScript 5.1.8.5-eri buruz:">
+<!ENTITY noscriptPermissionsText "Zein webgunek script-ak exekuta ditzakeen zehaztu dezakezu. Idatzi script-ak erabiltzea onartzea nahi duzun domeinuaren izena (adib. &quot;http://www.gunea.org&quot; or &quot;gunea.org&quot;) eta Onartu sakatu.">
+<!ENTITY noscriptWebAddress "Webgunearen helbidea:">
+<!ENTITY noscriptAllow "Onartu">
+<!ENTITY noscriptAllow.accesskey "O">
+<!ENTITY noscriptForbid "Debekatu">
+<!ENTITY noscriptForbid.accesskey "D">
+<!ENTITY noscriptTrust "Markatu konfiantzazkoa">
+<!ENTITY noscriptTrust.accesskey "k">
+<!ENTITY noscriptUntrust "Markatu ez-konfiantzazkoa">
+<!ENTITY noscriptUntrust.accesskey "E">
+<!ENTITY noscriptRemoveSelected "Kendu hautatutako guneak">
+<!ENTITY noscriptGloballyEnabled "Script-ak orokorrean onarturik (arriskutsua)">
+<!ENTITY noscriptAutoReload "Automatikoki birkargatu dagokien orriak baimenak aldatzean">
+<!ENTITY noscriptGeneral "Orokorra">
+<!ENTITY noscriptAppearance "Itxura">
+<!ENTITY noscriptShow "Ikusi:">
+<!ENTITY noscriptCtxMenu "Kontestu menua">
+<!ENTITY noscriptStatusIcon "Egoera barra ikonoa">
+<!ENTITY noscriptFullAddr "Helbide osoa (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Domeinu osoa (http://noscript.net)">
+<!ENTITY noscriptBaseDom "Oinarrizko 2. mailako domeinuak (noscript.net)">
+<!ENTITY noscriptTempCmd "Aldirako baterako onartu:">
+<!ENTITY noscriptSound "Audio abisua script-ak blokeatzean">
+<!ENTITY noscriptImport "Inporatu">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Esportatu">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Ikusi blokeatutako script-ei buruzko mezua">
+<!ENTITY noscriptNotify.bottom "Kokatu mezua behean">
+<!ENTITY noscriptSound.choose "Hautatu">
+<!ENTITY noscriptSound.choose.accesskey "H">
+<!ENTITY noscriptSound.play "Erreproduzitu">
+<!ENTITY noscriptSound.play.accesskey "r">
+<!ENTITY noscriptSound.reset "Berrezarri lehenespena">
+<!ENTITY noscriptSound.reset.accesskey "B">
+<!ENTITY noscriptAdvanced "Aurreratua">
+<!ENTITY noscriptAdditionalPermissions "Baimen gehigarriak konfiantzazko guneentzat">
+<!ENTITY noscriptAllowClipboard "Onartu kanpo arbelatik testu aberats kopiatu eta itsastea">
+<!ENTITY noscriptAdditionalRestrictions "Murrizte gehigarriak ez-konfiantzazko guneentzat">
+<!ENTITY noscriptPlugins "Plugin-ak">
+<!ENTITY noscriptContentBlocker "Ezarri murrizte hauek konfiantzazko guneei ere">
+<!ENTITY noscriptForbidJava "Debekatu Java:">
+<!ENTITY noscriptForbidXSLT "Debekatu XSLT">
+<!ENTITY noscriptForbidSilverlight "DEbekatu Microsoft Silverlight">
+<!ENTITY noscriptForbidIFrames "Debekatu &lt;markoak&gt;">
+<!ENTITY noscriptForbidFrames "Debeaktu &lt;markoa&gt;">
+<!ENTITY noscriptForbidFlash "Debekatu Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Debekatu beste pluginak">
+<!ENTITY noscriptForbidWebGL "Debekatu WebGL">
+<!ENTITY noscriptReloadWarn "Aukera hauek (eskuz) birkargatutako orrialde eta berrietan eragingo dute.">
+<!ENTITY noscriptConfirmUnblock "Eskatu berrespena aldi baterako objektu bat desblokeatzean">
+<!ENTITY noscriptStatusLabel "Egoera-barra etiketa">
+<!ENTITY noscriptForbidBookmarklets "Debekatu laster-markatzaileak">
+<!ENTITY noscriptShowPlaceholder "Ikusi leku-marka ikonoa">
+<!ENTITY noscriptTruncateTitle "Moztu dokumentu tituluak">
+<!ENTITY noscriptFixLinks "Saiatu JavaScript loturak konpontzen">
+<!ENTITY noscriptAllowBookmarks "Onartu laster-marka bidez irekitako guneak">
+<!ENTITY noscriptAllowViaBookmarks "Onartu laster-marka bidez irekitako guneak">
+<!ENTITY noscriptAllowPing "Onartu &lt;A PING�&gt;">
+<!ENTITY noscriptAllowLocalLinks "Onartu lotura lokalak">
+<!ENTITY noscriptForbidPing "Debekatu &lt;A PING�&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Debekatu METa berbidaraketak &lt;NOSCRIPT&gt; elementuen barnean">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptWhitelist "Zerrenda-zuria">
+<!ENTITY noscriptPermissions "BAimenak">
+<!ENTITY noscriptRefresh "Freskatu">
+<!ENTITY noscriptNotifications "Berri-emateak">
+<!ENTITY noscriptToolbarToggle "NoScript tresna-barra ezkerraz klikatzean uneko maila-altuneko gune baimenak aldatuko ditu">
+<!ENTITY noscriptTrusted "Konfiantzazkoa">
+<!ENTITY noscriptUntrusted "Ez-konfiantzazkoa">
+<!ENTITY noscriptUnknown "Ezezaguna">
+<!ENTITY noscriptAdd "Gehitu">
+<!ENTITY noscriptAdd.accesskey "G">
+<!ENTITY noscriptClose "Itxi">
+<!ENTITY noscriptSiteManager "Gune kudeatzailea">
+<!ENTITY noscriptSecurityManager "Segurtasun kudeatzailea">
+<!ENTITY noscriptPolicies "Politikak">
+<!ENTITY noscriptDefaultPolicies "Lehenetsitako politikak">
+<!ENTITY noscriptSitePolicies "Gune zehatzetako politikak">
+<!ENTITY noscriptNselNever "Ezkutatu &lt;NOSCRIPT&gt; elementuak">
+<!ENTITY noscriptNselForce "Ikusi blokeaturiko &lt;SCRIPT&gt;-a jarraitzen duen &lt;NOSCRIPT&gt; elementua">
+<!ENTITY noscriptAutoAllowTopLevel "Aldi baterako onartu maila-altueneko guneak lehenespenez">
+<!ENTITY noscriptDescription "Babes gehigarria zure firefoxentzat: NoScript-ek JavaScript (eta beste pluginak= onartzen ditu bakarrik zure aukerako konfiantzako guneetan (adib zure bankuko webgunean). Zerrenda-zurian oinarritutako lehentasunezko blokeoak segurtasun zuloen (ezagun eta ezezagunen) probetxuzko esplotazioa saihesten du funtzionalitaterik galdu gabe. Adituak ados daude: Firefox seguruagoa da NoScript erabiliaz :-)">
+<!ENTITY noscriptOptBlockCssScanners "Bloekatu CSS-oinarridun eskanerrak">
+<!ENTITY noscriptOptFilterXGet "Garbitu zeharkako-gune susmagarrik eskaerak">
+<!ENTITY noscriptOptFilterXPost "Bihurtu zeharkako-gune POST eskaerak data-gabeko GET eskaerak">
+<!ENTITY noscriptShowConsole "Ikusi kontsola:">
+<!ENTITY noscriptShowConsole.accesskey "I">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ�">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Segurtasun-gabeko birkargatzea">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "XSS-kontrako babeste salbuespenak">
+<!ENTITY noscriptXssExceptions.description "Espresio erregular hauek betetzen dituzten helburuak ez dira XSS aurka babestuko.">
+<!ENTITY noscriptMatchSample "Parekatze patroi sinplea:">
+<!ENTITY noscriptReset "Garbitu">
+<!ENTITY noscriptReset.accesskey "G">
+<!ENTITY noscriptResetDef "Lehenetsietara berrezarri">
+<!ENTITY noscriptResetDef.accesskey "l">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Kendu aldi baterako baimenak">
+<!ENTITY noscriptRevokeTemp.accesskey "K">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ez onartu ez-konfiantzako bezala markaturiko guneen objektuen kokalekua">
+<!ENTITY noscriptCollapseBlockedObjects "Bildu blokeaturiko objektuak">
+<!ENTITY noscriptExceptions "Salbuespenak:">
+<!ENTITY noscriptBlockedObjects "Blokeaturiko objektuak">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Blokeatu ez-konfiantzako bezala markatutako guneen objektu guztiak">
+<!ENTITY noscriptTempAllowPage "Aldi baterako onartu orrialde guzti hau">
+<!ENTITY noscriptTempAllowPage.accesskey "A">
+<!ENTITY noscriptAllowPage "Onartu orri hau">
+<!ENTITY noscriptAllowPage.accesskey "O">
+<!ENTITY noscriptTempToPerm "Egin orrialde baimenak iraunkorrak">
+<!ENTITY noscriptTempToPerm.accesskey "E">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ�">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Portaera">
+<!ENTITY noscriptHttps.cookies "Cookieak">
+<!ENTITY noscriptHttps.description "Debekatu web eduki aktiboak ez badira konexio seguru (HTTPS) baten bidez:">
+<!ENTITY noscriptHttps.never "Inoiz">
+<!ENTITY noscriptHttps.proxy "Proxy bat erabiltzean (Tor-ekin gomendatua)">
+<!ENTITY noscriptHttps.always "Beti">
+<!ENTITY noscriptHttpsForced "Behartu hurrengo guneak konexio seguruak (HTTPS) erabiltzea:">
+<!ENTITY noscriptHttpsForcedExceptions "Inoiz ez behartu konexio seguruak (HTTPS) hurrengo guneetan:">
+<!ENTITY noscriptSecureCookies "Gaitu cookie kudeaketa seguru automatikoa">
+<!ENTITY noscriptSecureCookiesForced "Behartu hurrengo guneek cookie guztiak HTTPS bidez ezartzea:">
+<!ENTITY noscriptSecureCookiesExceptions "Baztertu HTTPS bidezko segurtasun gabeko cookieak gune hauetan:">
+<!ENTITY noscriptClearClickTitle "ClearClick abisua">
+<!ENTITY noscriptClearClickHeader "Auekrako Clickjacking-a / UI berridazketa saiakera!">
+<!ENTITY noscriptClearClickDescription "NoScript-ek erdi-ezkutatutako elementu batekin sagu edo teklatu interakzioa gelditu du. Beheko irudian klikatu blokeaturik bertsio eta garbiaren arteko txandakatzerako.">
+<!ENTITY noscriptClearClickOpt "ClearClick babesa orrietan:">
+<!ENTITY noscriptClearClickReport "Txostena">
+<!ENTITY noscriptClearClickReport.accesskey "T">
+<!ENTITY noscriptClearClickReportId "Txosten IDa:">
+<!ENTITY noscriptTrustedPagesAdj "konfiantzazkoa">
+<!ENTITY noscriptUntrustedPagesAdj "ez-konfiantzazkoa">
+<!ENTITY noscriptKeepLocked "Mentendu elementu hau blokeaturik (gomendatua)">
+<!ENTITY noscriptEmbeddings "Txertatutako objektuak">
+<!ENTITY noscriptPrev "Aurrekoa">
+<!ENTITY noscriptNext "Hurrengoa">
+<!ENTITY noscriptFrameOptErr.title "Eduki hau ezin da marko batean bistarazi">
+<!ENTITY noscriptFrameOptErr.desc "Zure segurtasuna babesteko edukiaren argitaratzaileak ez du onartzen marko batean bistaratzea.">
+<!ENTITY noscriptFrameOptErr.link "Hemen klik egin eduki hau leiho berri batean irekitzeko.">
+<!ENTITY noscriptBookmarkSync "NoScript konfigurazioaren babes-kopia laster-marka batean egin errazago sinkronizatzeko.">
+<!ENTITY noscriptShowReleaseNotes "Bistarazi bertsio oharrak eguneraketetan">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Arau-jokoak:">
+<!ENTITY ABE.enabled.label "Gaitu ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Onartu guneek beren arau-jokoak bidaltzea">
+<!ENTITY ABE.edit.label "Editatu...">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Gaitu">
+<!ENTITY ABE.enable.accesskey "G">
+<!ENTITY ABE.disable.label "Desgaitu">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Berritu">
+<!ENTITY ABE.refresh.accesskey "B">
+<!ENTITY noscriptUninstall "Desinstalatu">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptForbidFonts "Forbid @font-face">
+<!ENTITY noscriptForbidMedia "Forbid &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/eu/noscript/noscript.properties b/extensions/noscript/chrome/locale/eu/noscript/noscript.properties
new file mode 100644
index 0000000..6132314
--- /dev/null
+++ b/extensions/noscript/chrome/locale/eu/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Onartu Script-ak orokorrean (arriskutsua)
+forbidGlobal=Debekatu Script-ak orokorrean (jakinarazten)
+allowLocal=Onartu %S
+allowTemp=Albi baterako onartu %S
+forbidLocal=Debekatu %S
+allowed.glb=Kontuz! Script-ak orokorki onartuak
+allowed.yes=Onartutako Scriptak
+allowed.prt=Partzialki onartutako Script-ak
+allowed.no=Debekatutako Script-ak
+global.warning.title=Kontuz!
+global.warning.text=Script-ak orokorki onartuko dira (gune guztientzat).\nHau potentzialki arriskutsua da.\nZiur zaude aurrera jarraitu nahi duzula?
+audio.samples=Audio adibideak
+confirm=Ziur zaude?
+alwaysAsk=Beti eskatu berrespena
+notifyHide=Ezkutatu %S segundo ondoren
+trust=%S-en konfiantza izan
+distrust=Markatu %S ez-konfiantzazko gisa
+untrustedOrigin=ez-konfiantzazko jatorria
+xss.notify.generic=NoScript-ek zeharka-gune script (XSS) potentzial bat gelditu du. Xehetasun teknikoak kontsolan erregistratu dira.
+xss.notify.showConsole=Ikusi kontsola:
+xss.notify.showConsole.accessKey=I
+xss.reason.filterXGet=Garbitu eskaera susmagarria. Jaottirzko URLa (%1$S) (%2$S)-tik eskatua. Gabitu URLa:(%3$S).
+xss.reason.filterXGetRef=Garbitu eskaera erreferentzia susmagarria. Jaottirzko URLa (%1$S) (%2$S)-tik eskatua. Gabitutako erreferentzia:(%3$S).
+xss.reason.filterXPost=Garbituta (%2$W)-tik egindako igoera susmagarria (%1$S): deskarga soileko GET eskaera bihurtua.
+unsafeReload.warning=UNSAFELY reloading a suspiciousnn%1$S [%2$S]\n\nFROM [%3$S]\n\nNoScript will NOT protect this request!n
+metaRefresh.notify=NoScript blocked a <META> redirection inside a <NOSCRIPT> element: %S in %S seconds.
+metaRefresh.notify.follow=Jarraitu berbideraketa
+metaRefresh.notify.follow.accessKey=J
+notify.options=Aukerak
+notify.options.accessKey=A
+reset.title=Berrabiarazi NoSCript
+reset.warning=ALL the NoScript preferences and site permissions will be reset to their default values immediately.\nThis action cannot be reverted.\nDo you want to continue?
+bookmarkSync.title=NoScript konfigurazio laster-marka
+bookmarkSync.message=Laster-marka hau ez da irekitzeko pentsatua, Xmarks edo Weave hedapenak erabiliaz sinkronizatzeko baizik.
+bookmarkSync.confirm=NoScript-ek dirudienez hemen gordetako laster-marka bat topatu du:\n%S\nBenetan zure NoSCript konfigurazio lokala laster-marka honetakoarekin gainidatzi nahi duzula?
+ABE.notify=%1$S eskaera ABE-k iragazi du: <%2$S> %3$S
+ABE.chooseEditor=Mesedez hautatu ABE arau-jokoentzat testu editore bat
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/fa-IR/noscript/about.properties b/extensions/noscript/chrome/locale/fa-IR/noscript/about.properties
new file mode 100644
index 0000000..a51437d
--- /dev/null
+++ b/extensions/noscript/chrome/locale/fa-IR/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=محاÙظت از ÙایرÙاکس شما:این برنامه از اجرا شدن اسکریپت ها در سایت های مختل٠جلوگیری Ù…ÛŒ کند.البته شما Ù…ÛŒ توانید به اسکریپت های سایت های مورد اعتماد خود اجازه Ùعالیت بدهید.
+aboutTitle=درباره %S
+extensionContributors=همکاران
+extensionContributors.tip=کسانی Ú©Ù‡ برای این اÙزونه زحمت کشیده اند
+extensionCreatorLabel=نویسنده :
+changelog=تغییرات برنامه
+changelog.tip=نمایش تغییرات ایجاد شده در هر نسخه
+license=مجوز
+license.tip=مجوز استÙاده کاربر از برنامه
+logo.tip=بازدید از سایت برنامه
+sponsor.tip=بازدید از سایت اسپانسر
+informaction.tip=بازدید از سایت InformAction
+extensionHomepage.tip=بازدید از سایت برنامه
+extensionCreator.tip=بازدید از سایت نویسنده
+version=نسخه %S
diff --git a/extensions/noscript/chrome/locale/fa-IR/noscript/noscript.dtd b/extensions/noscript/chrome/locale/fa-IR/noscript/noscript.dtd
new file mode 100644
index 0000000..6065730
--- /dev/null
+++ b/extensions/noscript/chrome/locale/fa-IR/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "تنظیمات...">
+<!ENTITY noscriptOptions.accesskey "ت">
+<!ENTITY noscriptOptionsLong "تنظیمات NoScript">
+<!ENTITY noscriptAbout "درباره NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "شما می توانید سایت هایی را که اجازه اجرای اسکریپت دارند را مشخص کنید.آدرس سایت یا نام دامنه را وارد کنید.(به عنوان مثال &quot;http://www.site.com&quot; یا &quot;site.com&quot;)">
+<!ENTITY noscriptWebAddress "آدرس وب سایت :">
+<!ENTITY noscriptAllow "اجازه دادن">
+<!ENTITY noscriptAllow.accesskey "ا">
+<!ENTITY noscriptForbid "ممنوع">
+<!ENTITY noscriptForbid.accesskey "Ù…">
+<!ENTITY noscriptTrust "علامت گدازی به عنوان تایید شده">
+<!ENTITY noscriptTrust.accesskey "ع">
+<!ENTITY noscriptUntrust "علامت گدازی به عنوان مشکوک">
+<!ENTITY noscriptUntrust.accesskey "Ù„">
+<!ENTITY noscriptRemoveSelected "پاک کردن سایت های انتخاب شده">
+<!ENTITY noscriptGloballyEnabled "تمام اسکریپت ها مجوز دارند (خطرناک)">
+<!ENTITY noscriptAutoReload "بارگذاری مجدد به صورت خودکار هنگام تغییر مجوزها">
+<!ENTITY noscriptGeneral "عمومی">
+<!ENTITY noscriptAppearance "تنظیمات ظاهری">
+<!ENTITY noscriptShow "نمایش...">
+<!ENTITY noscriptCtxMenu "نمایش در منوی کلیک راست">
+<!ENTITY noscriptStatusIcon "آیکون برنامه در نوار وضعیت">
+<!ENTITY noscriptFullAddr "آدرس کامل (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "نام کامل دامنه (http://www.noscript.net)">
+<!ENTITY noscriptBaseDom "سطح دوم نام دامنه ها (noscript.net)">
+<!ENTITY noscriptTempCmd "دادن مجوز موقت به [...]">
+<!ENTITY noscriptSound "پخش موزیک هنگام ممنوع شدن اسکریپت ها">
+<!ENTITY noscriptImport "ایمپورت">
+<!ENTITY noscriptImport.accesskey "ی">
+<!ENTITY noscriptExport "اکسپورت">
+<!ENTITY noscriptExport.accesskey "Ú©">
+<!ENTITY noscriptNotify "نمایش پیام هنگام متوق٠شدن اسکریپت ها">
+<!ENTITY noscriptNotify.bottom "نمایش پیام در پایین صÙحه">
+<!ENTITY noscriptSound.choose "انتخاب">
+<!ENTITY noscriptSound.choose.accesskey "Ù†">
+<!ENTITY noscriptSound.play "پخش">
+<!ENTITY noscriptSound.play.accesskey "Ù¾">
+<!ENTITY noscriptSound.reset "بازگردانی تنظیمات اولیه">
+<!ENTITY noscriptSound.reset.accesskey "ب">
+<!ENTITY noscriptAdvanced "پیشرÙته">
+<!ENTITY noscriptAdditionalPermissions "مجوزهای اضاÙÛŒ برای سایت های مورد اطمینان">
+<!ENTITY noscriptAllowClipboard "دادن مجوز برای کپی کردن و چسباندن متن سطح بالا">
+<!ENTITY noscriptAdditionalRestrictions "محدودیت بیشتر برای سایت های غیر مطمئن">
+<!ENTITY noscriptPlugins "اÙزودنی ها">
+<!ENTITY noscriptContentBlocker "اعمال این محدودیت ها روی سایت های مورد اطمینان">
+<!ENTITY noscriptForbidJava "Java ممنوع کردن">
+<!ENTITY noscriptForbidXSLT "Forbid XSLT">
+<!ENTITY noscriptForbidSilverlight "ممنوع کردن Microsoft® Silverlight">
+<!ENTITY noscriptForbidIFrames "ممنوع کردن &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "ممنوع کردن &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "ممنوع کردن @font-face">
+<!ENTITY noscriptForbidWebGL "ممنوع کردن WebGL">
+<!ENTITY noscriptForbidMedia "ممنوع کردن &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "ممنوع کردن Adobe Flash">
+<!ENTITY noscriptForbidPlugins "ممنوع کردن سایر پلاگین ها">
+<!ENTITY noscriptReloadWarn "این تنظیمات روی پنجره های جدید اعمال خواهند شد.">
+<!ENTITY noscriptConfirmUnblock "پرسیدن سوال قبل مجوز دادن به اسکریپت های یک سایت">
+<!ENTITY noscriptStatusLabel "برچسب نوار وضعیت">
+<!ENTITY noscriptForbidBookmarklets "ممنوع کردن سایت هایی که از نشانه گذاری ها باز می شوند.">
+<!ENTITY noscriptShowPlaceholder "نمایش آیکون">
+<!ENTITY noscriptTruncateTitle "کوتاه کردن عنوان پرونده">
+<!ENTITY noscriptFixLinks "اجازه دادن به لینک های جاوا اسکریپت">
+<!ENTITY noscriptAllowBookmarks "دادن مجوز به سایت هایی که از نشانه گذاری ها باز می شوند.">
+<!ENTITY noscriptAllowViaBookmarks "دادن مجوز به سایت هایی که از نشانه گذاری ها باز می شوند.">
+<!ENTITY noscriptAllowPing "اجازه دادن به &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "اجازه دادن به لینک های محلی">
+<!ENTITY noscriptForbidPing "ممنوع کردن &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "ممنوع کردن تÙییر مسیرهای META در عناصر &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "ر">
+<!ENTITY noscriptWhitelist "لیست سÙید">
+<!ENTITY noscriptPermissions "مجوزها">
+<!ENTITY noscriptRefresh "بارگذاری مجدد">
+<!ENTITY noscriptNotifications "هشدارها">
+<!ENTITY noscriptToolbarToggle "کلیک Ú†Ù¾ روی کلید نوار ابزار برنامه مجوز های سایت Ùعلی را باز Ù…ÛŒ کند.">
+<!ENTITY noscriptTrusted "مورد تایید">
+<!ENTITY noscriptUntrusted "مشکوک">
+<!ENTITY noscriptUnknown "ناشناس">
+<!ENTITY noscriptAdd "اÙزودن">
+<!ENTITY noscriptAdd.accesskey "ز">
+<!ENTITY noscriptClose "بستن">
+<!ENTITY noscriptSiteManager "مدیریت سایت">
+<!ENTITY noscriptSecurityManager "مدیریت امنیت">
+<!ENTITY noscriptPolicies "راهنماها">
+<!ENTITY noscriptDefaultPolicies "راهنماهای پیشÙرض">
+<!ENTITY noscriptSitePolicies "راهنمای مخصوص سایت">
+<!ENTITY noscriptNselNever "مخÙÛŒ کردن عناصر &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "نمایش عناصر &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "اجازه دادن به سایت های رده بالا به صورت موقت Ùˆ پیشÙرض">
+<!ENTITY noscriptDescription "Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality... Experts will agree: Firefox is really safer with NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "سد کردن اسکنرهای بر پایه CSS">
+<!ENTITY noscriptOptFilterXGet "Sanitize cross-site suspicious requests">
+<!ENTITY noscriptOptFilterXPost "Turn cross-site POST requests into data-less GET requests">
+<!ENTITY noscriptShowConsole "نمایش کنسول...">
+<!ENTITY noscriptShowConsole.accesskey "g">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS سوالات">
+<!ENTITY noscriptXssFaq.accesskey "X">
+<!ENTITY noscriptUnsafeReload "بازآوری ناامن">
+<!ENTITY noscriptUnsafeReload.accesskey "ب">
+<!ENTITY noscriptXssExceptions "Anti-XSS Protection Exceptions">
+<!ENTITY noscriptXssExceptions.description "Destinations matching these regular expressions will NOT be protected against XSS">
+<!ENTITY noscriptMatchSample "مثال تطابق الگو :">
+<!ENTITY noscriptReset "ریست">
+<!ENTITY noscriptReset.accesskey "ت">
+<!ENTITY noscriptResetDef "بازگردانی به تنظیمات اولیه">
+<!ENTITY noscriptResetDef.accesskey "د">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revoke Temporary Permissions">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "No placeholder for objects coming from sites marked as untrusted">
+<!ENTITY noscriptCollapseBlockedObjects "Collapse blocked objects">
+<!ENTITY noscriptExceptions "Exceptions...">
+<!ENTITY noscriptBlockedObjects "Blocked Objects">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Block every object coming from a site marked as untrusted">
+<!ENTITY noscriptTempAllowPage "Temporarily allow all this page">
+<!ENTITY noscriptTempAllowPage.accesskey "p">
+<!ENTITY noscriptAllowPage "Allow all this page">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Make page permissions permanent">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behavior">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image above to cycle beetween the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Embedded Objects">
+<!ENTITY noscriptPrev "Previuous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/fa-IR/noscript/noscript.properties b/extensions/noscript/chrome/locale/fa-IR/noscript/noscript.properties
new file mode 100644
index 0000000..3df184d
--- /dev/null
+++ b/extensions/noscript/chrome/locale/fa-IR/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=دادن مجوز به تمام اسکریپت‌ها (توصیه نمی‌شود)
+forbidGlobal=جلوگیری از Ùعالیت همه اسکریپت‌ها
+allowLocal=اجازه دادن به %S
+allowTemp=دادن مجوز موقت به %S
+forbidLocal=ممنوع کردن %S
+allowed.glb=خطر!به تمام اسکریپت‌ها مجوز Ùعالیت داده شده
+allowed.yes=هم اکنون اسکریپت‌ها مجوز اجرا دارند
+allowed.prt=اسکریپت‌ها مجوز موقت Ùعالیت دارند
+allowed.no=اسکریپت‌ها مجوز اجرا ندارند
+global.warning.title=هشدار!
+global.warning.text=به اسکریپت‌های تمام سایت‌ها اجازه Ùعالیت داده خواهد شد.ادامه؟
+audio.samples=نمونه‌های صوتی
+confirm=آیا مطمئن هستید؟
+alwaysAsk=همیشه بپرس
+notifyHide=پنهان شدن پس از %S ثانیه
+trust=تایید %S
+distrust=نشانه گذاری %S به عنوان سایت مشکوک
+untrustedOrigin=منبع نامطمئن
+xss.notify.generic=یک درخواست XSS از %S Ùیلتر شد.اطلاعات بیشتر در کنسول ذخیره شده است.
+xss.notify.showConsole=نمایش کنسول...
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Sanitized suspicious request. Original URL [%1$S] requested from [%2$S]. Sanitized URL: [%3$S].)
+xss.reason.filterXGetRef=Sanitized suspicious request referer. URL [%1$S] requested from [%2$S]. Sanitized Referer: [%3$S].)
+xss.reason.filterXPost=Sanitized suspicious upload to [%1$S] from [%2$S]: transformed into a download-only GET request.
+unsafeReload.warning=UNSAFELY reloading a suspicious\n\n%1$S [%2$S]\n\nFROM [%3$S]\n\nNoScript will NOT protect this request!\n
+metaRefresh.notify=NoScript یک تغییر مسیر <META> را در یک عنصر <NOSCRIPT> متوق٠کرد : %S در %S ثانیه
+metaRefresh.notify.follow=ادامه تغییر مسیر
+metaRefresh.notify.follow.accessKey=د
+notify.options=تنظیمات
+notify.options.accessKey=ت
+reset.title=راه اندازی دوباره NoScript
+reset.warning=تمام تنظیم ها Ùˆ سایت های دارای مجوز به حالت پیش Ùرض باز Ù…ÛŒ گردد.
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark's content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/fi/noscript/about.properties b/extensions/noscript/chrome/locale/fi/noscript/about.properties
new file mode 100644
index 0000000..15f1a0f
--- /dev/null
+++ b/extensions/noscript/chrome/locale/fi/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Lisäsuoja selaimelle Firefox: NoScript sallii JavaScript, Java (ja muut lisäkkeet) vain valitsemiltasi luotettavilta sivustoilta (esim. oman verkkopankin kotisivu). Tämä sallittujen listaan perustuva ennakoiva lähestymistapa estää tietoturva haavoittuvuuksien hyväksikäyttöä (tunnettujen ja jopa tuntemattomien!) ilman, että toimivuus heikentyy... Asiantuntijat ovat samaa mieltä: Firefox on oikeasti turvallisempi NoScript'in kanssa :-)
+aboutTitle=Tietoja %S
+extensionContributors=Käännökset:
+extensionContributors.tip=Ihmisiä joita on kiittäminen tästä laajennuksesta
+extensionCreatorLabel=Tekijä:
+changelog=Muutokset
+changelog.tip=Näytä versiomuutokset
+license=Lisenssi
+license.tip=Lue käyttöoikeuslisenssi
+logo.tip=Vieraile laajennuksen kotisivulla
+sponsor.tip=Vieraile sponsorin kotisivulla
+informaction.tip=Vieraile InformAction kotisivulla
+extensionHomepage.tip=Vieraile laajennuksen kotisivulla
+extensionCreator.tip=Vieraile tekijän kotisivulla
+version=Versio %S
diff --git a/extensions/noscript/chrome/locale/fi/noscript/noscript.dtd b/extensions/noscript/chrome/locale/fi/noscript/noscript.dtd
new file mode 100644
index 0000000..50dff61
--- /dev/null
+++ b/extensions/noscript/chrome/locale/fi/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Asetukset…">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript asetukset">
+<!ENTITY noscriptAbout "Tietoja NoScript 5.1.8.5istä…">
+<!ENTITY noscriptPermissionsText "Voit määrittää verkkosivut joiden sallitaan suorittaa scriptejä. Kirjoita verkko-osoite tai verkkonimi (esim. &quot;http://www.site.com&quot; tai &quot;site.com&quot;) jonka haluat sallia ja paina Salli.">
+<!ENTITY noscriptWebAddress "Verkkosivun osoite:">
+<!ENTITY noscriptAllow "Salli">
+<!ENTITY noscriptAllow.accesskey "l">
+<!ENTITY noscriptForbid "Kiellä">
+<!ENTITY noscriptForbid.accesskey "K">
+<!ENTITY noscriptTrust "Merkitse luotettavaksi">
+<!ENTITY noscriptTrust.accesskey "t">
+<!ENTITY noscriptUntrust "Merkitse epäluotettavaksi">
+<!ENTITY noscriptUntrust.accesskey "u">
+<!ENTITY noscriptRemoveSelected "Poista valitut sivut">
+<!ENTITY noscriptGloballyEnabled "Scriptit yleisesti sallittuja (turvaton)">
+<!ENTITY noscriptAutoReload "Lataa sivut automaattisesti uudelleen jos oikeudet muuttuvat">
+<!ENTITY noscriptGeneral "Yleistä">
+<!ENTITY noscriptAppearance "Ulkoasu">
+<!ENTITY noscriptShow "Näytä…">
+<!ENTITY noscriptCtxMenu "Hiiren 2. napin valikko">
+<!ENTITY noscriptStatusIcon "Tilapalkin kuvake">
+<!ENTITY noscriptFullAddr "Koko verkko-osoitteet (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Koko osoitenimet (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Tason 2 osoitenimet (noscript.net)">
+<!ENTITY noscriptTempCmd "Salli tilapäisesti […]">
+<!ENTITY noscriptSound "Äänimerkki kun scripti estetään">
+<!ENTITY noscriptImport "Tuo">
+<!ENTITY noscriptImport.accesskey "T">
+<!ENTITY noscriptExport "Vie">
+<!ENTITY noscriptExport.accesskey "V">
+<!ENTITY noscriptNotify "Näytä viesti estetyistä scripteistä">
+<!ENTITY noscriptNotify.bottom "Sijoita viesti alas">
+<!ENTITY noscriptSound.choose "Valitse">
+<!ENTITY noscriptSound.choose.accesskey "V">
+<!ENTITY noscriptSound.play "Toista">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Oletusarvot">
+<!ENTITY noscriptSound.reset.accesskey "O">
+<!ENTITY noscriptAdvanced "Lisäasetukset">
+<!ENTITY noscriptAdditionalPermissions "Lisäoikeudet luotetuille sivustoille">
+<!ENTITY noscriptAllowClipboard "Salli &quot;rich text&quot; kopiointi ja liittäminen ulkoiselta leikepöydältä">
+<!ENTITY noscriptAdditionalRestrictions "Lisäestot epäluotettaville sivustoille">
+<!ENTITY noscriptPlugins "Liitännäiset">
+<!ENTITY noscriptContentBlocker "Käytä näitä rajoituksia myös sallituille sivustoille">
+<!ENTITY noscriptForbidJava "Estä Java™">
+<!ENTITY noscriptForbidXSLT "Estä XSLT">
+<!ENTITY noscriptForbidSilverlight "Estä Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Estä &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Estä &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Estä @font-face">
+<!ENTITY noscriptForbidMedia "Estä &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Estä Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Estä muut lisäkkeet">
+<!ENTITY noscriptForbidWebGL "Estä WebGL">
+<!ENTITY noscriptReloadWarn "Nämä asetukset tulevat voimaan uusilla tai uudelleen ladatuilla sivuilla">
+<!ENTITY noscriptConfirmUnblock "Kysy hyväksyntä ennen tilapäistä kohteen vapauttamista">
+<!ENTITY noscriptStatusLabel "Tilarivin huomautukset">
+<!ENTITY noscriptForbidBookmarklets "Estä kirjanmerkki lisäkkeet">
+<!ENTITY noscriptShowPlaceholder "Näytä sijoitettu kuvake">
+<!ENTITY noscriptTruncateTitle "Katkaise dokumenttien otsikot">
+<!ENTITY noscriptFixLinks "Yritä korjata JavaScript linkit">
+<!ENTITY noscriptAllowBookmarks "Salli kirjanmerkkien kautta avatut sivustot">
+<!ENTITY noscriptAllowViaBookmarks "Salli kirjanmerkkien kautta avatut sivustot">
+<!ENTITY noscriptAllowPing "Salli &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Salli paikalliset linkit">
+<!ENTITY noscriptForbidPing "Estä &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Estä META uudelleenohjaukset &lt;NOSCRIPT&gt; elementtien sisällä">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "U">
+<!ENTITY noscriptNotifyMeta "Näytä viesti estetyistä META uudelleenohjauksista">
+<!ENTITY noscriptNotifyMeta.accesskey "U">
+<!ENTITY noscriptWhitelist "Sallittujen lista">
+<!ENTITY noscriptPermissions "Käyttöoikeudet">
+<!ENTITY noscriptRefresh "Päivitä">
+<!ENTITY noscriptNotifications "Ilmoitukset">
+<!ENTITY noscriptToolbarToggle "Hiiren napsautus työkalurivin NoScript painikkeeseen vaihtaa oikeudet nykyiselle sivulle">
+<!ENTITY noscriptTrusted "Luotettu">
+<!ENTITY noscriptUntrusted "Epäluotettava">
+<!ENTITY noscriptUnknown "Tuntematon">
+<!ENTITY noscriptAdd "Lisää">
+<!ENTITY noscriptAdd.accesskey "L">
+<!ENTITY noscriptClose "Sulje">
+<!ENTITY noscriptSiteManager "Sivustojen hallinta">
+<!ENTITY noscriptSecurityManager "Suojausten hallinta">
+<!ENTITY noscriptPolicies "Käytännöt">
+<!ENTITY noscriptDefaultPolicies "Oletus käytännöt">
+<!ENTITY noscriptSitePolicies "Sivustokohtaiset käytännöt">
+<!ENTITY noscriptNselNever "Piilota &lt;NOSCRIPT&gt; elementit">
+<!ENTITY noscriptNselForce "Näytä &lt;NOSCRIPT&gt; elementit jotka seuraavat estettyä &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Tilapäisesti salli ylimmän tason sivustot oletusarvoisesti">
+<!ENTITY noscriptDescription "Lisäsuoja selaimelle Firefox: NoScript sallii JavaScript, Java (ja muut lisäkkeet) vain valitsemiltasi luotettavilta sivustoilta (esim. oman verkkopankin kotisivu). Tämä sallittujen listaan perustuva ennakoiva lähestymistapa estää tietoturva haavoittuvuuksien hyväksikäyttöä (tunnettujen ja jopa tuntemattomien!) ilman, että toimivuus heikentyy... Asiantuntijat ovat samaa mieltä: Firefox on oikeasti turvallisempi NoScript'in kanssa :-)">
+<!ENTITY noscriptOptBlockCssScanners "Estä CSS-pohjaiset skannerit">
+<!ENTITY noscriptOptFilterXGet "Siisti sivustojen väliset epäilyttävät pyynnöt">
+<!ENTITY noscriptOptFilterXPost "Muuta sivustojen väliset POST-pyynnöt vähemmän tietoja sis. GET pyynnöiksi">
+<!ENTITY noscriptShowConsole "Näytä konsoli…">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS usein kysytyt…">
+<!ENTITY noscriptXssFaq.accesskey "K">
+<!ENTITY noscriptUnsafeReload "Turvaton uudelleen lataus">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Anti-XSS suojaus poikkeukset">
+<!ENTITY noscriptXssExceptions.description "Kohteet jotka sopivat näihin &quot;regular expression&quot; lausekkeisiin EIVÄT ole suojattuja XSS vastaan.">
+<!ENTITY noscriptMatchSample "Kaavan sopivuus näyte:">
+<!ENTITY noscriptReset "Nollaa">
+<!ENTITY noscriptReset.accesskey "o">
+<!ENTITY noscriptResetDef "Palauta oletukset">
+<!ENTITY noscriptResetDef.accesskey "o">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Peruuta tilapäiset oikeudet">
+<!ENTITY noscriptRevokeTemp.accesskey "t">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ei paikkamerkkiä kohteille jotka merkitty epäluotettaviksi">
+<!ENTITY noscriptCollapseBlockedObjects "Supista estetyt kohteet">
+<!ENTITY noscriptExceptions "Poikkeukset…">
+<!ENTITY noscriptBlockedObjects "Estetyt kohteet">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Estä jokainen kohde joka tulee epäluotettavalta sivulta">
+<!ENTITY noscriptTempAllowPage "Tilapäisesti salli kaikki tällä sivulla">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "Salli kaikki tällä sivulla">
+<!ENTITY noscriptAllowPage.accesskey "S">
+<!ENTITY noscriptTempToPerm "Tee sivun oikeudet pysyviksi">
+<!ENTITY noscriptTempToPerm.accesskey "p">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS usein kysytyt…">
+<!ENTITY noscriptHttpsFaq.accesskey "U">
+<!ENTITY noscriptHttps.behavior "Käyttäytyminen">
+<!ENTITY noscriptHttps.cookies "Evästeet">
+<!ENTITY noscriptHttps.description "Estä aktiivinen web-sisältö ellei se tule suojatusta (HTTPS) yhteydestä:">
+<!ENTITY noscriptHttps.never "Ei koskaan">
+<!ENTITY noscriptHttps.proxy "Kun välityspalvelinta käytetään (suositeltavaa Tor käytössä)">
+<!ENTITY noscriptHttps.always "Aina">
+<!ENTITY noscriptHttpsForced "Pakota seuraavat sivustot käyttämään suojattua (HTTPS) yhteyttä:">
+<!ENTITY noscriptHttpsForcedExceptions "Älä koskaan pakota suojattua (HTTPS) yhteyttä seuraavista sivuista:">
+<!ENTITY noscriptSecureCookies "Ota käyttöön automaattinen suojattujen evästeiden hallinta">
+<!ENTITY noscriptSecureCookiesForced "Pakota salaus kaikkiin evästeisiin HTTPS yhteydessä seuraavista sivuista:">
+<!ENTITY noscriptSecureCookiesExceptions "Ohita suojaamattomat evästeet HTTPS yhteydessä seuraavista sivuista:">
+<!ENTITY noscriptClearClickTitle "ClearClick varoitus">
+<!ENTITY noscriptClearClickHeader "Mahdollinen klikkauksen kaappaus / käyttöliittym. naamiointi yritys!">
+<!ENTITY noscriptClearClickDescription "NoScript keskeytti hiiri- tai näppäimistö vuorovaikutuksen osittain piilotettuun kohteeseen. Klikkaa kuvaa alla vaihtaaksesi sumennetun ja selkeän version välillä.">
+<!ENTITY noscriptClearClickOpt "ClearClick suojaus sivuilla…">
+<!ENTITY noscriptClearClickReport "Raportoi">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Raportin ID:">
+<!ENTITY noscriptTrustedPagesAdj "luotettu">
+<!ENTITY noscriptUntrustedPagesAdj "epäluotettava">
+<!ENTITY noscriptKeepLocked "Pidä tämä elementti lukittuna (suositus)">
+<!ENTITY noscriptEmbeddings "Sulautetut">
+<!ENTITY noscriptPrev "Edellinen">
+<!ENTITY noscriptNext "Seuraava">
+<!ENTITY noscriptFrameOptErr.title "Tätä sisältöä ei voida näyttää kehyksessä">
+<!ENTITY noscriptFrameOptErr.desc "Tämän sisällön julkaisija ei turvallisuus syistä anna sen näkyä kehyksessä.">
+<!ENTITY noscriptFrameOptErr.link "Klikkaa tästä avataksesi tämän sisällön uuteen ikkunaan">
+<!ENTITY noscriptBookmarkSync "Varmuuskopioi NoScript asetukset kirjanmerkkiin helppoa synkronointia varten">
+<!ENTITY noscriptShowReleaseNotes "Näytä julkaisutiedot päivityksen yhteydessä">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Säännöt:">
+<!ENTITY ABE.enabled.label "Käytä ABE:tä (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Sivustot voivat tarjota omia sääntöjään">
+<!ENTITY ABE.edit.label "Muokkaa…">
+<!ENTITY ABE.edit.accesskey "M">
+<!ENTITY ABE.enable.label "Käytä">
+<!ENTITY ABE.enable.accesskey "K">
+<!ENTITY ABE.disable.label "Poista käytöstä">
+<!ENTITY ABE.disable.accesskey "P">
+<!ENTITY ABE.refresh.label "Päivitä">
+<!ENTITY ABE.refresh.accesskey "P">
+<!ENTITY noscriptUninstall "Poista asennus">
+<!ENTITY noscriptRecentBlocked "Viimeksi estetyt sivustot">
+<!ENTITY noscriptExternalFilters "Ulkoiset suodattimet">
+<!ENTITY noscriptEF.enable "Käytä ulkoisia suodattimia">
+<!ENTITY noscriptEF.add "Uusi suodatin…">
+<!ENTITY noscriptEF.executable "Suoritettava tiedosto:">
+<!ENTITY noscriptEF.browse "Selaa…">
+<!ENTITY noscriptEF.contentType "Sisällön tyyppi (MIME) suodatettavaksi (täsmällinen tai &quot;regular expression&quot; lauseke):">
+<!ENTITY noscriptEF.exceptions "Älä suodata kohteita näiltä sivuilta:">
+<!ENTITY noscriptEF.remove "Poista">
+<!ENTITY noscriptPreset "Suojaustaso">
+<!ENTITY noscriptPreset.off "Pois (oletko tosissasi?!)">
+<!ENTITY noscriptPreset.low "Kevyt (estolista + Web Security)">
+<!ENTITY noscriptPreset.medium "Klassinen (sallittujen lista + Web Security)">
+<!ENTITY noscriptPreset.high "Linnake (täysi lukitus)">
+<!ENTITY noscript.hoverUI "Avaa oikeudet valikko kun hiiri osoittaa NoScript kuvaketta">
+<!ENTITY noscriptDonate "Lahjoita">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/fi/noscript/noscript.properties b/extensions/noscript/chrome/locale/fi/noscript/noscript.properties
new file mode 100644
index 0000000..e5cf932
--- /dev/null
+++ b/extensions/noscript/chrome/locale/fi/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Salli scriptit yleisesti (turvaton)
+forbidGlobal=Estä scriptit yleisesti (suositeltava)
+allowLocal=Salli %S
+allowTemp=Salli tilapäisesti %S
+forbidLocal=Estä %S
+allowed.glb=Varoitus! Scriptit käytössä kaikille sivuille
+allowed.yes=Scriptit pysyvästi sallittu
+allowed.prt=Scriptit osittain sallittu
+allowed.no=Scriptit pysyvästi estetty
+global.warning.title=Varoitus!
+global.warning.text=Scriptit asetetaan sallituksi yleisesti (kaikille sivustoille).\n Tämä on turvaton asetus.\nHaluatko varmasti jatkaa?
+audio.samples=Ääninäytteet
+confirm=Oletko varma?
+alwaysAsk=Kysy vahvistus joka kerta
+notifyHide=Piilota %S sekunnin jälkeen
+trust=Luota %S
+distrust=Merkitse %S epäluotettavaksi
+untrustedOrigin=epäluotettava alkuperä
+xss.notify.generic=NoScript suodatti mahdollisen cross-site scripting (XSS) yrityksen kohteesta %S. Tekniset yksityiskohdat on kirjattu konsoliin.
+xss.notify.showConsole=Näytä konsoli...
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Siistitty epäilyttävä pyyntö. Alkuperäinen URL [%1$S] pyydetty kohteesta [%2$S]. Siistitty URL: [%3$S].
+xss.reason.filterXGetRef=Siistitty epäilyttävä pyyntö viittaus. URL [%1$S] pyydetty kohteesta [%2$S]. Siistitty viittaus: [%3$S].
+xss.reason.filterXPost=Siistitty epäilyttävä lataus kohteeseen [%1$S] osoitteesta [%2$S]: muutettu vain-lataus GET pyynnöksi.
+unsafeReload.warning=TURVATTOMASTI uudelleenlataa epäilyttävän\n\n%1$S [%2$S]\n\nKOHTEESTA [%3$S]\n\nNoScript EI suojaa tätä pyyntöä!\n
+metaRefresh.notify=NoScript esti <META> uudelleenohjauksen <NOSCRIPT> elementin sisällä: %S %S sekunnissa.
+metaRefresh.notify.follow=Seuraa uudelleen ohjausta
+metaRefresh.notify.follow.accessKey=F
+notify.options=Valinnat
+notify.options.accessKey=O
+reset.title=NoScript oletukset
+reset.warning=KAIKKI NoScript asetukset ja sivustojen oikeudet palautetaan oletusarvoihinsa välittömästi. \nTätä toimintoa ei voi palauttaa. \nHaluatko jatkaa?
+bookmarkSync.title=NoScript asetukset -kirjanmerkki
+bookmarkSync.message=Tätä kirjanmerkkiä EI ole tarkoitus avata, vaan synkronoida käyttäen palvelua kuten Weave tai Xmarks laajennus.
+bookmarkSync.confirm=NoScript on löytänyt asetukset -kirjanmerkin ilmeisesti tallennettuna\n%S.\nHaluatko varmasti korvata paikallisen NoScript kokoonpanon tämän kirjanmerkin sisällöllä?
+ABE.notify=Pyyntö %1$S suodattanut ABE: <%2$S> %3$S
+ABE.chooseEditor=Valitse tekstieditori ABE säännöille
+ABE.syntaxError=Syntaksivirhe ABE säännössä!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Salli kaikki kohteesta %S
+allowTempFrom=Tilapäisesti salli kaikki kohteesta %S
+siteInfo.confirm=Olet aikeissa kysyä tietoja sivusta "%1$S" \nesittämällä kyselyn kohteeseen %2$S.\nHaluatko jatkaa?
+siteInfo.tooltip=Keskimmäinen-klik tai VAIHTO+klik avaa sivuston tietoja...
+ef.activate=Suodata %S
+ef.options=%S valinnat...
+ef.newName=Kirjoita nimi uudelle suodattimelle:
+ef.locateExe=Valitse suoritettava tiedosto %S suodattimelle
+disable=Poista käytöstä %S
+disable.accessKey=P
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/fr/noscript/about.properties b/extensions/noscript/chrome/locale/fr/noscript/about.properties
new file mode 100644
index 0000000..b8503c4
--- /dev/null
+++ b/extensions/noscript/chrome/locale/fr/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Protection supplémentaire pour votre navigateur Firefox : NoScript n'autorise JavaScript, Java (et les autres plugins) que sur les domaines de confiance de votre choix (par exemple le site web de votre banque). Cette approche de blocage préventif basée sur une liste blanche empêche l'exploitation de failles de sécurité (connues et même inconnues !) sans perte de fonctionnalités… Les experts en conviendront : Firefox est vraiment plus sécurisé avec NoScript. :-)
+aboutTitle=À propos de %S
+extensionContributors=Contributeurs :
+extensionContributors.tip=Personnes que vous devriez remercier pour cette extension
+extensionCreatorLabel=Auteur :
+changelog=Changements
+changelog.tip=Afficher les changements
+license=Licence
+license.tip=Lire la licence pour l'utilisateur final
+logo.tip=Visiter le site de l'extension
+sponsor.tip=Visiter le site du sponsor
+informaction.tip=Visiter le site d'InformAction
+extensionHomepage.tip=Visiter le site de l'extension
+extensionCreator.tip=Visiter le site de l'auteur
+version=Version %S
diff --git a/extensions/noscript/chrome/locale/fr/noscript/noscript.dtd b/extensions/noscript/chrome/locale/fr/noscript/noscript.dtd
new file mode 100644
index 0000000..64e49d7
--- /dev/null
+++ b/extensions/noscript/chrome/locale/fr/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Options">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Options de NoScript">
+<!ENTITY noscriptAbout "À propos de NoScript 5.1.8.5…">
+<!ENTITY noscriptPermissionsText "Il est possible de spécifier quels sites Web sont autorisés à exécuter des scripts. Saisissez l&apos;adresse exacte du site que vous désirez autoriser puis cliquez sur Autoriser.">
+<!ENTITY noscriptWebAddress "Adresse du site Web :">
+<!ENTITY noscriptAllow "Autoriser">
+<!ENTITY noscriptAllow.accesskey "A">
+<!ENTITY noscriptForbid "Interdire">
+<!ENTITY noscriptForbid.accesskey "I">
+<!ENTITY noscriptTrust "Faire confiance">
+<!ENTITY noscriptTrust.accesskey "C">
+<!ENTITY noscriptUntrust "Ne pas faire confiance">
+<!ENTITY noscriptUntrust.accesskey "P">
+<!ENTITY noscriptRemoveSelected "Enlever les sites sélectionnés">
+<!ENTITY noscriptGloballyEnabled "Autoriser les scripts globalement (dangereux)">
+<!ENTITY noscriptAutoReload "Recharger les pages affectées automatiquement après avoir changé les permissions">
+<!ENTITY noscriptGeneral "Général">
+<!ENTITY noscriptAppearance "Apparence">
+<!ENTITY noscriptShow "Afficher...">
+<!ENTITY noscriptCtxMenu "Menu contextuel">
+<!ENTITY noscriptStatusIcon "Icône dans la barre d&apos;état">
+<!ENTITY noscriptFullAddr "Adresses complètes (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Domaines complets (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Domaines de second niveau (noscript.net)">
+<!ENTITY noscriptTempCmd "Autoriser temporairement [...]">
+<!ENTITY noscriptSound "Retour audio quand des scripts sont bloqués">
+<!ENTITY noscriptImport "Importer">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exporter">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Afficher un message à propos des scripts bloqués">
+<!ENTITY noscriptNotify.bottom "Placer le message en bas">
+<!ENTITY noscriptSound.choose "Choisir">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Jouer">
+<!ENTITY noscriptSound.play.accesskey "J">
+<!ENTITY noscriptSound.reset "Réinitialiser">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Avancé">
+<!ENTITY noscriptAdditionalPermissions "Permissions supplémentaires pour les sites de confiance">
+<!ENTITY noscriptAllowClipboard "Autoriser le copier/coller de texte riche du presse-papier">
+<!ENTITY noscriptAdditionalRestrictions "Restrictions supplémentaires pour les sites à risque">
+<!ENTITY noscriptPlugins "Greffons">
+<!ENTITY noscriptContentBlocker "Appliquer ces restrictions également aux sites de confiance">
+<!ENTITY noscriptForbidJava "Interdire Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Interdire XSLT">
+<!ENTITY noscriptForbidSilverlight "Interdire Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Interdire &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Interdire &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Interdire @font-face">
+<!ENTITY noscriptForbidWebGL "Interdire WebGL">
+<!ENTITY noscriptForbidMedia "Interdire &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Interdire Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Interdire les autres plugins">
+<!ENTITY noscriptReloadWarn "Ces options prendront effet sur les pages rechargées (manuellement) et les nouvelles pages">
+<!ENTITY noscriptConfirmUnblock "Demander confirmation avant de débloquer temporairement un objet">
+<!ENTITY noscriptStatusLabel "Étiquette dans la barre d&apos;état">
+<!ENTITY noscriptForbidBookmarklets "Interdire les bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Afficher l&apos;emplacement fictif de l&apos;objet bloqué">
+<!ENTITY noscriptTruncateTitle "Tronquer le titre des documents">
+<!ENTITY noscriptFixLinks "Essayer de réparer les liens javascript">
+<!ENTITY noscriptAllowBookmarks "Autoriser tous les sites trouvés dans les marque-pages">
+<!ENTITY noscriptAllowViaBookmarks "Autoriser les sites ouverts par les marque-pages">
+<!ENTITY noscriptAllowPing "Autoriser &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Autoriser les liens locaux">
+<!ENTITY noscriptForbidPing "Interdire &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Interdire les redirections META dans des éléments &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "Afficher un message à propos des redirections META bloquées">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "Liste blanche">
+<!ENTITY noscriptPermissions "Permissions">
+<!ENTITY noscriptRefresh "Actualiser">
+<!ENTITY noscriptNotifications "Notifications">
+<!ENTITY noscriptToolbarToggle "Clic gauche sur le bouton de barre d&apos;outils NoScript inverse les permissions pour le site de premier niveau en cours">
+<!ENTITY noscriptTrusted "Fiable">
+<!ENTITY noscriptUntrusted "Non fiable">
+<!ENTITY noscriptUnknown "Inconnu">
+<!ENTITY noscriptAdd "Ajouter">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Fermer">
+<!ENTITY noscriptSiteManager "Gestionnaire de sites">
+<!ENTITY noscriptSecurityManager "Gestionnaire de sécurité">
+<!ENTITY noscriptPolicies "Politiques">
+<!ENTITY noscriptDefaultPolicies "Politiques par défaut">
+<!ENTITY noscriptSitePolicies "Politiques par site">
+<!ENTITY noscriptNselNever "Cacher les éléments &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Afficher l&apos;élément &lt;NOSCRIPT&gt; qui suit un &lt;SCRIPT&gt; bloqué">
+<!ENTITY noscriptAutoAllowTopLevel "Autoriser temporairement les sites de premier niveau par défaut">
+<!ENTITY noscriptDescription "Protection supplémentaire pour votre Firefox : NoScript ne permet l&apos;exécution de scripts JavaScript que sur les domaines de confiance de votre choix (p.ex. le site de votre banque). Ce système de blocage préventif de scripts basé sur une liste blanche empêche l&apos;exploitation de failles de sécurité (connues et même inconnues) sans perte de fonctionnalités… Les experts en conviendront : Firefox est réellement plus sûr avec NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Bloquer les scanners basés sur des CSS">
+<!ENTITY noscriptOptFilterXGet "Nettoyer les requêtes suspicieuses entre sites">
+<!ENTITY noscriptOptFilterXPost "Transformer les requêtes POST entre sites en requêtes GET sans données">
+<!ENTITY noscriptShowConsole "Afficher la console...">
+<!ENTITY noscriptShowConsole.accesskey "A">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "FAQ XSS">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Rechargement non sécurisé">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Exceptions de protection anti-XSS">
+<!ENTITY noscriptXssExceptions.description "Les destinations correspondant aux expressions régulières suivantes ne seront pas protégées contre le XSS">
+<!ENTITY noscriptMatchSample "Exemple de motif :">
+<!ENTITY noscriptReset "Réinitialiser">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Rétablir les valeurs par défaut">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Révoquer les permissions temporaires">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ne pas réserver d&apos;espace pour les objets venant de sites marqués comme sites à risque">
+<!ENTITY noscriptCollapseBlockedObjects "Utiliser l&apos;espace libéré par les éléments bloqués">
+<!ENTITY noscriptExceptions "Exceptions...">
+<!ENTITY noscriptBlockedObjects "Objets bloqués">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Bloquer tous les objets venant d&apos;un site marqué comme non fiable">
+<!ENTITY noscriptTempAllowPage "Autoriser cette page temporairement">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Autoriser toute la page">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Rendre les permissions de cette page permanentes">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "FAQ HTTPS...">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Comportement">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Interdire le contenu web actif, sauf s&apos;il vient d&apos;une connexion sécurisée (HTTPS) :">
+<!ENTITY noscriptHttps.never "Jamais">
+<!ENTITY noscriptHttps.proxy "Lors de l&apos;utilisation d&apos;un proxy (recommandé avec Tor)">
+<!ENTITY noscriptHttps.always "Toujours">
+<!ENTITY noscriptHttpsForced "Forcer les sites suivants à utiliser une connexion sécurisée (HTTPS) :">
+<!ENTITY noscriptHttpsForcedExceptions "Ne jamais forcer les sites suivants à utiliser une connexion sécurisée (HTTPS) :">
+<!ENTITY noscriptSecureCookies "Activer la Gestion Sécurisée Automatique des Cookies">
+<!ENTITY noscriptSecureCookiesForced "Forcer le chiffrement pour tous les cookies définis par HTTPS pour les sites suivants :">
+<!ENTITY noscriptSecureCookiesExceptions "Ignorer les cookies non sûrs définis par HTTPS pour les sites suivants :">
+<!ENTITY noscriptClearClickTitle "Avertissement ClearClick">
+<!ENTITY noscriptClearClickHeader "Clickjacking potentiel / rétablissement de tentative d&apos;UI">
+<!ENTITY noscriptClearClickDescription "NoScript a intercepté une interaction de la souris ou du clavier avec une élément partiellement caché. Cliquez sur l&apos;image en-dessus pour passer de la version cachée à la version visible.">
+<!ENTITY noscriptClearClickOpt "Protection ClearClick sur les pages…">
+<!ENTITY noscriptClearClickReport "Rapport">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "ID du rapport">
+<!ENTITY noscriptTrustedPagesAdj "fiables">
+<!ENTITY noscriptUntrustedPagesAdj "non fiables">
+<!ENTITY noscriptKeepLocked "Garder cet environnement verrouillé (recommandé)">
+<!ENTITY noscriptEmbeddings "Objets embarqués">
+<!ENTITY noscriptPrev "Précédent">
+<!ENTITY noscriptNext "Suivant">
+<!ENTITY noscriptFrameOptErr.title "Le contenu ne peut pas être affiché dans un cadre">
+<!ENTITY noscriptFrameOptErr.desc "Pour protéger votre sécurité, l'éditeur de ce contenu n'autorise pas à l'afficher dans un cadre.">
+<!ENTITY noscriptFrameOptErr.link "Cliquez ici pour ouvrir ce contenu dans une nouvelle fenêtre">
+<!ENTITY noscriptBookmarkSync "Sauvegarder la configuration de NoScript dans un marque-page pour une synchronisation facile">
+<!ENTITY noscriptShowReleaseNotes "Afficher les notes de version lors des mises à jour">
+<!ENTITY ABE "EFA">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Jeux de règles :">
+<!ENTITY ABE.enabled.label "Activer EFA (Exécuteur de Frontières des Applications)">
+<!ENTITY ABE.siteEnabled.label "Autoriser les sites à faire passer leurs propres jeux de règles">
+<!ENTITY ABE.edit.label "Éditer…">
+<!ENTITY ABE.edit.accesskey "e">
+<!ENTITY ABE.enable.label "Activer">
+<!ENTITY ABE.enable.accesskey "v">
+<!ENTITY ABE.disable.label "Désactiver">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Actualiser">
+<!ENTITY ABE.refresh.accesskey "r">
+<!ENTITY noscriptUninstall "Désinstaller">
+<!ENTITY noscriptRecentBlocked "Sites récemment bloqués">
+<!ENTITY noscriptExternalFilters "Filtres externes">
+<!ENTITY noscriptEF.enable "Activer les filtres externes">
+<!ENTITY noscriptEF.add "Nouveau filtre…">
+<!ENTITY noscriptEF.executable "Fichier exécutable :">
+<!ENTITY noscriptEF.browse "Parcourir…">
+<!ENTITY noscriptEF.contentType "Type de contenu (MIME) à filtrer (correspondance exacte ou expression rationnelle) :">
+<!ENTITY noscriptEF.exceptions "Ne pas filtrer les objets provenant de ces sites :">
+<!ENTITY noscriptEF.remove "Supprimer">
+<!ENTITY noscriptPreset "Niveau de sécurité">
+<!ENTITY noscriptPreset.off "Éteint (vous êtes sérieux ?!)">
+<!ENTITY noscriptPreset.low "Passage facile (liste noire + sécurité web)">
+<!ENTITY noscriptPreset.medium "Classique (liste blanche + sécurité web)">
+<!ENTITY noscriptPreset.high "Forteresse (blocus complet)">
+<!ENTITY noscript.hoverUI "Ouvrir le menu des permissions lorsque la souris survole l'icône de NoScript.">
+<!ENTITY noscriptDonate "Donner">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Répercuter les permissions du document principal vers les scripts de tierce partie">
+<!ENTITY noscriptRestrictSubdocScripting "Bloquer les scripts dans les sous-documents sur liste blanche, sur les pages non placées sur liste blanche">
+<!ENTITY noscriptGlobalHttpsWhitelist "Autoriser les scripts HTTPS globalement, dans les documents HTTPS">
+<!ENTITY noscriptAutoReload.currentTab "Recharger uniquement l'onglet actif">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
+<!ENTITY noscriptCustom "Custom">
diff --git a/extensions/noscript/chrome/locale/fr/noscript/noscript.properties b/extensions/noscript/chrome/locale/fr/noscript/noscript.properties
new file mode 100644
index 0000000..3d04621
--- /dev/null
+++ b/extensions/noscript/chrome/locale/fr/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Autoriser Javascript globalement (dangereux)
+forbidGlobal=Interdire Javascript globalement (recommandé)
+allowLocal=Autoriser %S
+allowTemp=Autoriser %S temporairement
+forbidLocal=Interdire %S
+allowed.glb=Danger ! Javascript autorisé globalement
+allowed.yes=Javascript actuellement autorisé
+allowed.prt=JavaScript partiellement autorisé
+allowed.no=Javascript actuellement interdit
+global.warning.title=Attention !
+global.warning.text=Javascript sera autorisé globalement (pour tous les sites).\nCette action est potentiellement dangereuse.\nVoulez-vous réellement continuer ?
+audio.samples=Exemples audio
+confirm=Êtes-vous sûr ?
+alwaysAsk=Toujours demander confirmation
+notifyHide=Cacher après %S seconde(s)
+trust=Faire confiance à %S
+distrust=Marquer %S comme non fiable
+untrustedOrigin=une origine douteuse
+xss.notify.generic=NoScript a filtré une tentative de script entre sites (Cross-site scripting, XSS) de %S. Les détails techniques ont été inscrits dans la console.
+xss.notify.showConsole=Afficher la console...
+xss.notify.showConsole.accessKey=A
+xss.reason.filterXGet=Nettoyé requête suspicieuse. URL originale [%1$S] demandée depuis [%2$S]. URL nettoyée : [%3$S].
+xss.reason.filterXGetRef=Nettoyé requête de référence suspicieuse. URL [%1$S] demandée depuis [%2$S]. Référent nettoyé : [%3$S].
+xss.reason.filterXPost=Nettoyé téléversement suspicieux vers [%1$S] depuis [%2$S] : transformé en une simple requête de téléchargement GET.
+unsafeReload.warning=Rechargement NON SÛR d'un\n\n%1$S [%2$S]\n\nsuspicieux\n\nDE [%3$S]\n\nNoScript ne protégera PAS cette requête !\n
+metaRefresh.notify=NoScript a bloqué une redirection <meta> dans un élément <noscript> : %S en %S secondes
+metaRefresh.notify.follow=Suivre la redirection
+metaRefresh.notify.follow.accessKey=S
+notify.options=Options
+notify.options.accessKey=O
+reset.title=Réinitialiser NoScript
+reset.warning=TOUTES les préférences de NoScript et les permissions des sites seront réinitialisées à leurs valeurs par défaut immédiatement.\nCette action ne peut PAS être annulée.\nVoulez-vous continuer ?
+bookmarkSync.title=Marque-page de configuration de NoScript
+bookmarkSync.message=Ce marque-page n'est PAS prévu pour être ouvert, mais pour être synchronisé en utilisant un service tel que Weave ou l'extension XMarks.
+bookmarkSync.confirm=NoScript a trouvé un marque-page de configuration visiblement sauvegardé le\n%S.\nVoulez-vous vraiment écraser votre configuration de NoScript par le contenu de ce marque-page ?
+ABE.notify=Requête %1$S filtrée par EFA : <%2$S> %3$S
+ABE.chooseEditor=Choisissez un éditeur de texte pour les jeux de règles EFA
+ABE.syntaxError=Erreur de syntaxe dans le jeu de règles EFA !
+ABE.wanIpAsLocal=IP WAN (%S) ∈ LOCAL
+allowFrom=Tout autoriser de %S
+allowTempFrom=Tout autoriser temporairement de %S
+siteInfo.confirm=Vous allez demander des informations à propos du site "%1$S" en soumettant un requête à %2$S.\nVoulez-vous continuer ?
+siteInfo.tooltip=Clic du milieu ou Maj+click pour les infos du site…
+ef.activate=Filtrer %S
+ef.options=Options de %S…
+ef.newName=Entrer le nom du nouveau filtre :
+ef.locateExe=Sélectionner le fichier exécutable pour le filtre %S
+disable=Désactiver %S
+disable.accessKey=D
+removal.title=Avertissement de Baisse de la Sécurité
+removal.message=En désactivant ou désinstallant NoScript, vous abandonnez TOUTES les protections fournies par NoScript.\n\nSi vous êtes simplement fatigué de gérer les permissions de script site par site, il y a un choix plus sûr.\n\nNoScript peut arrêter de bloquer les scripts, exceptés ceux que vous marquez comme non fiables, tout en continuant de vous protéger avec les contremesures de sécurités les plus avancées contre XSS, le Clickjacking, CSRF et d'autres menaces web.\n\nVoulez-vous réellement enlever TOUTES les protections NoScript ?\n
+removal.no=Non, arrêter simplement de bloquer les scripts
+removal.yes=Oui, enlever TOUTES les protections
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/gl-ES/noscript/about.properties b/extensions/noscript/chrome/locale/gl-ES/noscript/about.properties
new file mode 100644
index 0000000..ebb5832
--- /dev/null
+++ b/extensions/noscript/chrome/locale/gl-ES/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality... Experts will agree: Firefox is really safer with NoScript :-)
+aboutTitle=Acerca de %S
+extensionContributors=Colaboradores:
+extensionContributors.tip=Xente á que lle debes agradecer esta extensión
+extensionCreatorLabel=Autor:
+changelog=Cambios
+changelog.tip=Amosar os cambios
+license=Licenza
+license.tip=Ler a licenza de usuario final
+logo.tip=Visitar a páxina web da extensión
+sponsor.tip=Visitar a páxina web do patrocinador
+informaction.tip=Visitar a páxina web de InformAction
+extensionHomepage.tip=Visitar a páxina web da extensión
+extensionCreator.tip=Visitar a páxina web do autor
+version=Version %S
diff --git a/extensions/noscript/chrome/locale/gl-ES/noscript/noscript.dtd b/extensions/noscript/chrome/locale/gl-ES/noscript/noscript.dtd
new file mode 100644
index 0000000..3cf3490
--- /dev/null
+++ b/extensions/noscript/chrome/locale/gl-ES/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opcións...">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Opcións de NoScript">
+<!ENTITY noscriptAbout "Acerca de NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Podes especificar que páxinas web poden executar scripts. Teclea o enderezo ou o dominio (por exemplo &quot;http://www.paxina.com&quot; ou &quot;paxina.com&quot;) do sitio que queres autorizar e despois preme en &quot;Permitir&quot;.">
+<!ENTITY noscriptWebAddress "Enderezo web:">
+<!ENTITY noscriptAllow "Permitir">
+<!ENTITY noscriptAllow.accesskey "A">
+<!ENTITY noscriptForbid "Non permitir">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Marcar como sitio fiábel">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Marcar como sitio non fiábel">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Borrar os ficheiros seleccionados">
+<!ENTITY noscriptGloballyEnabled "Scripts globalmente permitidos (perigoso)">
+<!ENTITY noscriptAutoReload "Recargar automaticamente as páxinas afectadas cando os permisos cambien">
+<!ENTITY noscriptGeneral "Xeral">
+<!ENTITY noscriptAppearance "Aspecto">
+<!ENTITY noscriptShow "Amosar...">
+<!ENTITY noscriptCtxMenu "Menú contextual">
+<!ENTITY noscriptStatusIcon "Icona da barra de estado">
+<!ENTITY noscriptFullAddr "Enderezos completos (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Dominios (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Dominios base de segundo nivel (noscript.net)">
+<!ENTITY noscriptTempCmd "Permitir temporalmente [...]">
+<!ENTITY noscriptSound "Audio feedback when scripts are blocked">
+<!ENTITY noscriptImport "Importar">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exportar">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Amosar mensaxes sobre os scripts bloqueados">
+<!ENTITY noscriptNotify.bottom "Colocar mensaxe ao final">
+<!ENTITY noscriptSound.choose "Escoller">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Reproducir">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Voltar ao valores iniciais">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Avanzado">
+<!ENTITY noscriptAdditionalPermissions "Permisos adicionais para sitios de confianza">
+<!ENTITY noscriptAllowClipboard "Permitir copiar e pegar texto desde un portapapeis externo">
+<!ENTITY noscriptAdditionalRestrictions "Restricións adicionais para sitio non de confianza">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Apply these restrictions to trusted sites too">
+<!ENTITY noscriptForbidJava "Non permitir Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Non permitir XSLT">
+<!ENTITY noscriptForbidSilverlight "Non permitir Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Non permitir &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Non permitir &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Non permitir @font-face">
+<!ENTITY noscriptForbidWebGL "Non permitir WebGL">
+<!ENTITY noscriptForbidMedia "Non permitir &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Non permitir Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Non permitir outros plugins">
+<!ENTITY noscriptReloadWarn "Estas opcións terán efecto en páxinas novas ou (manualmente) recargadas">
+<!ENTITY noscriptConfirmUnblock "Pedir confirmación antes de desblocar temporalmente un obxecto">
+<!ENTITY noscriptStatusLabel "Etiqueta da barra de estado">
+<!ENTITY noscriptForbidBookmarklets "Non permitir bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Amosar icona">
+<!ENTITY noscriptTruncateTitle "Truncar títulos de documentos">
+<!ENTITY noscriptFixLinks "Tentar fixar ligazóns Javascript">
+<!ENTITY noscriptAllowBookmarks "Permitir enderezos abertos mediante bookmarks">
+<!ENTITY noscriptAllowViaBookmarks "Permitir enderezos abertos mediante bookmarks">
+<!ENTITY noscriptAllowPing "Permitir &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Permitir enderezos locais">
+<!ENTITY noscriptForbidPing "Non permitir &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Non permitir redireccións META dentro de elementos &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptWhitelist "Lista branca">
+<!ENTITY noscriptPermissions "Permisos">
+<!ENTITY noscriptRefresh "Refrescar">
+<!ENTITY noscriptNotifications "Notificacións">
+<!ENTITY noscriptToolbarToggle "Clic esquerdo no barra NoScript cambia permisos para a páxina actual">
+<!ENTITY noscriptTrusted "Fiábel">
+<!ENTITY noscriptUntrusted "Non fiábel">
+<!ENTITY noscriptUnknown "Descoñecido">
+<!ENTITY noscriptAdd "Engadir">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Pechar">
+<!ENTITY noscriptSiteManager "Xestor do sitio">
+<!ENTITY noscriptSecurityManager "Xestor de seguridade">
+<!ENTITY noscriptPolicies "Políticas">
+<!ENTITY noscriptDefaultPolicies "Políticas por defecto">
+<!ENTITY noscriptSitePolicies "Políticas específicas do sitio">
+<!ENTITY noscriptNselNever "Ocultar elementos &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Amosar o elemento &lt;NOSCRIPT&gt; que siga a un &lt;SCRIPT&gt; blocado">
+<!ENTITY noscriptAutoAllowTopLevel "Temporarily allow top-level sites by default">
+<!ENTITY noscriptDescription "Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality... Experts will agree: Firefox is really safer with NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Bloquear escáners baseados en CSS">
+<!ENTITY noscriptOptFilterXGet "Sanitize cross-site suspicious requests">
+<!ENTITY noscriptOptFilterXPost "Turn cross-site POST requests into data-less GET requests">
+<!ENTITY noscriptShowConsole "Amosar consola">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "FAQ XSS">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Unsafe Reload">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Excepcións ña protección anti-XSS">
+<!ENTITY noscriptXssExceptions.description "Os destinos que coincidan con estas expresións regulares NON serán protexidos contra XSS">
+<!ENTITY noscriptMatchSample "Mostra de coincidencia de patróns:">
+<!ENTITY noscriptReset "Reset">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Reset to defaults">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revoke Temporary Permissions">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "No placeholder for objects coming from sites marked as untrusted">
+<!ENTITY noscriptCollapseBlockedObjects "Collapse blocked objects">
+<!ENTITY noscriptExceptions "Exceptions...">
+<!ENTITY noscriptBlockedObjects "Blocked Objects">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Block every object coming from a site marked as untrusted">
+<!ENTITY noscriptTempAllowPage "Temporarily allow all this page">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Allow all this page">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Make page permissions permanent">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behavior">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image above to cycle beetween the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Embedded Objects">
+<!ENTITY noscriptPrev "Previuous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/gl-ES/noscript/noscript.properties b/extensions/noscript/chrome/locale/gl-ES/noscript/noscript.properties
new file mode 100644
index 0000000..afc9c9a
--- /dev/null
+++ b/extensions/noscript/chrome/locale/gl-ES/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Permitir scripts globalmente (perigoso)
+forbidGlobal=Non permitir scripts globalmente (aconsellado)
+allowLocal=Permitir %S
+allowTemp=Permitir temporalmente %S
+forbidLocal=Non permitir %S
+allowed.glb=Perigo! Scripts permitidos globalmente
+allowed.yes=Scripts permitidos actualmente
+allowed.prt=Scripts parcialmente permitidos
+allowed.no=Scripts non permitidos actualmente
+global.warning.title=Ollo!
+global.warning.text=Os scripts van ser permitidos de xeito global (para cada áxina web).\n Esta é unha acción potencialmente perigosa.\n Estás seguro de querer facelo?
+audio.samples=Mostras de audio
+confirm=Estás seguro?
+alwaysAsk=Pedir sempre confirmación
+notifyHide=Ocultar logo de %S segundos
+trust=Confiar en %S
+distrust=Marcar %S como non fiábel
+untrustedOrigin=Unha orixe non confiábel
+xss.notify.generic=NoScript filtrou un intento potencias de cross-site scripting (XSS) dende %S. Os detalles técnicos foron almacenados na consola.
+xss.notify.showConsole=Amosar consola...
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Sanitized suspicious request. Original URL [%1$S] requested from [%2$S]. Sanitized URL: [%3$S].)
+xss.reason.filterXGetRef=Sanitized suspicious request referer. URL [%1$S] requested from [%2$S]. Sanitized Referrer: [%3$S].)
+xss.reason.filterXPost=Sanitized suspicious upload to [%1$S] from [%2$S]: transformed into a download-only GET request.
+unsafeReload.warning=UNSAFELY reloading a suspicious\n\n%1$S [%2$S]\n\nFROM [%3$S]\n\nNoScript will NOT protect this request!\n
+metaRefresh.notify=NoScript blocou unha redirección <META> dentro dun elemento <NOSCRIPT>: %S en %S segundos.
+metaRefresh.notify.follow=Seguir redirección
+metaRefresh.notify.follow.accessKey=F
+notify.options=Opcións
+notify.options.accessKey=O
+reset.title=NoScript Reset
+reset.warning=ALL the NoScript preferences and site permissions will be reset to their default values immediately.\nThis action cannot be reverted.\nDo you want to continue?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark's content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/he-IL/noscript/about.properties b/extensions/noscript/chrome/locale/he-IL/noscript/about.properties
new file mode 100644
index 0000000..3dd0f2f
--- /dev/null
+++ b/extensions/noscript/chrome/locale/he-IL/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=×”×’× ×” נוספת עבור ×”Ö¾Firefox שלך: NoScript מתיר ל־ â„¢JS, Java (ותוספות ×חרות) לפעול רק ×‘×ª×—×•×ž×™× ×ž×”×™×ž× ×™× ×¢×œ פי בחירתך (כגון: ×תר הבית של חשבון הבנק שלך). גישה זו מבוססת על "רשימת מותרי×" החוסמת מר×ש ×ת מה ש×ינו מורשה, מונעת ניצול של פרצות ×בטחה (×›×לה ×©×™×“×•×¢×™× ×•×פילו שעדיין ל×!) מבלי לגרוע בתיפקודיות הגלישה..! ×ž×•×ž×—×™× ×™×¡×›×™×ž×• ש־Firefox בטוח יותר ×¢× NoScript :-)
+aboutTitle=%S ×ודות
+extensionContributors=מתרגמי×:
+extensionContributors.tip=×× ×©×™× ×©×¦×¨×™×š להודות ×œ×”× ×¢×‘×•×¨ הרחבה זו
+extensionCreatorLabel=מחבר:
+changelog=יומן ×¨×™×©×•× ×©×œ שינויי×
+changelog.tip=הצג יומן ×¨×™×©×•× ×©×œ שינויי×
+license=רשיון
+license.tip=×§×¨× ×ת ×”×¡×›× ×”×¨×©×™×•×Ÿ למשתמש קצה
+logo.tip=בקר בדף הבית של ההרחבה
+sponsor.tip=בקר בדף הבית של המפרס×
+informaction.tip=בקר בדף הבית של חברת InformAction
+extensionHomepage.tip=בקר בדף הבית של ההרחבה
+extensionCreator.tip=בקר בדף הבית של מחבר ההרחבה
+version=גירסה %S
diff --git a/extensions/noscript/chrome/locale/he-IL/noscript/noscript.dtd b/extensions/noscript/chrome/locale/he-IL/noscript/noscript.dtd
new file mode 100644
index 0000000..a889914
--- /dev/null
+++ b/extensions/noscript/chrome/locale/he-IL/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "הגדרות...">
+<!ENTITY noscriptOptions.accesskey "">
+<!ENTITY noscriptOptionsLong "NoScript הגדרות של">
+<!ENTITY noscriptAbout "×ודות NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "ציין ×ילו ××ª×¨×™× ×™×›×•×œ×™× ×œ×§×‘×œ היתר להפעלת קבצי Script. הקלד ×ת כתובת ×”×תר ×ו ×ת ×©× ×”×ª×—×•× (כגון: &quot;http://www.site.com&quot; ×ו &quot;site.com&quot;) ול×חר מכן לחץ על התר.">
+<!ENTITY noscriptWebAddress "כתובת/תחו×:">
+<!ENTITY noscriptAllow "התר">
+<!ENTITY noscriptAllow.accesskey "">
+<!ENTITY noscriptForbid "×סור">
+<!ENTITY noscriptForbid.accesskey "">
+<!ENTITY noscriptTrust "סמן כמהימן">
+<!ENTITY noscriptTrust.accesskey "">
+<!ENTITY noscriptUntrust "סמן ×›×œ× ×ž×”×™×ž×Ÿ">
+<!ENTITY noscriptUntrust.accesskey "">
+<!ENTITY noscriptRemoveSelected "הסר">
+<!ENTITY noscriptGloballyEnabled "קבצי Script ×ž×•×ª×¨×™× ×‘×ופן כללי (×œ× ×ž×•×ž×œ×¥)">
+<!ENTITY noscriptAutoReload "טען מחדש ×“×¤×™× ×©×ž×•×©×¤×¢×™× ×‘×¢×ª שינוי הרש×ות ב×ופן עצמי">
+<!ENTITY noscriptGeneral "כללי">
+<!ENTITY noscriptAppearance "תצוגה">
+<!ENTITY noscriptShow "הצג...">
+<!ENTITY noscriptCtxMenu "תפריט הקשר">
+<!ENTITY noscriptStatusIcon "סמל שורת מצב">
+<!ENTITY noscriptFullAddr "כתובות מל×ות (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "×ª×—×•×ž×™× ×ž×œ××™× (www.noscript.net)">
+<!ENTITY noscriptBaseDom "תחומי בסיס ברמה שנייה (noscript.net)">
+<!ENTITY noscriptTempCmd "התר ב×ופן זמני [...]">
+<!ENTITY noscriptSound "הפעל צליל משוב ×›×שר קבצי Script נחסמי×">
+<!ENTITY noscriptImport "יבו×">
+<!ENTITY noscriptImport.accesskey "">
+<!ENTITY noscriptExport "יצו×">
+<!ENTITY noscriptExport.accesskey "">
+<!ENTITY noscriptNotify "הצג הודעה ×ודות קבצי Script חסומי×">
+<!ENTITY noscriptNotify.bottom "×ž×§× ×”×•×“×¢×•×ª בתחתית הדף">
+<!ENTITY noscriptSound.choose "עיון...">
+<!ENTITY noscriptSound.choose.accesskey "">
+<!ENTITY noscriptSound.play "נגן">
+<!ENTITY noscriptSound.play.accesskey "">
+<!ENTITY noscriptSound.reset "×יפוס">
+<!ENTITY noscriptSound.reset.accesskey "">
+<!ENTITY noscriptAdvanced "מתקד×">
+<!ENTITY noscriptAdditionalPermissions "הרש×ות נוספות ב××ª×¨×™× ×ž×”×™×ž× ×™×">
+<!ENTITY noscriptAllowClipboard "×פשר העתקה והדבקה של מלל עשיר מ×חסון זכרון חיצוני">
+<!ENTITY noscriptAdditionalRestrictions "הגבלות נוספות ב××ª×¨×™× ×©××™× × ×ž×”×™×ž× ×™×">
+<!ENTITY noscriptPlugins "תוספי×">
+<!ENTITY noscriptContentBlocker "החל הגבלות ×לו ×’× ×¢×œ ××ª×¨×™× ×ž×”×™×ž× ×™×">
+<!ENTITY noscriptForbidJava "מנע ™Java">
+<!ENTITY noscriptForbidXSLT "מנע XSLT">
+<!ENTITY noscriptForbidSilverlight "מנע ™Silverlight">
+<!ENTITY noscriptForbidIFrames "מנע &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "מנע &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "מנע @font-face">
+<!ENTITY noscriptForbidWebGL "×סור על WebGL">
+<!ENTITY noscriptForbidMedia "מנע &lt;AUDIO&gt;/&lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "מנע ®Flash">
+<!ENTITY noscriptForbidPlugins "מנע ×ª×•×¡×¤×™× ×חרי×">
+<!ENTITY noscriptReloadWarn "×פשרויות ×לה ישפיעו על ×“×¤×™× ×—×“×©×™× ×ו על ×›×לה שיטענו מחדש ב×ופן ידני">
+<!ENTITY noscriptConfirmUnblock "בקש ×ישור לפני ביטול חסימה של רכיב ב×ופן זמני">
+<!ENTITY noscriptStatusLabel "כותרת שורת מצב">
+<!ENTITY noscriptForbidBookmarklets "מנע יישומי סימניה">
+<!ENTITY noscriptShowPlaceholder "הצג סמל כתחליף">
+<!ENTITY noscriptTruncateTitle "חתוך ×ת הכותרות במסמך">
+<!ENTITY noscriptFixLinks "נסה לתקן ×§×™×©×•×¨×™× ×©×œ JS">
+<!ENTITY noscriptAllowBookmarks "×פשר ××ª×¨×™× ×©× ×¤×ª×—×™× ×“×¨×š הסימניות">
+<!ENTITY noscriptAllowViaBookmarks "×פשר ××ª×¨×™× ×©× ×¤×ª×—×™× ×“×¨×š הסימניות">
+<!ENTITY noscriptAllowPing "התר &lt;...A PING&gt;">
+<!ENTITY noscriptAllowLocalLinks "התר ×§×™×©×•×¨×™× ×ž×§×•×ž×™×™×">
+<!ENTITY noscriptForbidPing "מנע &lt;...A PING&gt;">
+<!ENTITY noscriptForbidMetaRefresh "מנע ניתוב מחודש של META ×‘×¨×›×™×‘×™× ×©×œ &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "">
+<!ENTITY noscriptWhitelist "היתרי×">
+<!ENTITY noscriptPermissions "הרש×ות">
+<!ENTITY noscriptRefresh "רענן מחדש">
+<!ENTITY noscriptNotifications "הודעות">
+<!ENTITY noscriptToolbarToggle "לחיצה שמ×לית על לחצן סרגל ×›×œ×™× ×©×œ NoScript תשנה מצב הרש×ות עבור ×תר ר×שי נוכחי">
+<!ENTITY noscriptTrusted "מהימן">
+<!ENTITY noscriptUntrusted "×œ× ×ž×”×™×ž×Ÿ">
+<!ENTITY noscriptUnknown "×œ× ×™×“×•×¢">
+<!ENTITY noscriptAdd "הוסף">
+<!ENTITY noscriptAdd.accesskey "">
+<!ENTITY noscriptClose "סגור">
+<!ENTITY noscriptSiteManager "מנהל ×תר">
+<!ENTITY noscriptSecurityManager "מנהל ×בטחה">
+<!ENTITY noscriptPolicies "מדיניות">
+<!ENTITY noscriptDefaultPolicies "מדיניות ברירת מחדל">
+<!ENTITY noscriptSitePolicies "מדיניות מפורשת של ×תר">
+<!ENTITY noscriptNselNever "הסתר ×¨×›×™×‘×™× ×©×œ &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "הצג רכיב &lt;NOSCRIPT&gt; ×©×‘× ×חרי &lt;SCRIPT&gt; חסו×.">
+<!ENTITY noscriptAutoAllowTopLevel "התר ××ª×¨×™× ×¨××©×™×™× ×‘×ופן זמני כברירת מחדל">
+<!ENTITY noscriptDescription "×”×’× ×” נוספת עבור ×”Ö¾Firefox שלך: NoScript מתיר ל־ â„¢JS, Java (ותוספות ×חרות) לפעול רק ×‘×ª×—×•×ž×™× ×ž×”×™×ž× ×™× ×¢×œ פי בחירתך (כגון: ×תר הבית של חשבון הבנק שלך). גישה זו מבוססת על &quot;רשימת מותרי×&quot; החוסמת מר×ש ×ת מה ש×ינו מורשה, מונעת ניצול של פרצות ×בטחה (×›×לה ×©×™×“×•×¢×™× ×•×פילו שעדיין ל×!) מבלי לגרוע בתיפקודיות הגלישה..! ×ž×•×ž×—×™× ×™×¡×›×™×ž×• ש־Firefox בטוח יותר ×¢× NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "×—×¡×•× ×¡×•×¨×§×™× ×ž×‘×•×¡×¡×™ CSS">
+<!ENTITY noscriptOptFilterXGet "הסר בקשות צד שלישי חשודות בין ×תרי×">
+<!ENTITY noscriptOptFilterXPost "הפוך בקשות POST של ××ª×¨×™× ×ž×¦×“ שלישי לבקשות GET ×œ×œ× × ×ª×•× ×™× × ×œ×•×•×™×">
+<!ENTITY noscriptShowConsole "הצג מסוף...">
+<!ENTITY noscriptShowConsole.accesskey "">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "ש×לות נפוצות ×‘× ×•×©× XSS...">
+<!ENTITY noscriptXssFaq.accesskey "ל">
+<!ENTITY noscriptUnsafeReload "טעינה מחדש ×œ× ×‘×˜×•×—×”">
+<!ENTITY noscriptUnsafeReload.accesskey "">
+<!ENTITY noscriptXssExceptions "הגנת Anti-XSS ליוצ××™× ×ž×Ÿ הכלל">
+<!ENTITY noscriptXssExceptions.description "×™×¢×“×™× ×”×ª×•××ž×™× ×œ×‘×™×˜×•×™×™× ×¨×’×™×œ×™× ×לה ×œ× ×™×”×™×• ×ž×•×’× ×™× ×ž×¤× ×™ XSS.">
+<!ENTITY noscriptMatchSample "דוגמה התו×מת לתבנית:">
+<!ENTITY noscriptReset "×יפוס">
+<!ENTITY noscriptReset.accesskey "">
+<!ENTITY noscriptResetDef "×פס להגדרות ברירת מחדל">
+<!ENTITY noscriptResetDef.accesskey "">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "בטל הרש×ות זמניות">
+<!ENTITY noscriptRevokeTemp.accesskey "">
+<!ENTITY noscriptNoUntrustedPlaceholder "×ל תציג מצייני ×ž×™×§×•× ×¢×‘×•×¨ ×¨×›×™×‘×™× ×”×ž×’×™×¢×™× ×ž××ª×¨×™× ×©×¡×•×ž× ×• ×›×œ× ×ž×”×™×ž× ×™×">
+<!ENTITY noscriptCollapseBlockedObjects "×¦×ž×¦× ×¨×›×™×‘×™× ×—×¡×•×ž×™×">
+<!ENTITY noscriptExceptions "חריגי×...">
+<!ENTITY noscriptBlockedObjects "×¨×›×™×‘×™× ×—×¡×•×ž×™×">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "×—×¡×•× ×›×œ רכיב שמגיע מ×תר המסומן ×›×œ× ×ž×”×™×ž×Ÿ">
+<!ENTITY noscriptTempAllowPage "זמנית התר ×ת כל הדף ×–×”">
+<!ENTITY noscriptTempAllowPage.accesskey "">
+<!ENTITY noscriptAllowPage "התר ×ת כל הדף ×–×”">
+<!ENTITY noscriptAllowPage.accesskey "">
+<!ENTITY noscriptTempToPerm "הפוך הרש×ות בדף לקבועות">
+<!ENTITY noscriptTempToPerm.accesskey "">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "ש×לות נפוצות ×‘× ×•×©× HTTPS...">
+<!ENTITY noscriptHttpsFaq.accesskey "">
+<!ENTITY noscriptHttps.behavior "התנהגות">
+<!ENTITY noscriptHttps.cookies "קבצי Cookie">
+<!ENTITY noscriptHttps.description "מנע תוכן רשת פעיל, ××œ× ×× ×›×Ÿ ×”×•× ×ž×’×™×¢ מחיבור מ×ובטח (HTTPS):">
+<!ENTITY noscriptHttps.never "××£ פע×">
+<!ENTITY noscriptHttps.proxy "בעת שימוש ב־proxy (מומלץ ×¢× Tor)">
+<!ENTITY noscriptHttps.always "תמיד">
+<!ENTITY noscriptHttpsForced "כפה ×ת ×”××ª×¨×™× ×”×‘××™× ×œ×¢×©×•×ª שימוש בחיבור מ×ובטח (HTTPS):">
+<!ENTITY noscriptHttpsForcedExceptions "×ל תכפה שימוש בחיבור מ×ובטח (HTTPS) עבור ×”××ª×¨×™× ×”×‘××™×:">
+<!ENTITY noscriptSecureCookies "×פשר ניהול עצמי של קבצי Cookie מ×ובטחי×">
+<!ENTITY noscriptSecureCookiesForced "כפה הצפנה עבור כל קבצי ×”Ö¾Cookies שנקבעו ×¢&quot;×™ חיבור HTTPS ב××ª×¨×™× ×”×‘××™×:">
+<!ENTITY noscriptSecureCookiesExceptions "×”×ª×¢×œ× ×ž×§×‘×¦×™ Cookie ×œ× ×‘×˜×•×—×™× ×©× ×§×‘×¢×• ×¢&quot;×™ חיבור HTTPS ב××ª×¨×™× ×”×‘××™×:">
+<!ENTITY noscriptClearClickTitle "הזהר מפני ClearClick">
+<!ENTITY noscriptClearClickHeader "Clickjacking ×פשרי/ניסיון תיקון ממשק המשתמש!">
+<!ENTITY noscriptClearClickDescription "NoScript מעכב ×ת פעולת הגומלין של העכבר ×ו המקלדת ×¢× ×¨×›×™×‘ מוסתר ב×ופן חלקי. לחץ על התמונה שלהלן כדי לעבור בין הרכיב ×”×—×¡×•× ×œ×’×™×¨×¡×” הברורה שלו.">
+<!ENTITY noscriptClearClickOpt "הגנה מפני ClearClick">
+<!ENTITY noscriptClearClickReport "דווח">
+<!ENTITY noscriptClearClickReport.accesskey "">
+<!ENTITY noscriptClearClickReportId "מזהה דוח:">
+<!ENTITY noscriptTrustedPagesAdj "מהימן">
+<!ENTITY noscriptUntrustedPagesAdj "×œ× ×ž×”×™×ž×Ÿ">
+<!ENTITY noscriptKeepLocked "שמור על רכיב זה נעול (מומלץ)">
+<!ENTITY noscriptEmbeddings "רכיבי×">
+<!ENTITY noscriptPrev "הקוד×">
+<!ENTITY noscriptNext "הב×">
+<!ENTITY noscriptFrameOptErr.title "×ין ×פשרות להציג תוכן ×–×” במסגרת">
+<!ENTITY noscriptFrameOptErr.desc "כדי להגן על ×”×בטחה שלך, ×”×ž×•×¦×™× ×œ×ור של תוכן ×–×” ×ינו מ×פשר ×©×”×•× ×™×•×¦×’ במסגרת.">
+<!ENTITY noscriptFrameOptErr.link "לחץ ×›×ן כדי לפתוח תוכן ×–×” בחלון חדש">
+<!ENTITY noscriptBookmarkSync "גבה הגדרות של NoScript בסימניה עבור סנכרון קל">
+<!ENTITY noscriptNotifyMeta "הצג הודעה ×ודות ניתוב מחודש של META חסו×">
+<!ENTITY noscriptNotifyMeta.accesskey "">
+<!ENTITY noscriptShowReleaseNotes "הצג הערות שחרור ל×חר כל עדכון של NoScript">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "ערכת כללי×:">
+<!ENTITY ABE.enabled.label "×פשר ×ת ABE (×כיפת גבולות יישו×)">
+<!ENTITY ABE.siteEnabled.label "×פשר ל××ª×¨×™× ×œ×“×—×•×£ ×ת ערכת ×”×›×œ×œ×™× ×©×œ×”×">
+<!ENTITY ABE.edit.label "ערוך...">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "התר">
+<!ENTITY ABE.enable.accesskey "">
+<!ENTITY ABE.disable.label "מנע">
+<!ENTITY ABE.disable.accesskey "">
+<!ENTITY ABE.refresh.label "רענן">
+<!ENTITY ABE.refresh.accesskey "">
+<!ENTITY noscriptUninstall "הסר">
+<!ENTITY noscriptRecentBlocked "××ª×¨×™× ×©× ×—×¡×ž×• ל×חרונה">
+<!ENTITY noscriptExternalFilters "מסנני×">
+<!ENTITY noscriptEF.enable "×פשר ×ž×¡× × ×™× ×—×™×¦×•× ×™×™×">
+<!ENTITY noscriptEF.add "מסנן חדש...">
+<!ENTITY noscriptEF.executable "קובץ הפעלה:">
+<!ENTITY noscriptEF.browse "עיון...">
+<!ENTITY noscriptEF.contentType "סוג תוכן MIME שיסונן ×¢&quot;×™ הת×מה מדויקת ×ו ביטוי רגיל:">
+<!ENTITY noscriptEF.exceptions "×ל תסנן ×¨×›×™×‘×™× ×©×‘××™× ×ž××ª×¨×™× ×לה:">
+<!ENTITY noscriptEF.remove "הסר">
+<!ENTITY noscriptPreset "רמת ×בטחה">
+<!ENTITY noscriptPreset.off "כבוי (×תה רציני?!)">
+<!ENTITY noscriptPreset.low "מעבר קל (רשימה ×סורה + ×בטחת רשת)">
+<!ENTITY noscriptPreset.medium "קל×סי (רשימה מותרת + ×בטחת רשת)">
+<!ENTITY noscriptPreset.high "מבצר (נעילה מל××”)">
+<!ENTITY noscript.hoverUI "פתח ×ת תפריט ההרש×ות בעת הצבת מצביע העכבר מעל הסמל של NoScript">
+<!ENTITY noscriptDonate "תרו×">
+<!ENTITY noscriptDonate.accesskey "">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/he-IL/noscript/noscript.properties b/extensions/noscript/chrome/locale/he-IL/noscript/noscript.properties
new file mode 100644
index 0000000..a19a530
--- /dev/null
+++ b/extensions/noscript/chrome/locale/he-IL/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=התר קבצי Script מכל ×תר (×œ× ×ž×•×ž×œ×¥)
+forbidGlobal=מנע קבצי Script מכל ×תר (מומלץ)
+allowLocal=התר ×ת %S
+allowTemp=זמנית התר ×ת %S
+forbidLocal=מנע ×ת %S
+allowed.glb=×זהרה! קבצי Script ×ž×•×ª×¨×™× ×‘×›×œ ×תר
+allowed.yes=קבצי Script ×ž×•×ª×¨×™× ×›×¢×ª
+allowed.prt=קבצי Script ×ž×¡×•×™×ž×™× ×ž×•×ª×¨×™×
+allowed.no=קבצי Script ××¡×•×¨×™× ×›×¢×ª
+global.warning.title=×זהרה!
+global.warning.text=מעתה יותרו קבצי Script מכל ×תר.\nייתכן שיש בכך סיכון.\n×”×× ×‘×¨×¦×•× ×š לעשות ×–×ת?
+audio.samples=דגימות שמע
+confirm=×”×× ×œ×‘×¦×¢?
+alwaysAsk=בקש תמיד ×ישור
+notifyHide=הסתר ×חרי %S שניות
+trust=סמוך על %S
+distrust=×ל תסמוך על %S
+untrustedOrigin=מקור ×œ× ×מין
+xss.notify.generic=NoScript סינן נסיון להרצת קבצי Script של צד שלישי (XSS) מה×תר %S. ×¤×¨×˜×™× ×©×™×ž×•×©×™×™× ×™×•×¤×™×¢×• במסוף.
+xss.notify.showConsole=הצג מסוף...
+xss.notify.showConsole.accessKey=מ
+xss.reason.filterXGet=בקשה חשודה סוננה. ה-URL המקורי: [%1$S] שהופעל מתוך [%2$S]. ה-URL המסונן: [%3$S].
+xss.reason.filterXGetRef=מקור הפניה חשוד לבקשה סונן. ×”-URL [%1$S] שהופעל מתוך [%2$S]. מקור ההפניה ל×חר סינון: [%3$S].
+xss.reason.filterXPost=ההעל××” החשודה ×ל [%1$S] מ×ת [%2$S] סוננה: ×”×™× ×ולצה להפוך לבקשת GET בלי העל×ת נתוני×
+unsafeReload.warning=טוען מחדש ב×ופן *בלתי בטוח*nn%1$S[%2$S]\n\nמה×תר [%3$S]\n\nנוסקריפט *ל×* יגן על הבקשה הזו!\n
+metaRefresh.notify=NoScript ×—×¡× ×”×¤× ×™×™×ª META בתוך תגית NOSCRIPT: %S בזמן של %S שניות.
+metaRefresh.notify.follow=בצע הפניות
+metaRefresh.notify.follow.accessKey=×¢
+notify.options=×פשרויות
+notify.options.accessKey=×
+reset.title=×יפוס NoScript להגדרות ברירת מחדל
+reset.warning=הגדרות NoScript ורשימת הרש×ות ×™×ופסו למצב ברירת המחדל.\n×œ× ×œ×™×ª×Ÿ לבטל פעולה זו ולחזור למצב הקוד×.\n×”×× ×‘×¨×¦×•× ×š להמשיך?
+bookmarkSync.title=NoScript תצורת הסימניה של
+bookmarkSync.message=סימניה זו ××™× ×” ×מורה להיפתח, ××œ× × ×•×¢×“×” להיות מסונכרת ב×מצעות שירות, כגון: Weave ×ו ×¢"×™ הרחבת Xmarks.
+bookmarkSync.confirm=NoScript ×ž×¦× ×¡×™×ž× ×™×ª תצורה שלכ×ורה שמורה ב \n%S.\n ×”×× ×‘×¨×¦×•× ×š להחליף ×ת תצורת ×”- NoScript המקומי שלך ×¢× ×ª×•×›×Ÿ סימניה זו?
+ABE.notify=בקשת% 1 $ S ×ž×¡×•× × ×™× ×¢"×™ ABE: <% 2 $ S>% 3 $ S
+ABE.chooseEditor=×× × ×‘×—×¨ עורך טקסט עבור ערכת ×›×œ×œ×™× ×©×œ ABE
+ABE.syntaxError=שגי×ת תחביר בערכת ×›×œ×œ×™× ×©×œ ABE
+ABE.wanIpAsLocal=(WAN IP (%S ∈ מקומי
+allowFrom=התר הכל מ־ %S
+allowTempFrom=זמנית התר הכל מ־ %S
+siteInfo.confirm=הינך עומד לבקש מידע ×ודות ' %1$ S ' ב×תר ×¢"×™ שליחת ש×ילתה %2$S ×”×× ×‘×¨×¦×•× ×š להמשיך?
+siteInfo.tooltip=לחיצה ×מצעית ×ו על shift + לחיצה לצורך מידע ב×תר...
+ef.activate=סנן %S
+ef.options=%S ×פשרויות...
+ef.newName=הזן ×ת ×©× ×”×ž×¡× ×Ÿ החדש:
+ef.locateExe=בחר ×ת קובץ ההפעלה עבור מסנן ×”-S%
+disable=בטל %S
+disable.accessKey=ב
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/hr-HR/noscript/about.properties b/extensions/noscript/chrome/locale/hr-HR/noscript/about.properties
new file mode 100644
index 0000000..8de6ff0
--- /dev/null
+++ b/extensions/noscript/chrome/locale/hr-HR/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Dodatna zaÅ¡tita za VaÅ¡ Firefox: NoScript dopuÅ¡ta JavaScript, Java (i druge dodatke) samo za provjerene domene VaÅ¡eg izbora (npr. VaÅ¡a stranica Intenet bankarstva) . Ovaj pristup preventivnog blokiranja zasnovan na popisu dopuÅ¡tenih sprijeÄava iskoriÅ¡tavanje sigurnosnih slabosti (znanih i neznanih) bez ikakvog gubitka funkcionalnosti... StruÄnjaci će se složiti: Firefox je zbilja sigurniji s NoScript :-)
+aboutTitle=O %S
+extensionContributors=Oni koji su doprinjeli:
+extensionContributors.tip=Ljudi kojima trebate zahvaliti na ovom proširenju
+extensionCreatorLabel=Autor:
+changelog=Popis promjena
+changelog.tip=Prikaži popis promjena
+license=Licenca
+license.tip=ProÄitajte licencu za krajnjeg korisnika
+logo.tip=Posjetite poÄetnu stranicu proÅ¡irenja
+sponsor.tip=Posjetite pokroviteljevu poÄetnu stranicu
+informaction.tip=Posjetite poÄetnu stranicu InformAction-a
+extensionHomepage.tip=Posjetite poÄetnu stranicu proÅ¡irenja
+extensionCreator.tip=Posjetite autorovu poÄetnu stranicu
+version=Version %S
diff --git a/extensions/noscript/chrome/locale/hr-HR/noscript/noscript.dtd b/extensions/noscript/chrome/locale/hr-HR/noscript/noscript.dtd
new file mode 100644
index 0000000..00d9813
--- /dev/null
+++ b/extensions/noscript/chrome/locale/hr-HR/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opcije...">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript Opcije">
+<!ENTITY noscriptAbout "O NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Možete odrediti koje web stranice imaju dopuštenje za izvođenje skripti. Upišite adresu ili domenu (npr. &quot;http://www.stranica.hr&quot; ili &quot;stranica.hr&quot;) stranice kojoj želite dopustiti i kliknite na Dopusti.">
+<!ENTITY noscriptWebAddress "Adresa web stranice:">
+<!ENTITY noscriptAllow "Dopusti">
+<!ENTITY noscriptAllow.accesskey "D">
+<!ENTITY noscriptForbid "Zabrani">
+<!ENTITY noscriptForbid.accesskey "b">
+<!ENTITY noscriptTrust "OznaÄi kao provjereno">
+<!ENTITY noscriptTrust.accesskey "v">
+<!ENTITY noscriptUntrust "OznaÄi kao neprovjereno">
+<!ENTITY noscriptUntrust.accesskey "e">
+<!ENTITY noscriptRemoveSelected "Ukloni oznaÄene stranice">
+<!ENTITY noscriptGloballyEnabled "Skripte su općenito dopuštene (opasno)">
+<!ENTITY noscriptAutoReload "Automatski ponovno uÄitaj obuhvaćene stranice nakon promjene dopuÅ¡tenja">
+<!ENTITY noscriptGeneral "Općenito">
+<!ENTITY noscriptAppearance "Izgled">
+<!ENTITY noscriptShow "Prikaži...">
+<!ENTITY noscriptCtxMenu "Kontekstni izbornik">
+<!ENTITY noscriptStatusIcon "Ikonu u statusnoj traci">
+<!ENTITY noscriptFullAddr "Puna adresa (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Puna domena (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Osnovne domene drugog nivoa (noscript.net)">
+<!ENTITY noscriptTempCmd "Privremeno dopusti [...]">
+<!ENTITY noscriptSound "ZvuÄni signal kada su skripte blokirane">
+<!ENTITY noscriptImport "Uvezi">
+<!ENTITY noscriptImport.accesskey "U">
+<!ENTITY noscriptExport "Izvezi">
+<!ENTITY noscriptExport.accesskey "I">
+<!ENTITY noscriptNotify "Prikaži poruku o blokiranim skriptama">
+<!ENTITY noscriptNotify.bottom "Prikaži poruku pri dnu">
+<!ENTITY noscriptSound.choose "Izaberi">
+<!ENTITY noscriptSound.choose.accesskey "z">
+<!ENTITY noscriptSound.play "Pusti">
+<!ENTITY noscriptSound.play.accesskey "P">
+<!ENTITY noscriptSound.reset "Vrati zadano">
+<!ENTITY noscriptSound.reset.accesskey "r">
+<!ENTITY noscriptAdvanced "Napredno">
+<!ENTITY noscriptAdditionalPermissions "Dodatna dopuštenja za provjerene stranice">
+<!ENTITY noscriptAllowClipboard "Dopusti kopiranje i lijepljenje obogaćenog teksta iz vanjskog međuspremnika">
+<!ENTITY noscriptAdditionalRestrictions "Dodatna ograniÄenja za neprovjerene stranice">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Apply these restrictions to trusted sites too">
+<!ENTITY noscriptForbidJava "Zabrani Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Zabrani XSLT">
+<!ENTITY noscriptForbidSilverlight "Zabrani Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Zabrani &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Zabrani &lt;FRAMES&gt;">
+<!ENTITY noscriptForbidFonts "Zabraniti @font-face">
+<!ENTITY noscriptForbidWebGL "Zabraniti WebGL">
+<!ENTITY noscriptForbidMedia "Zabraniti &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Zabrani Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Zabrani druge dodatke">
+<!ENTITY noscriptReloadWarn "Ove postavke će imati uÄinka na novim ili (ruÄno) ponovno uÄitanim stranicama">
+<!ENTITY noscriptConfirmUnblock "Pitaj za potvrdu prije privremenog deblokiranja objekta">
+<!ENTITY noscriptStatusLabel "Naziv u statusnoj traci">
+<!ENTITY noscriptForbidBookmarklets "Zabrani bookmarklete">
+<!ENTITY noscriptShowPlaceholder "Prikaži ikonu za držanje položaja">
+<!ENTITY noscriptTruncateTitle "Odsijeci naslove dokumenta">
+<!ENTITY noscriptFixLinks "Pokušaj popraviti poveznice JavaScripta">
+<!ENTITY noscriptAllowBookmarks "Dopusti stranice koje su otvorene putem zabilješki">
+<!ENTITY noscriptAllowViaBookmarks "Dopusti stranice koje su otvorene putem zabilješki">
+<!ENTITY noscriptAllowPing "Dopusti &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Dopusti lokalne poveznice">
+<!ENTITY noscriptForbidPing "Zabrani &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Forbid META redirections inside &lt;NOSCRIPT&gt; elements">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "Pokazati poruku u vezi s blokiranim META-redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "Popis dopuštenih">
+<!ENTITY noscriptPermissions "Dopuštenja">
+<!ENTITY noscriptRefresh "Osvježi">
+<!ENTITY noscriptNotifications "Obavijesti">
+<!ENTITY noscriptToolbarToggle "Lijevom klikom na NoScript gumb alatne trake mijenjate dopuštenja za trenutnu vršnu stranicu">
+<!ENTITY noscriptTrusted "Pouzdane">
+<!ENTITY noscriptUntrusted "Nepouzdane">
+<!ENTITY noscriptUnknown "Nepoznato">
+<!ENTITY noscriptAdd "Dodaj">
+<!ENTITY noscriptAdd.accesskey "D">
+<!ENTITY noscriptClose "Zatvori">
+<!ENTITY noscriptSiteManager "Upravitelj stranicom">
+<!ENTITY noscriptSecurityManager "Upravitelj sigurnosti">
+<!ENTITY noscriptPolicies "Police">
+<!ENTITY noscriptDefaultPolicies "Zadane police">
+<!ENTITY noscriptSitePolicies "SpecifiÄne police stranice">
+<!ENTITY noscriptNselNever "Sakrij &lt;NOSCRIPT&gt; elemente">
+<!ENTITY noscriptNselForce "Prikaži &lt;NOSCRIPT&gt; elemente koji slijede blokirane &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Privremeno kao zadano dopusti vršne stranice">
+<!ENTITY noscriptDescription "Dodatna zaÅ¡tita za VaÅ¡ Firefox: NoScript dopuÅ¡ta JavaScript, Java (i druge dodatke) samo za provjerene domene VaÅ¡eg izbora (npr. VaÅ¡a stranica Intenet bankarstva) . Ovaj pristup preventivnog blokiranja zasnovan na popisu dopuÅ¡tenih sprijeÄava iskoriÅ¡tavanje sigurnosnih slabosti (znanih i neznanih) bez ikakvog gubitka funkcionalnosti... StruÄnjaci će se složiti: Firefox je zbilja sigurniji s NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Block CSS-based scanners">
+<!ENTITY noscriptOptFilterXGet "Sanitize cross-site suspicious requests">
+<!ENTITY noscriptOptFilterXPost "Turn cross-site POST requests into data-less GET requests">
+<!ENTITY noscriptShowConsole "Show Console...">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Unsafe Reload">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Anti-XSS Protection Exceptions">
+<!ENTITY noscriptXssExceptions.description "Destinations matching these regular expressions will NOT be protected against XSS">
+<!ENTITY noscriptMatchSample "Pattern matching sample:">
+<!ENTITY noscriptReset "Reset">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Reset to defaults">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revoke Temporary Permissions">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "No placeholder for objects coming from sites marked as untrusted">
+<!ENTITY noscriptCollapseBlockedObjects "Collapse blocked objects">
+<!ENTITY noscriptExceptions "Exceptions...">
+<!ENTITY noscriptBlockedObjects "Blocked Objects">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Block every object coming from a site marked as untrusted">
+<!ENTITY noscriptTempAllowPage "Temporarily allow all this page">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Allow all this page">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Make page permissions permanent">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "ÄŒesto postavljena pitanja u vezi HTTPS-a">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Ponašanje">
+<!ENTITY noscriptHttps.cookies "KolaÄiće">
+<!ENTITY noscriptHttps.description "Zabraniti aktivni web-sadržaj ukoliko ne potjeÄe iz sigurne (HTTPS) konekcije">
+<!ENTITY noscriptHttps.never "Nikada">
+<!ENTITY noscriptHttps.proxy "Kada se koristi proxy (preporuÄeno sa Tor-om)">
+<!ENTITY noscriptHttps.always "Uvijek">
+<!ENTITY noscriptHttpsForced "Prisiliti sljedeće sajtove da koriste sigurnu (HTTPS) konekciju">
+<!ENTITY noscriptHttpsForcedExceptions "Nikada ne prisiliti korištenje sigurne (HTTPS) konekcije za sljedeće sajtove">
+<!ENTITY noscriptSecureCookies "Dozvoliti automatiÄnu upravu sigurnih kolaÄića">
+<!ENTITY noscriptSecureCookiesForced "Prisiliti enkripciju za sve kolaÄiće podeÅ¡ene preko HTTPS-a kod sljedećih sajta:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignorirati nesigurne kolaÄiće podeÅ¡ene preko HTTPS-a kod sljedećih sajta:">
+<!ENTITY noscriptClearClickTitle "ClearClick-upozorenje">
+<!ENTITY noscriptClearClickHeader "Mogući Clickjacking/UI Redressing napad">
+<!ENTITY noscriptClearClickDescription "NoScript je primjetio interakciju miša ili tastatura sa djelomićno sakrivenim elementom. Klikni na gornju sliku kako bi promjenio između zaklonjene i jasne verzije">
+<!ENTITY noscriptClearClickOpt "ClearClick-zaštita na stranicama...">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "pouzdane">
+<!ENTITY noscriptUntrustedPagesAdj "nepouzdane">
+<!ENTITY noscriptKeepLocked "Držati zakljuÄan ovaj elemenat (preporuÄeno)">
+<!ENTITY noscriptEmbeddings "Ugrađeni objekti">
+<!ENTITY noscriptPrev "Prethodni">
+<!ENTITY noscriptNext "Sljedeći">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptShowReleaseNotes "Pokazati informacije vezane za novo izdanje u slucaju azuriranja">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Skupovi pravila (rulesets):">
+<!ENTITY ABE.enabled.label "Ukljuciti ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Dozvoljiti sajtovima koristenje njihovih rulesets-a (skupovi pravila)">
+<!ENTITY ABE.edit.label "Modificirati...">
+<!ENTITY ABE.edit.accesskey "M">
+<!ENTITY ABE.enable.label "Ukljuciti">
+<!ENTITY ABE.enable.accesskey "u">
+<!ENTITY ABE.disable.label "Izkljuciti">
+<!ENTITY ABE.disable.accesskey "I">
+<!ENTITY ABE.refresh.label "Osvjeziti">
+<!ENTITY ABE.refresh.accesskey "O">
+<!ENTITY noscriptUninstall "Dezinstalirati">
+<!ENTITY noscriptRecentBlocked "Nedavno blokirane web stranice">
+<!ENTITY noscriptExternalFilters "Vanjski filteri">
+<!ENTITY noscriptEF.enable "Ukljuciti vanjski filteri">
+<!ENTITY noscriptEF.add "Novi Filter...">
+<!ENTITY noscriptEF.executable "Izvršni fajl...">
+<!ENTITY noscriptEF.browse "Pregledati...">
+<!ENTITY noscriptEF.contentType "Tocni MIME-tip sadrzaja ili regexp za filtriranje sadrzaja">
+<!ENTITY noscriptEF.exceptions "Ne filtrirati elemente iz sljedecih web stranica:">
+<!ENTITY noscriptEF.remove "Ukiniti">
+<!ENTITY noscriptPreset "Razina sigurnosti">
+<!ENTITY noscriptPreset.off "Izkljuciti (ozbiljno???)">
+<!ENTITY noscriptPreset.low "Easy going (Crna lista + web sigurnost)">
+<!ENTITY noscriptPreset.medium "Classic (Bijela lista + web sigurnost)">
+<!ENTITY noscriptPreset.high "Tvrðava (Kompletno blokiranje)">
+<!ENTITY noscript.hoverUI "Otvoriti meni dopustenja u slucaju mouseover-a nad NoScript ikonom">
+<!ENTITY noscriptDonate "Donacija">
+<!ENTITY noscriptDonate.accesskey "d">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/hr-HR/noscript/noscript.properties b/extensions/noscript/chrome/locale/hr-HR/noscript/noscript.properties
new file mode 100644
index 0000000..c746b7a
--- /dev/null
+++ b/extensions/noscript/chrome/locale/hr-HR/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Općenito dopusti skripte (opasno)
+forbidGlobal=Općenito zabrani skripte (preporuÄljivo)
+allowLocal=Dopusti: %S
+allowTemp=Privremeno dopusti: %S
+forbidLocal=Zabrani: %S
+allowed.glb=Opasnost! Skripte su općenito dopuštene
+allowed.yes=Skripte su trenutno dopuštene
+allowed.prt=Skripte su djelomiÄno dopuÅ¡tene
+allowed.no=Skripte su trenutno zabranjene
+global.warning.title=Upozorenje!
+global.warning.text=Skripte će biti općenito dopuštene (za svaku stranicu).\n Ovo je potencijalno opasna radnja.\nŽelite li doista nastaviti?
+audio.samples=ZvuÄni primjeri
+confirm=Sigurni ste?
+alwaysAsk=Uvijek pitaj za potvrdu
+notifyHide=Sakrij nakon %S sek
+trust=Dodaj u pouzdane %S
+distrust=OznaÄi %S kao nepouzdane
+untrustedOrigin=an untrusted origin
+xss.notify.generic=NoScript filtered a potential cross-site scripting (XSS) attempt from %S. Technical details have been logged to the Console.
+xss.notify.showConsole=Show Console...
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Sanitized suspicious request. Original URL [%1$S] requested from [%2$S]. Sanitized URL: [%3$S].
+xss.reason.filterXGetRef=Sanitized suspicious request referer. URL [%1$S] requested from [%2$S]. Sanitized Referrer: [%3$S].
+xss.reason.filterXPost=Sanitized suspicious upload to [%1$S] from [%2$S]: transformed into a download-only GET request.
+unsafeReload.warning=UNSAFELY reloading a suspicious\n\n%1$S [%2$S]\n\nFROM [%3$S]\n\nNoScript will NOT protect this request!\n
+metaRefresh.notify=NoScript blocked a <META> redirection inside a <NOSCRIPT> element: %S in %S seconds.
+metaRefresh.notify.follow=Follow Redirection
+metaRefresh.notify.follow.accessKey=F
+notify.options=Options
+notify.options.accessKey=O
+reset.title=NoScript Reset
+reset.warning=ALL the NoScript preferences and site permissions will be reset to their default values immediately.\nThis action cannot be reverted.\nDo you want to continue?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+bookmarkSync.confirm=NoScript je nasao configuracijski obiljezivac na\n%S.\nHocete li stvarno prepisati preko lokalne NoScript configuracije s sadrzajem ovog obiljezivaca?
+ABE.notify=Zahtjev %1$S filtriran od ABE: <%2$S> %3$S
+ABE.chooseEditor=Molimo birajte ureðivac teksta za ABE skupine pravila (rulesets)
+ABE.syntaxError=Sintaksni error u ABE pravilama (rulesets)
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Dopustiti sve iz %S
+allowTempFrom=Privremeno sve dopustiti iz %S
+siteInfo.confirm=Hocete li stvarno raspitati se za informaciju o sajtu \"%1$S\" \n predajuci zahtjev %2$S. -u?
+siteInfo.tooltip=Srednji-klik ili shift+klik za informaciju o web stranici...
+ef.activate=Filtrirati %S
+ef.options=%S opcije...
+ef.newName=Upisati ime novog filtera:
+ef.locateExe=Birati izvršni fajl za filtar %S
+disable=Izkljuciti %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/hsb/noscript/about.properties b/extensions/noscript/chrome/locale/hsb/noscript/about.properties
new file mode 100644
index 0000000..b5c321b
--- /dev/null
+++ b/extensions/noscript/chrome/locale/hsb/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Wosebity Å¡kit za waÅ¡ Firefox: NoScript dowola JavaScript, Java (a druhe tykaÄe) jenož za dowÄ›rliwe domeny waÅ¡eje wólby (na pÅ™. waÅ¡e websydÅ‚o za domjacne bankowanje). Tuta běła lisćina, kotraž na prewentiwnym pÅ™istupje k blokowanje bazÄ›ruje, zadźěwa znjewužiwanju wÄ›stotnych dźěrow (znatych a samo njeznatych!) bjez zhubjenja funkcionalnosće… Eksperća pÅ™izwola: Firefox je woprawdźe wÄ›sćiÅ¡i z NoScript :-)
+aboutTitle=Wo %S
+extensionContributors=Sobuskutkowacy:
+extensionContributors.tip=Ludźo, kotrymž wy měł so za tute rozšěrjenje dźakować
+extensionCreatorLabel=Awtor:
+changelog=Protokol změnow
+changelog.tip=Protokol změnow pokazać
+license=Licenca
+license.tip=Licencu za kónÄnych wužiwarjow Äitać
+logo.tip=Startowu stronu rozšěrjenja wopytać
+sponsor.tip=Startowu stronu sponsora wopytać
+informaction.tip=Startowu stronu InformAction wopytać
+extensionHomepage.tip=Startowu stronu rozšěrjenja wopytać
+extensionCreator.tip=Startowu stronu awtora wopytać
+version=Wersija %S
diff --git a/extensions/noscript/chrome/locale/hsb/noscript/noscript.dtd b/extensions/noscript/chrome/locale/hsb/noscript/noscript.dtd
new file mode 100644
index 0000000..fa97035
--- /dev/null
+++ b/extensions/noscript/chrome/locale/hsb/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opcije…">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Opcije NoScript">
+<!ENTITY noscriptAbout "Wo NoScript 5.1.8.5…">
+<!ENTITY noscriptPermissionsText "Móžeće podać, kotre websydła smědźa skripty wuwjesć. Zapisajće adresu abo domenu (na př. &quot;http://www.site.com&quot; abo &quot;site.com&quot;) websydła, kotremuž chceće to dowolić a klikńće potom na &quot;Dowolić&quot;.">
+<!ENTITY noscriptWebAddress "Adresa websydła:">
+<!ENTITY noscriptAllow "Dowolić">
+<!ENTITY noscriptAllow.accesskey "w">
+<!ENTITY noscriptForbid "Zakazać">
+<!ENTITY noscriptForbid.accesskey "Z">
+<!ENTITY noscriptTrust "Jako dowěry hódny markěrować">
+<!ENTITY noscriptTrust.accesskey "J">
+<!ENTITY noscriptUntrust "Jako dowěry njehódny markěrować">
+<!ENTITY noscriptUntrust.accesskey "N">
+<!ENTITY noscriptRemoveSelected "Wubrane sydła wotstronić">
+<!ENTITY noscriptGloballyEnabled "Skripty globalnje dowolene (riskantny)">
+<!ENTITY noscriptAutoReload "Potrjechene strony awtomatisce znowa zaÄitać, hdyž so prawa mÄ›njeja">
+<!ENTITY noscriptGeneral "Powšitkowny">
+<!ENTITY noscriptAppearance "Napohlad">
+<!ENTITY noscriptShow "Pokazać…">
+<!ENTITY noscriptCtxMenu "Kontekstowy meni">
+<!ENTITY noscriptStatusIcon "Wobrazk w statusowej lajsće">
+<!ENTITY noscriptFullAddr "Dospołne adresy (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Dospołne domeny (http://www.noscript.net)">
+<!ENTITY noscriptBaseDom "Domeny druheje runiny (noscript.net)">
+<!ENTITY noscriptTempCmd "[…] nachwilu dowolić">
+<!ENTITY noscriptSound "Zynk wothrać, hdyž so skripty blokuja">
+<!ENTITY noscriptImport "Importować">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Eksportować">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Zdźělenku wo zablokowanych skriptach pokazać">
+<!ENTITY noscriptNotify.bottom "Zdźělenku deleka zaměstnić">
+<!ENTITY noscriptSound.choose "Wubrać">
+<!ENTITY noscriptSound.choose.accesskey "W">
+<!ENTITY noscriptSound.play "Wothrać">
+<!ENTITY noscriptSound.play.accesskey "h">
+<!ENTITY noscriptSound.reset "Standard wobnowić">
+<!ENTITY noscriptSound.reset.accesskey "S">
+<!ENTITY noscriptAdvanced "Rozšěrjene">
+<!ENTITY noscriptAdditionalPermissions "Přidatne prawa za dowěry hódne sydła">
+<!ENTITY noscriptAllowClipboard "Zasunjenje RTF z eksterneho mjezyskłada dowolić">
+<!ENTITY noscriptAdditionalRestrictions "Přidatne wobmjezowanja za dowěry njehódne sydła">
+<!ENTITY noscriptPlugins "TykaÄe">
+<!ENTITY noscriptContentBlocker "Tute wobmjezowanja tež na sydła w běłej lisćinje nałožić">
+<!ENTITY noscriptForbidJava "Java™ zakazać">
+<!ENTITY noscriptForbidXSLT "XSLT zakazać">
+<!ENTITY noscriptForbidSilverlight "Microsoft® Silverlight™ zakazać">
+<!ENTITY noscriptForbidIFrames "&lt;IFRAME&gt; zakazać">
+<!ENTITY noscriptForbidFrames "&lt;FRAME&gt; zakazać">
+<!ENTITY noscriptForbidFonts "@font-face zakazać">
+<!ENTITY noscriptForbidWebGL "WebGL zakazać">
+<!ENTITY noscriptForbidMedia "&lt;AUDIO&gt;/&lt;VIDEO&gt; zakazać">
+<!ENTITY noscriptForbidFlash "Adobe® Flash® zakazać">
+<!ENTITY noscriptForbidPlugins "Druhe tykaÄe zakazać">
+<!ENTITY noscriptReloadWarn "Tute opcije budu so hakle pola nowych abo znowa zaÄitanych stronow wuskutkować">
+<!ENTITY noscriptConfirmUnblock "Wo wobkrućenje prosyć, prjedy haÄ so objekt nachwilu dowoli">
+<!ENTITY noscriptStatusLabel "Popis w statusowej lajsće">
+<!ENTITY noscriptForbidBookmarklets "Bookmarklety zakazać">
+<!ENTITY noscriptShowPlaceholder "Zastupniski wobrazk pokazać">
+<!ENTITY noscriptTruncateTitle "Titule dokumentow wobrězać">
+<!ENTITY noscriptFixLinks "Z JavaScriptom wutworjene wotkazy porjedźić spytać">
+<!ENTITY noscriptAllowBookmarks "SydÅ‚a woÄinjene pÅ™ez zapoÅ‚ožki dowolić">
+<!ENTITY noscriptAllowViaBookmarks "SydÅ‚a woÄinjene pÅ™ez zapoÅ‚ožki dowolić">
+<!ENTITY noscriptAllowPing "&lt;A PING...&gt; dowolić">
+<!ENTITY noscriptAllowLocalLinks "Lokalne wotkazy dowolić">
+<!ENTITY noscriptForbidPing "&lt;A PING...&gt; zakazać">
+<!ENTITY noscriptForbidMetaRefresh "Dalesposrědkowanja META znutřka elementach &lt;NOSCRIPT&gt; zakazać">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "T">
+<!ENTITY noscriptNotifyMeta "Zdźělenku wo zablokowanych META-dalesposrědkowanjach pokazać">
+<!ENTITY noscriptNotifyMeta.accesskey "T">
+<!ENTITY noscriptWhitelist "Běła lisćina">
+<!ENTITY noscriptPermissions "Prawa">
+<!ENTITY noscriptRefresh "Aktualizować">
+<!ENTITY noscriptNotifications "Zdźělenki">
+<!ENTITY noscriptToolbarToggle "Kliknjenje z lÄ›wej tastu na tłóÄatko NoScript w gratowej lajsće pÅ™epina prawa za aktualne sydÅ‚o najwyÅ¡eje runiny">
+<!ENTITY noscriptTrusted "Dowěry hódne">
+<!ENTITY noscriptUntrusted "Dowěry njehódne">
+<!ENTITY noscriptUnknown "Njeznaty">
+<!ENTITY noscriptAdd "Přidać">
+<!ENTITY noscriptAdd.accesskey "P">
+<!ENTITY noscriptClose "ZaÄinić">
+<!ENTITY noscriptSiteManager "Zrjadowak sydłow">
+<!ENTITY noscriptSecurityManager "Wěstotny zrjadowak">
+<!ENTITY noscriptPolicies "Prawidła">
+<!ENTITY noscriptDefaultPolicies "Standardne prawidła">
+<!ENTITY noscriptSitePolicies "Prawidła za specifiske sydła">
+<!ENTITY noscriptNselNever "Elementy &lt;NOSCRIPT&gt; schować">
+<!ENTITY noscriptNselForce "Element &lt;NOSCRIPT&gt; pokazać, kotryž zablokowanemu &lt;SCRIPT&gt; slěduje">
+<!ENTITY noscriptAutoAllowTopLevel "Po standardźe sydła najwyšeje runiny nachwilu dowolić">
+<!ENTITY noscriptDescription "Wosebity Å¡kit za waÅ¡ Firefox: NoScript dowola JavaScript, Java (a druhe tykaÄe) jenož za dowÄ›ry hódne domeny waÅ¡eje wólby (na pÅ™. waÅ¡e websydÅ‚o za domjacne bankowanje). Tuta běła lisćina, kotraž na prewentiwnym pÅ™istupje k blokowanju bazÄ›ruje, zadźěwa znjewužiwanju wÄ›stotnych dźěrow (znatych a samo njeznatych!) bjez zhubjenja funkcionalnosće… Eksperća pÅ™izwola: Firefox je woprawdźe wÄ›sćiÅ¡i z NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Skanery na zakładźe CSS blokować">
+<!ENTITY noscriptOptFilterXGet "Podhladne XSS-požadanja porjedźić">
+<!ENTITY noscriptOptFilterXPost "XSS-požadanja POST do požadanjow GET wobsahowacych mjenje datow přetworić">
+<!ENTITY noscriptShowConsole "Konsolu pokazać…">
+<!ENTITY noscriptShowConsole.accesskey "K">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "Huste prašenja XSS…">
+<!ENTITY noscriptXssFaq.accesskey "H">
+<!ENTITY noscriptUnsafeReload "NjewÄ›ste znowazaÄitanje">
+<!ENTITY noscriptUnsafeReload.accesskey "N">
+<!ENTITY noscriptXssExceptions "Wuwzaća škita přećiwo XSS">
+<!ENTITY noscriptXssExceptions.description "Cile, kotrež tutym regularnym wurazam wotpowěduja, NJEbudu so přećiwo XSS škitać.">
+<!ENTITY noscriptMatchSample "Přikład za wotpowědnik mustra:">
+<!ENTITY noscriptReset "Wróćo stajić">
+<!ENTITY noscriptReset.accesskey "s">
+<!ENTITY noscriptResetDef "Na standard wróćo stajić">
+<!ENTITY noscriptResetDef.accesskey "t">
+<!ENTITY noscriptOptionsWidth "60em">
+<!ENTITY noscriptRevokeTemp "Nachwilne prawa wotwołać">
+<!ENTITY noscriptRevokeTemp.accesskey "N">
+<!ENTITY noscriptNoUntrustedPlaceholder "Žadyn zastupniski wobrazk za objekty, kotrež ze sydłow pochadźeja, kotrež su jako dowěry njehódne markěrowane">
+<!ENTITY noscriptCollapseBlockedObjects "Zablokowane objekty fałdować">
+<!ENTITY noscriptExceptions "Wuwzaća…">
+<!ENTITY noscriptBlockedObjects "Zablokowane objekty">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Kóždy objekt blokować, kotryž ze sydła pochadźa, kotrež je jako dowěry njehódne markěrowane">
+<!ENTITY noscriptTempAllowPage "Tutu cyłu stronu nachwilu dowolić">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "Wšitko na tutej stronje dowolić">
+<!ENTITY noscriptAllowPage.accesskey "W">
+<!ENTITY noscriptTempToPerm "Prawa strony na přeco připokazać">
+<!ENTITY noscriptTempToPerm.accesskey "P">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS huste prašenja…">
+<!ENTITY noscriptHttpsFaq.accesskey "H">
+<!ENTITY noscriptHttps.behavior "Zadźerženje">
+<!ENTITY noscriptHttps.cookies "Placki">
+<!ENTITY noscriptHttps.description "Aktiwny webwobsah zakazać, chibazo pochadźa z wěsteho zwiska (HTTPS):">
+<!ENTITY noscriptHttps.never "Ženje">
+<!ENTITY noscriptHttps.proxy "PÅ™i wužiwanju proksy (z Torom doporuÄeny)">
+<!ENTITY noscriptHttps.always "Přeco">
+<!ENTITY noscriptHttpsForced "Slědowace sydła nućić wěste zwiski (HTTPS) wužiwać:">
+<!ENTITY noscriptHttpsForcedExceptions "Slědowace sydła ženje njenućić wěste zwiski (HTTPS) wužiwać:">
+<!ENTITY noscriptSecureCookies "Awtomatiske wěste zarjadowanje plackow zmóžnić">
+<!ENTITY noscriptSecureCookiesForced "ZakluÄowanje za wÅ¡Ä› placki wunućić, kotrež su so pÅ™ez HTTPS za slÄ›dowace sydÅ‚a nastajili:">
+<!ENTITY noscriptSecureCookiesExceptions "Njewěste placki, kotrež buchu přez HTTPS za slědowace sydła nastajene, ignorować:">
+<!ENTITY noscriptClearClickTitle "Warnowanje přez ClearClick">
+<!ENTITY noscriptClearClickHeader "Potencielny pospyt Clickjacking / přeadresowanja!">
+<!ENTITY noscriptClearClickDescription "NoScript je interakciju myše abo tastatury z dźělnje schowanym elementom wotpopadnył. Klikńće na slědowacy wobraz, zo by mjez zablokowanej a widźomnej wersiju přeměnił.">
+<!ENTITY noscriptClearClickOpt "Škit přez ClearClick na stronach…">
+<!ENTITY noscriptClearClickReport "Rozprawa">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "ID rozprawy:">
+<!ENTITY noscriptTrustedPagesAdj "dowěry hódny">
+<!ENTITY noscriptUntrustedPagesAdj "dowěry njehódny">
+<!ENTITY noscriptKeepLocked "Tutón element zawrjeny wostajić (doporuÄeny)">
+<!ENTITY noscriptEmbeddings "Zasadźenja">
+<!ENTITY noscriptPrev "Předchadny">
+<!ENTITY noscriptNext "Přichodny">
+<!ENTITY noscriptFrameOptErr.title "Tutón wobsah njeda so we wobłuku zwobraznić">
+<!ENTITY noscriptFrameOptErr.desc "Zo by swoju wěstotu zarućił, wudawaćel tutoho wobsaha njedowoluje, zo by so tutón wobsah we wobłuku zwobraznił.">
+<!ENTITY noscriptFrameOptErr.link "Klikńće tu, zo byšće tutón wobsah w nowym woknje woÄiniÅ‚">
+<!ENTITY noscriptBookmarkSync "Konfiguraciju NoScript w zapołožce za lochku synchronizaciju zawěsćić">
+<!ENTITY noscriptShowReleaseNotes "Wersije informacije při aktualizacijach zwobraznić">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Sadźby prawidłow:">
+<!ENTITY ABE.enabled.label "ABE (Application Boundaries Enforcer) zmóžnić">
+<!ENTITY ABE.siteEnabled.label "Sydłam dowolić, zo bychu swójske sadźby prawidłow wužiwali">
+<!ENTITY ABE.edit.label "Wobdźěłać…">
+<!ENTITY ABE.edit.accesskey "W">
+<!ENTITY ABE.enable.label "Zmóžnić">
+<!ENTITY ABE.enable.accesskey "m">
+<!ENTITY ABE.disable.label "Znjemóžnić">
+<!ENTITY ABE.disable.accesskey "Z">
+<!ENTITY ABE.refresh.label "Aktualizować">
+<!ENTITY ABE.refresh.accesskey "A">
+<!ENTITY noscriptUninstall "Wotinstalować">
+<!ENTITY noscriptRecentBlocked "Njedawno zablokowane sydła">
+<!ENTITY noscriptExternalFilters "Eksterne filtry">
+<!ENTITY noscriptEF.enable "Eksterne filtry zmóžnić">
+<!ENTITY noscriptEF.add "Nowy filter…">
+<!ENTITY noscriptEF.executable "Wuwjedujomna dataja:">
+<!ENTITY noscriptEF.browse "Přepytać…">
+<!ENTITY noscriptEF.contentType "Wobsahowy typ (MIME), kotryž ma so wufiltrować (eksaktne zapřijeće abo regularny wuraz):">
+<!ENTITY noscriptEF.exceptions "Objekty njefiltrować, kotrež ze slědowacych sydłow pochadźeja:">
+<!ENTITY noscriptEF.remove "Wotstronić">
+<!ENTITY noscriptPreset "Wěstotny schodźenk">
+<!ENTITY noscriptPreset.off "Wupinjeny (sy ty seriozny?!)">
+<!ENTITY noscriptPreset.low "Słaba wěstota (Čorna lisćina + webwěstota)">
+<!ENTITY noscriptPreset.medium "Klasiska wěstota (Běła lisćina + webwěstota)">
+<!ENTITY noscriptPreset.high "Twjerdźizna (dospołnje zawrjeny)">
+<!ENTITY noscript.hoverUI "Meni prawow woÄinić, hdyž pokazowak myÅ¡e je nad NoScriptowym wobrazom">
+<!ENTITY noscriptDonate "Darić">
+<!ENTITY noscriptDonate.accesskey "a">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/hsb/noscript/noscript.properties b/extensions/noscript/chrome/locale/hsb/noscript/noscript.properties
new file mode 100644
index 0000000..41acd53
--- /dev/null
+++ b/extensions/noscript/chrome/locale/hsb/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Skripty globalnje dowolić (riskantny)
+forbidGlobal=Skripty globalnje zakazać (doporuÄeny)
+allowLocal=%S dowolić
+allowTemp=%S nachwilu dowolić
+forbidLocal=%S zakazać
+allowed.glb=Strach! Skripty su globalnje dowolene
+allowed.yes=Skripty tuchwilu dowolene
+allowed.prt=Skripty zdźěla dowolene
+allowed.no=Skripty tuchwilu zakazane
+global.warning.title=Warnowanje!
+global.warning.text=Skripty budu so (za kóžde sydÅ‚o) generelnje dowoleć.\n To je potencielnje straÅ¡na akcija.\nChceće woprawdźe pokroÄować?
+audio.samples=Awdiopřikłady
+confirm=Sy sej wěsty?
+alwaysAsk=Přeco wo wobkrućenje prosyć
+notifyHide=Po %S sekundach schować
+trust=%S dowěrić
+distrust=%S jako dowěry njehódny markěrować
+untrustedOrigin=dowěry njehódny pochad
+xss.notify.generic=NoScript je potencielny pospyt křižoweho skriptowanja (XSS) z %S wufiltrował. Techniske podrobnosće su so w konsoli protokowali.
+xss.notify.showConsole=Konsolu pokazać…
+xss.notify.showConsole.accessKey=K
+xss.reason.filterXGet=Podhladne požadanje je so porjedźiło. Originalny URL [%1$S] z [%2$S] požadany. Porjedźeny URL: [%3$S].
+xss.reason.filterXGetRef=Podhladny požadanski referer porjedźeny. URL [%1$S] z [%2$S] požadany. Porjedźeny referer: [%3$S].
+xss.reason.filterXPost=Podhladne nahraće do [%1$S] z [%2$S] porjedźene: přetwori so do požadanja GET wobmjezowaneho na sćehnjenje.
+unsafeReload.warning=NJEWĚSTA aktualizacija podhladneho\n\n%1$S [%2$S]\n\nZ [%3$S]\n\nNoScript NJEbudźe tute požadanje škitać!\n
+metaRefresh.notify=NoScript je dalesposrědkowanje <META> znutřka elementa <NOSCRIPT> blokował: %S za %S sekundow.
+metaRefresh.notify.follow=Dalesposrědkowanju slědować
+metaRefresh.notify.follow.accessKey=D
+notify.options=Opcije
+notify.options.accessKey=O
+reset.title=NoScript wróćo stajeny
+reset.warning=WÅ Äš nastajenja NoScripta a sydÅ‚owe dowolenja budu so hnydom na swoje standardne hódnoty wróćo stajeć.\nTuta akcija njeda so cofnyć.\nChceće pokroÄować?
+bookmarkSync.title=Konfiguraciska zapołožka NoScript
+bookmarkSync.message=Tuta zapoÅ‚ožka NJEJE za to mysleny so woÄinić, ale so z pomocu sÅ‚užby kaž Weave abo rozÅ¡Ä›rjenja XMarks synchronizować.
+bookmarkSync.confirm=NoScript je konfiguracisku zapołožku namakał, kotraž je najskerje na\n%S składowana.\nChceće woprawdźe swoju lokalnu konfiguraciju NoScript z wobsahom tuteje zapołožki přepisać?
+ABE.notify=Naprašowanje %1$S filtrowane přez ABE: <%2$S> %3$S
+ABE.chooseEditor=Prošu wubjerće teksotwy editor za sadźby prawidłow ABE
+ABE.syntaxError=Syntaksowy zmylk w sadźbje prawidłow ABE!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOKALNY
+allowFrom=Wšě z %S dowolić
+allowTempFrom=Wšě z %S nachwilu dowolić
+siteInfo.confirm=Chceće runje wo informacije wo sydle \"%1$S\" prosyć\nsćelo napraÅ¡owanje do %2$S.\nChceće pokroÄować?
+siteInfo.tooltip=Srjedźne kliknjenje abo Umsch+kliknjenje za informacije wo sydle…
+ef.activate=Filter %S
+ef.options=opcije %S…
+ef.newName=Zapodajće mjeno noweho filtra:
+ef.locateExe=Wuwjedujomnu dataju za filter %S wubrać
+disable=%S znjemóžnić
+disable.accessKey=z
+removal.title=Warnowanje znižowanja wěstoty
+removal.message=Hdyž NoScript znjemóžnjeće abo wotinstalujeće, wzdaće WÅ EHO Å¡kita, kotryž NoScript k dispoziciji steji.\n\nJeli maće jenož syte, ze skriptowymi dowolnosćemi sydÅ‚o po sydle wobchadźeće, je wÄ›sćiÅ¡a móžnosć.\n\nNoScript móže blokowanje skriptow skónÄić, nimo tych, kotrež woznamjenjeće jako dowÄ›ry njehódne, mjeztym zo hišće z najbóle rozÅ¡Ä›rjenymi wÄ›stotnymi pÅ™ećiwnymi naprawami pÅ™ećiwo XSS, Clickjacking, CSRF a drugim webwohroženjam.\n\nChceće woprawdźe WŠÓN Å¡kit pÅ™ez NoScript wotstronić?\n
+removal.no=NÄ›, jenož blokowanje skriptow skónÄić
+removal.yes=Haj, WŠÓN škit wotstronić
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/hu-HU/noscript/about.properties b/extensions/noscript/chrome/locale/hu-HU/noscript/about.properties
new file mode 100644
index 0000000..8663225
--- /dev/null
+++ b/extensions/noscript/chrome/locale/hu-HU/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Extra védelem a Firefoxhoz…
+aboutTitle=A %S névjegye
+extensionContributors=Közreműködtek:
+extensionContributors.tip=Azok a személyek, akiknek köszönhető ez a kiterjesztés
+extensionCreatorLabel=Szerző:
+changelog=Fejlesztési napló
+changelog.tip=Tekintse meg a fejlesztési naplót
+license=Licenc
+license.tip=Olvassa el a végfelhasználói licencszerződést
+logo.tip=Keresse fel a kiterjesztés honlapját
+sponsor.tip=Keresse fel a szponzor honlapját
+informaction.tip=Keresse fel az InformAction honlapját
+extensionHomepage.tip=Keresse fel a kiterjesztés honlapját
+extensionCreator.tip=Keresse fel a szerző honlapját
+version=Változat %S
diff --git a/extensions/noscript/chrome/locale/hu-HU/noscript/noscript.dtd b/extensions/noscript/chrome/locale/hu-HU/noscript/noscript.dtd
new file mode 100644
index 0000000..7dedf55
--- /dev/null
+++ b/extensions/noscript/chrome/locale/hu-HU/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Beállítások…">
+<!ENTITY noscriptOptions.accesskey "B">
+<!ENTITY noscriptOptionsLong "A NoScript beállításai">
+<!ENTITY noscriptAbout "A NoScript 5.1.8.5 névjegye">
+<!ENTITY noscriptPermissionsText "Megadhatja, hogy mely webhelyek számára engedélyezi a parancsfájlok futtatását. Ãrja be az engedélyezni kívánt webhely címét vagy tartomány nevét (pl. &quot;http://www.webhely.hu&quot; vagy &quot;webhely.hu&quot;), majd kattintson az Engedélyezés gombra.">
+<!ENTITY noscriptWebAddress "A webhely címe:">
+<!ENTITY noscriptAllow "Engedélyezés">
+<!ENTITY noscriptAllow.accesskey "N">
+<!ENTITY noscriptForbid "Letiltás">
+<!ENTITY noscriptForbid.accesskey "L">
+<!ENTITY noscriptTrust "Megjelölés megbízhatóként">
+<!ENTITY noscriptTrust.accesskey "b">
+<!ENTITY noscriptUntrust "Megjelölés megbízhatatlanként">
+<!ENTITY noscriptUntrust.accesskey "n">
+<!ENTITY noscriptRemoveSelected "A kiválasztott webhelyek eltávolítása">
+<!ENTITY noscriptGloballyEnabled "A parancsfájlok általános futtatása engedélyezett (veszélyes)">
+<!ENTITY noscriptAutoReload "Az érintett oldalak automatikus újratöltése az engedélyek megváltoztatásakor">
+<!ENTITY noscriptGeneral "Ãltalános">
+<!ENTITY noscriptAppearance "Megjelenés">
+<!ENTITY noscriptShow "Megjelenítés…">
+<!ENTITY noscriptCtxMenu "Helyi menü">
+<!ENTITY noscriptStatusIcon "Ikon az állapotsoron">
+<!ENTITY noscriptFullAddr "Teljes címek (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Teljes tartományok (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Alap 2. szintű tartományok (noscript.net)">
+<!ENTITY noscriptTempCmd "Ideiglenes engedélyezés […]">
+<!ENTITY noscriptSound "Hangjelzés a parancsfájlok blokkolásakor">
+<!ENTITY noscriptImport "Importálás">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exportálás">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Üzenet megjelenítése a blokkolt parancsfájlokról">
+<!ENTITY noscriptNotify.bottom "Az üzenet alulra helyezése">
+<!ENTITY noscriptSound.choose "Választás">
+<!ENTITY noscriptSound.choose.accesskey "V">
+<!ENTITY noscriptSound.play "Lejátszás">
+<!ENTITY noscriptSound.play.accesskey "L">
+<!ENTITY noscriptSound.reset "Alaphelyzet">
+<!ENTITY noscriptSound.reset.accesskey "H">
+<!ENTITY noscriptAdvanced "Speciális">
+<!ENTITY noscriptAdditionalPermissions "A megbízható webhelyek további engedélyei">
+<!ENTITY noscriptAllowClipboard "A rich text másolás és a külső vágólapról történő beillesztés engedélyezése">
+<!ENTITY noscriptAdditionalRestrictions "A megbízhatatlan webhelyek további korlátozásai">
+<!ENTITY noscriptPlugins "Beépülők">
+<!ENTITY noscriptContentBlocker "A korlátozások alkalmazása a megbízható webhelyekre is">
+<!ENTITY noscriptForbidJava "A Java™ tiltása">
+<!ENTITY noscriptForbidXSLT "A XSLT tiltása">
+<!ENTITY noscriptForbidSilverlight "A Microsoft® Silverlight™ tiltása">
+<!ENTITY noscriptForbidIFrames "Az &lt;IFRAME&gt; tiltása">
+<!ENTITY noscriptForbidFrames "A &lt;FRAME&gt; tiltása">
+<!ENTITY noscriptForbidFonts "A @font-face letiltása">
+<!ENTITY noscriptForbidWebGL "A WebGL letiltása">
+<!ENTITY noscriptForbidMedia "Az &lt;AUDIO&gt; / &lt;VIDEO&gt; letiltása">
+<!ENTITY noscriptForbidFlash "Az Adobe® Flash® tiltása">
+<!ENTITY noscriptForbidPlugins "Egyéb beépülő modulok tiltása">
+<!ENTITY noscriptReloadWarn "Ezek a beállítások új vagy (kézzel) újratöltött oldalaknál lépnek érvénybe">
+<!ENTITY noscriptConfirmUnblock "Megerősítés kérése egy objektum ideiglenes feloldása előtt">
+<!ENTITY noscriptStatusLabel "Az állapotsor címkéje">
+<!ENTITY noscriptForbidBookmarklets "A bookmarkletek (könyvjelzők) letiltása">
+<!ENTITY noscriptShowPlaceholder "A helykitöltő ikon megjelenítése">
+<!ENTITY noscriptTruncateTitle "A dokumentumok címeinek lerövidítése">
+<!ENTITY noscriptFixLinks "Kísérlet a JavaScript hivatkozások javítására">
+<!ENTITY noscriptAllowBookmarks "A könyvjelzőkben található összes webhely engedélyezése">
+<!ENTITY noscriptAllowViaBookmarks "A könyvjelzőből megnyitott webhelyek engedélyezése">
+<!ENTITY noscriptAllowPing "Engedélyezés: &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Helyi linkek engedélyezése">
+<!ENTITY noscriptForbidPing "Letiltás: &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "META átirányítások letiltása a &lt;NOSCRIPT&gt; elemekben">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "l">
+<!ENTITY noscriptNotifyMeta "Üzenet megjelenítése a blokkolt META átirányításokról">
+<!ENTITY noscriptNotifyMeta.accesskey "y">
+<!ENTITY noscriptWhitelist "Fehérlista">
+<!ENTITY noscriptPermissions "Engedélyek">
+<!ENTITY noscriptRefresh "Újratöltés">
+<!ENTITY noscriptNotifications "Jelentések">
+<!ENTITY noscriptToolbarToggle "Az eszköztár ikonjának helyi menüje megváltoztathatja a jelenlegi webhely (legmagasabb szint) engedélyeit">
+<!ENTITY noscriptTrusted "Megbízható">
+<!ENTITY noscriptUntrusted "Megbízhatatlan">
+<!ENTITY noscriptUnknown "Ismeretlen">
+<!ENTITY noscriptAdd "Hozzáadás">
+<!ENTITY noscriptAdd.accesskey "H">
+<!ENTITY noscriptClose "Bezárás">
+<!ENTITY noscriptSiteManager "Webhely-kezelő">
+<!ENTITY noscriptSecurityManager "Megbízhatóság-kezelő">
+<!ENTITY noscriptPolicies "Kezelés">
+<!ENTITY noscriptDefaultPolicies "Alapértelmezett kezelés">
+<!ENTITY noscriptSitePolicies "Webhelyspecifikus kezelés">
+<!ENTITY noscriptNselNever "&lt;NOSCRIPT&gt; elemek elrejtése">
+<!ENTITY noscriptNselForce "&lt;NOSCRIPT&gt; elem megjelenítése, amely a blokkolt &lt;SCRIPT&gt; után következik">
+<!ENTITY noscriptAutoAllowTopLevel "Legmagasabb szintű webhelyek ideiglenes engedélyezése">
+<!ENTITY noscriptDescription "Firefox extra védelme: NoScript engedélyezheti a JavaScript, Java (és más beépülőket) az Ön által megadott webhelyekre (pl. átutalások interneten keresztül). Ez a megbízható szervereket tartalmazó lista megelőző blokkoláson alapszik, így óv a támadásoktól a biztonsági réseken keresztül (ismert és ismeretlen!), mindezt működés közben… Az expertek egyetértenek: A Firefox a NoScript kiterjesztéssel valóban biztonságosabb :-)">
+<!ENTITY noscriptOptBlockCssScanners "CSS-alapú szkennerek blokkolása">
+<!ENTITY noscriptOptFilterXGet "Gyanús XSS hozzáférések kezelése">
+<!ENTITY noscriptOptFilterXPost "POST hozzáférés átváltása GET hozzáférésre">
+<!ENTITY noscriptShowConsole "Konzol megjelenítése…">
+<!ENTITY noscriptShowConsole.accesskey "K">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS GYIK…">
+<!ENTITY noscriptXssFaq.accesskey "G">
+<!ENTITY noscriptUnsafeReload "Megbízhatatlan újratöltése">
+<!ENTITY noscriptUnsafeReload.accesskey "N">
+<!ENTITY noscriptXssExceptions "Anti-XSS védelem kivételek">
+<!ENTITY noscriptXssExceptions.description "A következő reguláris kifejezéseknek megfelelő webhelyek NEM LESZNEK az XSS ellen védve.">
+<!ENTITY noscriptMatchSample "Sablon példa:">
+<!ENTITY noscriptReset "Alaphelyzet">
+<!ENTITY noscriptReset.accesskey "A">
+<!ENTITY noscriptResetDef "Alaphelyzetbe állít">
+<!ENTITY noscriptResetDef.accesskey "h">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Ideiglenes hozzáférések visszavonása">
+<!ENTITY noscriptRevokeTemp.accesskey "v">
+<!ENTITY noscriptNoUntrustedPlaceholder "Nincs helykitöltő a megbízhatatlannak megjelölt webhelyekről érkező objektumoknál">
+<!ENTITY noscriptCollapseBlockedObjects "Blokkolt objektumok összecsukása">
+<!ENTITY noscriptExceptions "Kivételek…">
+<!ENTITY noscriptBlockedObjects "Blokkolt objektumok">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Minden megbízhatatlanként megjelölt oldalról érkező objektum blokkolása">
+<!ENTITY noscriptTempAllowPage "Parancsfájlok ideiglenes engedélyezése az oldalon">
+<!ENTITY noscriptTempAllowPage.accesskey "i">
+<!ENTITY noscriptAllowPage "Parancsfájlok engedélyezése az oldalon">
+<!ENTITY noscriptAllowPage.accesskey "e">
+<!ENTITY noscriptTempToPerm "Oldal jogosultságok állandósítása">
+<!ENTITY noscriptTempToPerm.accesskey "j">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS GyIK...">
+<!ENTITY noscriptHttpsFaq.accesskey "y">
+<!ENTITY noscriptHttps.behavior "Viselkedés">
+<!ENTITY noscriptHttps.cookies "Sütik">
+<!ENTITY noscriptHttps.description "Aktív tartalom letiltása, ha nem biztonságos kapcsolatról (HTTPS) ered:">
+<!ENTITY noscriptHttps.never "Soha">
+<!ENTITY noscriptHttps.proxy "Ha proxy szerver van használatban (Tor ajánlott)">
+<!ENTITY noscriptHttps.always "Mindig">
+<!ENTITY noscriptHttpsForced "Biztonságos hozzáférés (HTTPS) erőltetése az alábbi oldalaknál:">
+<!ENTITY noscriptHttpsForcedExceptions "Ne erőltesse a biztonságos hozzáférést (HTTPS) az alábbi oldalaknál:">
+<!ENTITY noscriptSecureCookies "Biztonságos sütik automatikus kezelésének engedélyezése">
+<!ENTITY noscriptSecureCookiesForced "Sütik titkosításának erőltetése, amelyek HTTPS segítségével lettek beállítva az alábbi oldalakon:">
+<!ENTITY noscriptSecureCookiesExceptions "Veszélyes sütik figyelmen kívül hagyása, amelyek HTTPS segítségével lettek beállítva az alábbi oldalakon:">
+<!ENTITY noscriptClearClickTitle "ClearClick figyelmeztetések">
+<!ENTITY noscriptClearClickHeader "Kattintás után hamisítványgyanús viselkedés lehetséges!">
+<!ENTITY noscriptClearClickDescription "A NoScript billentyűzet vagy egér kölcsönhatását észlelte egy részlegesen rejtett objektummal. A képre kattintva válthat a gyanús és a tiszta változat között.">
+<!ENTITY noscriptClearClickOpt "ClearClick védelem a">
+<!ENTITY noscriptClearClickReport "Jelentés">
+<!ENTITY noscriptClearClickReport.accesskey "J">
+<!ENTITY noscriptClearClickReportId "Jelentés azonosító:">
+<!ENTITY noscriptTrustedPagesAdj "biztonságos oldalakon">
+<!ENTITY noscriptUntrustedPagesAdj "nem biztonságos oldalakon">
+<!ENTITY noscriptKeepLocked "Az elem blokkolása a továbbiakban is (ajánlott)">
+<!ENTITY noscriptEmbeddings "Beágyazott objektumok">
+<!ENTITY noscriptPrev "Előző">
+<!ENTITY noscriptNext "Következő">
+<!ENTITY noscriptFrameOptErr.title "Ez a tartalom keretben nem jeleníthető meg">
+<!ENTITY noscriptFrameOptErr.desc "A tartalom kiadója nem engedélyezte annak keretben történő megjelenítését.">
+<!ENTITY noscriptFrameOptErr.link "Kattintson ide a tartalom megjelenítéséhez új ablakban">
+<!ENTITY noscriptBookmarkSync "A NoScript konfigurációjának biztonsági mentése könyvjelzőbe (a szinkronizáció egyszerűbbé tétele)">
+<!ENTITY noscriptShowReleaseNotes "Kiadási megjegyzések megjelenítése frissítéskor">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Szabálycsomagok:">
+<!ENTITY ABE.enabled.label "ABE engedélyezése (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "A weboldalak hozzáadhatják saját szabálycsomagjaikat">
+<!ENTITY ABE.edit.label "Szerkesztés...">
+<!ENTITY ABE.edit.accesskey "S">
+<!ENTITY ABE.enable.label "Engedélyezés">
+<!ENTITY ABE.enable.accesskey "E">
+<!ENTITY ABE.disable.label "Letiltás">
+<!ENTITY ABE.disable.accesskey "L">
+<!ENTITY ABE.refresh.label "Frissítés">
+<!ENTITY ABE.refresh.accesskey "F">
+<!ENTITY noscriptUninstall "Eltávolítás">
+<!ENTITY noscriptRecentBlocked "Legutoljára blokkolt oldalak">
+<!ENTITY noscriptExternalFilters "Külső szűrők">
+<!ENTITY noscriptEF.enable "Külső szűrők engedélyezése">
+<!ENTITY noscriptEF.add "Új szűrő…">
+<!ENTITY noscriptEF.executable "Futtatható fájl:">
+<!ENTITY noscriptEF.browse "Tallózás…">
+<!ENTITY noscriptEF.contentType "MIME tartalom, amelyet szűrni (teljes egyezés vagy reguláris kifejezés) kíván:">
+<!ENTITY noscriptEF.exceptions "Ne szűrje az alábbi oldalakról érkező objektumokat:">
+<!ENTITY noscriptEF.remove "Eltávolítás">
+<!ENTITY noscriptPreset "Biztonsági szint">
+<!ENTITY noscriptPreset.off "Kikapcsolás (valóban?!)">
+<!ENTITY noscriptPreset.low "Gyenge (feketelista + web biztonság)">
+<!ENTITY noscriptPreset.medium "Klasszikus (fehérlista + web biztonság)">
+<!ENTITY noscriptPreset.high "Erős (teljes szűrés)">
+<!ENTITY noscript.hoverUI "Hozzáférések menü megnyitása, ha az egér kurzora a NoScript ikon felett van">
+<!ENTITY noscriptDonate "Hozzájárulás">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/hu-HU/noscript/noscript.properties b/extensions/noscript/chrome/locale/hu-HU/noscript/noscript.properties
new file mode 100644
index 0000000..9b7d515
--- /dev/null
+++ b/extensions/noscript/chrome/locale/hu-HU/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=A parancsfájlok általános engedélyezése (veszélyes)
+forbidGlobal=A parancsfájlok általános letiltása (ajánlott)
+allowLocal=Engedélyezés: %S
+allowTemp=Ideiglenes engedélyezés: %S
+forbidLocal=Letiltás: %S
+allowed.glb=Veszélyes! A parancsfájlok általános futtatása engedélyezett
+allowed.yes=A parancsfájlok futtatása jelenleg engedélyezett
+allowed.prt=A parancsfájlok futtatása részben engedélyezett
+allowed.no=A parancsfájlok futtatása jelenleg letiltott
+global.warning.title=Figyelem!
+global.warning.text=Ön általánosan (minden webhelyhez) kívánja engedélyezni a parancsfájlok futtatását.\nEz veszélyes lehet.\nValóban kívánja folytatni?
+audio.samples=Hangminták
+confirm=Biztos benne?
+alwaysAsk=Megerősítés kérése minden alkalommal
+notifyHide=Elrejtés %S másodperc után
+trust=Megbízható: %S
+distrust=Megbízhatatlan: %S
+untrustedOrigin=megbízhatatlan eredet
+xss.notify.generic=A NoScript kiszűrt egy lehetséges XSS szkriptet a %S oldalról. Technikai részleteket a konzol tartalmaz.
+xss.notify.showConsole=Konzol megjelenítése…
+xss.notify.showConsole.accessKey=K
+xss.reason.filterXGet=Gyanús hozzáférés kezelve. Eredeti cím [%1$S] hozzáférést kért a [%2$S] címhez. Kezelt cím: [%3$S].
+xss.reason.filterXGetRef=Gyanús hozzáférési üzenet kezelve. Cím [%1$S] hozzáférést kért a [%2$S] címhez. Kezelt üzenet: [%3$S].
+xss.reason.filterXPost=Gyanús átvitel a [%2$S] címről a [%1$S] címre kezelve: átalakítva csak átvételre (GET).
+unsafeReload.warning=Gyanús elem újratöltése a következő címről:\n\n %1$S [%2$S]\n\nA(z) [%3$S]\n\ncímről a NoScript nem óvja a kérést!\n
+metaRefresh.notify=NoScript blokkolta a <META> átirányítás a <NOSCRIPT> elemen belül: %S - %S mp.
+metaRefresh.notify.follow=Ãtirányítás követése
+metaRefresh.notify.follow.accessKey=i
+notify.options=Opciók
+notify.options.accessKey=O
+reset.title=NoScript alaphelyzetbe állítása
+reset.warning=A NoScript valamennyi beállítása alaphelyzetbe kerül.\nA felhasználó által a weboldalakhoz beállított szkriptek tiltásai is törlődnek.\n\nEz a művelet nem vonható vissza.\nValóban szeretné folytatni?
+bookmarkSync.title=NoScript konfigurációs könyvjelző
+bookmarkSync.message=Ez a könyvjelző szinkronizációt segít elő a Weave/XMarks kiterjesztés szolgáltatásainak segítségével.
+bookmarkSync.confirm=A NoScript feltehetően mentett konfigurációs könyvjelzőt talált:\n%S.\nKívánja felülírni a jelenlegi NoScript konfigurációját a könyvjelző tartalmával?
+ABE.notify=A %1$S kérést az ABE kiszűrte: <%2$S> %3$S
+ABE.chooseEditor=Kérem válassza ki a szövegszerkesztőt az ABE szabálycsomaghoz
+ABE.syntaxError=Szintaxis hiba az ABE szabálycsoportban!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Mindegyik engedélyezése: %S
+allowTempFrom=Mindegyik ideiglenes engedélyezése: %S
+siteInfo.confirm=Infót kér a(z) "%1$S" oldalról\na(z) %2$S. kérés segítségével.\nFolytatja?
+siteInfo.tooltip=Középső kattintás vagy shift+kattintás az oldal információhoz…
+ef.activate=Szűrő %S
+ef.options=%S opciók…
+ef.newName=Adja meg az új szűrő nevét:
+ef.locateExe=Válassz ki a futtatható fájlt a(z) %S szűrőhöz
+disable=%S letiltása
+disable.accessKey=l
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/id-ID/noscript/about.properties b/extensions/noscript/chrome/locale/id-ID/noscript/about.properties
new file mode 100644
index 0000000..f336d12
--- /dev/null
+++ b/extensions/noscript/chrome/locale/id-ID/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Perlindungan tambahan untuk FireFox Anda: NoScript mengijinkan JavaScript, Java (dan plugin lainnya) hanya untuk domain terpercaya pilihan Anda (misal: situs web-banking personal). Daftar putih ini menjadi dasar perlindungan dari penyalahgunaan lubang keamanan (yang diketahui maupun tidak) tanpa kehilangan fungsionalitas... Para ahli percaya: FireFox lebih aman bersama NoScript :-)
+aboutTitle=Tentang %S
+extensionContributors=Kontributor:
+extensionContributors.tip=Orang-orang yang perlu anda beri ucapan terima kasih untuk ekstension ini
+extensionCreatorLabel=Penulis:
+changelog=Catatan Perubahan
+changelog.tip=Tampilkan Catatan Perubahan
+license=Lisensi
+license.tip=Baca lisensi end-user
+logo.tip=Datangi homepage ekstension
+sponsor.tip=Datangi homepage sponsor
+informaction.tip=Datangi homepage InformAction
+extensionHomepage.tip=Datangi homepage ekstension
+extensionCreator.tip=Datangi homepage Penulis
+version=Versi %S
diff --git a/extensions/noscript/chrome/locale/id-ID/noscript/noscript.dtd b/extensions/noscript/chrome/locale/id-ID/noscript/noscript.dtd
new file mode 100644
index 0000000..65497ec
--- /dev/null
+++ b/extensions/noscript/chrome/locale/id-ID/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Pilihan...">
+<!ENTITY noscriptOptions.accesskey "P">
+<!ENTITY noscriptOptionsLong "Pilihan NoScript">
+<!ENTITY noscriptAbout "Tentang NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Anda dapat menentukan situs web mana yang diijinkan menjalankan naskah. Masukkan alamat atau domain (contoh: &quot;http://www.site.com&quot; atau &quot;site.com&quot;) yang akan diberi ijin kemudian klik Ijinkan.">
+<!ENTITY noscriptWebAddress "Alamat situs web:">
+<!ENTITY noscriptAllow "Ijinkan">
+<!ENTITY noscriptAllow.accesskey "I">
+<!ENTITY noscriptForbid "Larang">
+<!ENTITY noscriptForbid.accesskey "L">
+<!ENTITY noscriptTrust "Tandai sebagai Terpercaya">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Tandai sebagai Tidak Terpercaya">
+<!ENTITY noscriptUntrust.accesskey "X">
+<!ENTITY noscriptRemoveSelected "Hapus situs terpilih">
+<!ENTITY noscriptGloballyEnabled "Seluruh naskah diperbolehkan (berbahaya)">
+<!ENTITY noscriptAutoReload "Otomatis mengambil ulang halaman yang terpengaruh saat perijinan berubah">
+<!ENTITY noscriptGeneral "Umum">
+<!ENTITY noscriptAppearance "Penampilan">
+<!ENTITY noscriptShow "Tampilkan...">
+<!ENTITY noscriptCtxMenu "Menu kontekstual">
+<!ENTITY noscriptStatusIcon "Ikon papan status">
+<!ENTITY noscriptFullAddr "Alamat Lengkap (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Domain Lengkap (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Dasar Domain level ke-2 (noscript.net)">
+<!ENTITY noscriptTempCmd "Ijinkan sementara [...]">
+<!ENTITY noscriptSound "Umpan balik suara saat naskah dihalangi">
+<!ENTITY noscriptImport "Impor">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Ekspor">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Tampilkan pesan tetang naskah yang dihalangi">
+<!ENTITY noscriptNotify.bottom "Taruh pesan di bawah">
+<!ENTITY noscriptSound.choose "Pilih">
+<!ENTITY noscriptSound.choose.accesskey "P">
+<!ENTITY noscriptSound.play "Mainkan">
+<!ENTITY noscriptSound.play.accesskey "M">
+<!ENTITY noscriptSound.reset "Reset ke awal">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Canggih">
+<!ENTITY noscriptAdditionalPermissions "Tambahan perijinan untuk situs terpercaya">
+<!ENTITY noscriptAllowClipboard "Perbolehkan copy dan paster rich text dari clipboard eksternal">
+<!ENTITY noscriptAdditionalRestrictions "Pembatasan tambahan untuk situs tidak terpercaya">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Apply these restrictions to trusted sites too">
+<!ENTITY noscriptForbidJava "Larang Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Larang XSLT">
+<!ENTITY noscriptForbidSilverlight "Forbid Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Forbid &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Forbid &lt;FRAMES&gt;">
+<!ENTITY noscriptForbidFlash "Larang Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Larang plugin lainnya">
+<!ENTITY noscriptReloadWarn "Pilihan ini akan berpengaruh pada halaman yang baru atau yang baru diambil ulang">
+<!ENTITY noscriptConfirmUnblock "Konfirmasi ulang sebelum membuka sementara penghalang suatu objek">
+<!ENTITY noscriptStatusLabel "Label papan status">
+<!ENTITY noscriptForbidBookmarklets "Larang bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Tampilkan ikon placeholder">
+<!ENTITY noscriptTruncateTitle "Potong judul dokumen">
+<!ENTITY noscriptFixLinks "Berusaha memperbaiki link JavaScript">
+<!ENTITY noscriptAllowBookmarks "Ijinkan bookmarks">
+<!ENTITY noscriptAllowViaBookmarks "Ijinkan situs dibuka melalui bookmarks">
+<!ENTITY noscriptAllowPing "Ijinkan &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Ijinkan link lokal">
+<!ENTITY noscriptForbidPing "Larang &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Larang perubahan arah META didalam elemen &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "M">
+<!ENTITY noscriptWhitelist "Daftar putih">
+<!ENTITY noscriptPermissions "Ijin-ijin">
+<!ENTITY noscriptRefresh "Segarkan">
+<!ENTITY noscriptNotifications "Pemberitahuan">
+<!ENTITY noscriptToolbarToggle "Klik kiri pada toolbar NoScript membalikan">
+<!ENTITY noscriptTrusted "Terpercaya">
+<!ENTITY noscriptUntrusted "Tidak Terpercaya">
+<!ENTITY noscriptUnknown "Tidak diketahui">
+<!ENTITY noscriptAdd "Tambah">
+<!ENTITY noscriptAdd.accesskey "a">
+<!ENTITY noscriptClose "Tutup">
+<!ENTITY noscriptSiteManager "Manajer Situs">
+<!ENTITY noscriptSecurityManager "Manajer Keamanan">
+<!ENTITY noscriptPolicies "Kebijakan">
+<!ENTITY noscriptDefaultPolicies "Kebijakan awal">
+<!ENTITY noscriptSitePolicies "Kebijakan Situs">
+<!ENTITY noscriptNselNever "Sembunyikan elemen &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Tampikan elemen &lt;NOSCRIPT&gt; yang mengikuti &lt;SCRIPT&gt; yang dihalangi">
+<!ENTITY noscriptAutoAllowTopLevel "Ijinkan sementara situs top-level untuk awal">
+<!ENTITY noscriptDescription "Perlindungan tambahan untuk FireFox Anda: NoScript mengijinkan JavaScript, Java (dan plugin lainnya) hanya untuk domain terpercaya pilihan Anda (misal: situs web-banking personal). Daftar putih ini menjadi dasar perlindungan dari penyalahgunaan lubang keamanan (yang diketahui maupun tidak) tanpa kehilangan fungsionalitas... Para ahli percaya: FireFox lebih aman bersama NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "halangi pemindai berdasar CSS">
+<!ENTITY noscriptOptFilterXGet "Bersihkan permintaan cross-site yang mencurigakan">
+<!ENTITY noscriptOptFilterXPost "Ubah permintaan POST cross-site menjadi permintaan GET tanpa data">
+<!ENTITY noscriptShowConsole "Tampilkan Penyangga">
+<!ENTITY noscriptShowConsole.accesskey "P">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Ambil ulang yang tidak aman">
+<!ENTITY noscriptUnsafeReload.accesskey "u">
+<!ENTITY noscriptXssExceptions "Pengecualian Perlindungan Anti-XSS">
+<!ENTITY noscriptXssExceptions.description "Pencocokan tujuan regular expression ini tidak akan dilindungi dari XSS">
+<!ENTITY noscriptMatchSample "Contoh pencocokan pola:">
+<!ENTITY noscriptReset "Reset">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Reset ke awal">
+<!ENTITY noscriptResetDef.accesskey "r">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Mencabut Izin Sementara">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "Tidak ada tempat tetap untuk obyek yang datang dari situs yang tidak dipercaya">
+<!ENTITY noscriptCollapseBlockedObjects "Gabung obyek yang diblok">
+<!ENTITY noscriptExceptions "Pengecualian...">
+<!ENTITY noscriptBlockedObjects "Obyek yang Diblok">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Blok setiap obyek yang datang dari situs yang tidak dipercaya">
+<!ENTITY noscriptTempAllowPage "Sementara bolehkan semua halaman ini">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Bolehkan semua halaman ini">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Buat izin permanen halaman">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Perilaku">
+<!ENTITY noscriptHttps.cookies "Cookie">
+<!ENTITY noscriptHttps.description "Larangkan konten aktif web kecuali datang dari koneksi aman (HTTPS):">
+<!ENTITY noscriptHttps.never "Tidak pernah">
+<!ENTITY noscriptHttps.proxy "Ketika menggunakan proxy (direkomendasikan dengan Tor)">
+<!ENTITY noscriptHttps.always "Selalu">
+<!ENTITY noscriptHttpsForced "Paksa situs berikut ini untuk menggunakan koneksi aman (HTTPS):">
+<!ENTITY noscriptHttpsForcedExceptions "Tidak pernah paksakan koneksi aman (HTTPS) untuk situs berikut ini:">
+<!ENTITY noscriptSecureCookies "Hidupkan Manajemen Otomatis Keamanan Cookie">
+<!ENTITY noscriptSecureCookiesForced "Enkripsikan paksa semua set cookie melalui HTTPS dari situs berikut ini:">
+<!ENTITY noscriptSecureCookiesExceptions "Abaikan set cookie tidak aman melalui HTTPS dari situs berikut ini:">
+<!ENTITY noscriptClearClickTitle "Peringatan ClearClick">
+<!ENTITY noscriptClearClickHeader "Clickjacking Potensial / Mencoba memakai ulang UI!">
+<!ENTITY noscriptClearClickDescription "NoScript menginterupsi interaksi mouse atau keyboard dengan elemen tersembunyi yang terpisah. Klik pada gambar di atas memilih antara versi terhalang dan jelas.">
+<!ENTITY noscriptClearClickOpt "Proteksi ClearClick pada halaman…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "terpercaya">
+<!ENTITY noscriptUntrustedPagesAdj "tidak terpercaya">
+<!ENTITY noscriptKeepLocked "Jaga elemen ini terkunci (direkomendasikan)">
+<!ENTITY noscriptEmbeddings "Obyek yang ditanam">
+<!ENTITY noscriptPrev "Previuous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptForbidFonts "Forbid @font-face">
+<!ENTITY noscriptForbidWebGL "Forbid WebGL">
+<!ENTITY noscriptForbidMedia "Forbid &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/id-ID/noscript/noscript.properties b/extensions/noscript/chrome/locale/id-ID/noscript/noscript.properties
new file mode 100644
index 0000000..882877a
--- /dev/null
+++ b/extensions/noscript/chrome/locale/id-ID/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Ijinkan semua naskah (berbahaya)
+forbidGlobal=Larang semua naskah
+allowLocal=Ijinkan %S
+allowTemp=Ijinkan sementara %S
+forbidLocal=Larang %S
+allowed.glb=Bahaya! Semua naskah diperbolehkan
+allowed.yes=Naskah diperbolehkan
+allowed.prt=Naskah sebagian diperbolehkan
+allowed.no=Larang naskah
+global.warning.title=Parhatian!
+global.warning.text=Naskah dari semua situs akan diperbolehkan.\n Ini membuka potensi bahaya.\n Anda yakin untuk meneruskannya?
+audio.samples=Contoh suara
+confirm=Anda yakin?
+alwaysAsk=Selalu tanyakan untuk konfirmasi
+notifyHide=Sembunyikan setelah %S detik
+trust=Percayai %S
+distrust=Tandai %S sebagai Tidak terpercaya
+untrustedOrigin=sumber tidak terpercaya
+xss.notify.generic=NoScript memfilter potensi usaha penaskahan antar situs (XSS) dari %S. Catatan teknis telah ditulis ke Penyangga.
+xss.notify.showConsole=Tampilkan Penyangga...
+xss.notify.showConsole.accessKey=P
+xss.reason.filterXGet=Membersihkan permintaan yang mencurigakan. URL [%2$S] meminta URL asli [%1$S]. URL yang telah dibersihkan: [%3$S].)
+xss.reason.filterXGetRef=Membersihkan penunjuk permintaan yang mencurigakan. URL [%2$S] meminta [%1$S]. Penunjuk yang telah dibersihkan: [%3$S].)
+xss.reason.filterXPost=Membersihkan unggah yang mencurigakan dari [%2$S] ke [%1$S]: dirubah menjadi permintaan GET hanya-unggah.
+unsafeReload.warning=TIDAK AMAN mengambil ulang benda mencurigakan %1$S [%2$S]\n\n dari [%3$S]\n\nNoScript tidak akan menjaga permintaan ini!\n
+metaRefresh.notify=NoScript menghalangi perubahan arah <META> dari dalam unsur <NOSCRIPT>: %S dalam %S detik.
+metaRefresh.notify.follow=Ikuti perubahan arah
+metaRefresh.notify.follow.accessKey=I
+notify.options=Pilihan
+notify.options.accessKey=P
+reset.title=Reset NoScript
+reset.warning=SELURUH pilihan NoScript and perijinan situs akan di reset ke nilai awal.\nTindakan ini tidak dapat diulang mundur.\nApakah Anda ingin melanjutkan?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark's content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/it/noscript/about.properties b/extensions/noscript/chrome/locale/it/noscript/about.properties
new file mode 100644
index 0000000..9a44feb
--- /dev/null
+++ b/extensions/noscript/chrome/locale/it/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Protezione aggiuntiva per Firefox: NoScript consente l'esecuzione di JavaScript, di Java (e, opzionalmente, degli altri plugin) solo per domini fidati di tua scelta (es. la tua banca online). Questo blocco preventivo basato su whitelist impedisce lo sfruttamento di vulnerabiltà della sicurezza (sia note che addirittura ancora sconosciute!) senza perdita di funzionalità... Gli esperti concordano: Firefox è davvero più sicuro con NoScript :-)
+aboutTitle=Informazioni su %S
+extensionContributors=Collaboratori:
+extensionContributors.tip=Chi bisogna ringraziare per questa estensione
+extensionCreatorLabel=Autore:
+changelog=Storia versioni
+changelog.tip=Esamina la storia delle versioni
+license=Licenza
+license.tip=Leggi la licenza per l'utente finale
+logo.tip=Visita il sito web dell'estensione
+sponsor.tip=Visita il sito web dello sponsor
+informaction.tip=Visita il sito web di InformAction
+extensionHomepage.tip=Visita il sito web dell'estensione
+extensionCreator.tip=Visita il sito web dell'autore
+version=Versione %S
diff --git a/extensions/noscript/chrome/locale/it/noscript/noscript.dtd b/extensions/noscript/chrome/locale/it/noscript/noscript.dtd
new file mode 100644
index 0000000..8f29b5e
--- /dev/null
+++ b/extensions/noscript/chrome/locale/it/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opzioni…">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Opzioni NoScript">
+<!ENTITY noscriptAbout "Informazioni su NoScript 5.1.8.5…">
+<!ENTITY noscriptPermissionsText "Qui si possono indicare i siti per i quali l&apos;esecuzione degli script è consentita. Digitare l&apos;indirizzo o il dominio (es. &quot;http://www.sito.com&quot; oppure &quot;sito.com&quot;) e fare clic su Permetti.">
+<!ENTITY noscriptWebAddress "Indirizzo del sito:">
+<!ENTITY noscriptAllow "Permetti">
+<!ENTITY noscriptAllow.accesskey "P">
+<!ENTITY noscriptForbid "Vieta">
+<!ENTITY noscriptForbid.accesskey "V">
+<!ENTITY noscriptTrust "Considera fidato">
+<!ENTITY noscriptTrust.accesskey "f">
+<!ENTITY noscriptUntrust "Considera non fidato">
+<!ENTITY noscriptUntrust.accesskey "n">
+<!ENTITY noscriptRemoveSelected "Rimuovi i siti selezionati">
+<!ENTITY noscriptGloballyEnabled "Esecuzione script abilitati globalmente (pericoloso)">
+<!ENTITY noscriptAutoReload "Ricarica automaticamente la pagina quando i permessi cambiano">
+<!ENTITY noscriptAutoReload.currentTab "Ricarica solo la scheda corrente">
+<!ENTITY noscriptGeneral "Generale">
+<!ENTITY noscriptAppearance "Aspetto">
+<!ENTITY noscriptShow "Mostra…">
+<!ENTITY noscriptCtxMenu "Menù contestuale">
+<!ENTITY noscriptStatusIcon "Icona sulla barra di stato">
+<!ENTITY noscriptFullAddr "Indirizzi completi">
+<!ENTITY noscriptFullDom "Dominii completi">
+<!ENTITY noscriptBaseDom "Dominii base (di secondo livello)">
+<!ENTITY noscriptTempCmd "Permetti temporaneamente […]">
+<!ENTITY noscriptSound "Notifica audio per gli script bloccati">
+<!ENTITY noscriptImport "Importa">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Esporta">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Mostra messaggio sul blocco degli script">
+<!ENTITY noscriptNotify.bottom "Posiziona il messaggio in basso">
+<!ENTITY noscriptSound.choose "Scegli">
+<!ENTITY noscriptSound.choose.accesskey "S">
+<!ENTITY noscriptSound.play "Suona">
+<!ENTITY noscriptSound.play.accesskey "u">
+<!ENTITY noscriptSound.reset "Ripristina predefinito">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Avanzate">
+<!ENTITY noscriptAdditionalPermissions "Permessi aggiuntivi per i siti fidati">
+<!ENTITY noscriptAllowClipboard "Permetti copia e incolla di testo formattato da altre applicazioni">
+<!ENTITY noscriptAdditionalRestrictions "Restrizioni aggiuntive per i siti non fidati">
+<!ENTITY noscriptPlugins "Plugin">
+<!ENTITY noscriptContentBlocker "Applica queste restrizioni anche ai siti fidati">
+<!ENTITY noscriptForbidJava "Vieta Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Vieta XSLT">
+<!ENTITY noscriptForbidSilverlight "Vieta Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Vieta &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Vieta &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Vieta @font-face">
+<!ENTITY noscriptForbidWebGL "Vieta WebGL">
+<!ENTITY noscriptForbidMedia "Vieta &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Vieta Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Vieta altri plugin">
+<!ENTITY noscriptReloadWarn "Queste opzioni avranno effetto nelle nuove pagine e in quelle ricaricate (manualmente)">
+<!ENTITY noscriptConfirmUnblock "Chiedi conferma prima di sbloccare temporaneamente un oggetto">
+<!ENTITY noscriptStatusLabel "Etichetta sulla barra di stato">
+<!ENTITY noscriptForbidBookmarklets "Vieta i bookmarklet">
+<!ENTITY noscriptShowPlaceholder "Mostra icona sostitutiva">
+<!ENTITY noscriptTruncateTitle "Tronca i titoli dei documenti">
+<!ENTITY noscriptFixLinks "Tenta di correggere i link JavaScript">
+<!ENTITY noscriptAllowBookmarks "Permetti tutti i siti presenti nei segnalibri">
+<!ENTITY noscriptAllowViaBookmarks "Permetti i siti aperti attraverso i segnalibri">
+<!ENTITY noscriptAllowPing "Permetti il ping dai collegamenti">
+<!ENTITY noscriptAllowLocalLinks "Permetti collegamenti locali">
+<!ENTITY noscriptForbidPing "Vieta il ping dai collegamenti">
+<!ENTITY noscriptForbidMetaRefresh "Blocca i reindirizzamenti META dall&apos;interno di elementi &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "Mostra messaggio quando un reindirizzamento META è bloccato">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "Lista fidata">
+<!ENTITY noscriptPermissions "Permessi">
+<!ENTITY noscriptRefresh "Aggiorna">
+<!ENTITY noscriptNotifications "Notifiche">
+<!ENTITY noscriptToolbarToggle "Il clic sinistro sul pulsante della barra inverte i permessi per il sito principale">
+<!ENTITY noscriptTrusted "Fidato">
+<!ENTITY noscriptUntrusted "Non fidato">
+<!ENTITY noscriptUnknown "Sconosciuto">
+<!ENTITY noscriptCustom "Personalizzato">
+<!ENTITY noscriptAdd "Aggiungi">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Chiudi">
+<!ENTITY noscriptSiteManager "Gestione Siti">
+<!ENTITY noscriptSecurityManager "Gestione Sicurezza">
+<!ENTITY noscriptPolicies "Politiche">
+<!ENTITY noscriptDefaultPolicies "Politiche predefinite">
+<!ENTITY noscriptSitePolicies "Politiche specifiche per i siti">
+<!ENTITY noscriptNselNever "Nascondi gli elementi &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Mostra l&apos;elemento &lt;NOSCRIPT&gt; che segue un elemento &lt;SCRIPT&gt; bloccato">
+<!ENTITY noscriptAutoAllowTopLevel "Permetti temporaneamente il sito principale in automatico">
+<!ENTITY noscriptDescription "Protezione aggiuntiva per Firefox: NoScript consente l&apos;esecuzione di JavaScript, di Java (e, opzionalmente, degli altri plugin) solo per domini fidati di tua scelta (es. la tua banca online). Questo blocco preventivo basato su whitelist impedisce lo sfruttamento di vulnerabiltà della sicurezza (sia note che addirittura ancora sconosciute!) li esperti confermeranno: Firefox è davvero più sicuro con NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Blocca gli scanner basati su CSS">
+<!ENTITY noscriptOptFilterXGet "Filtra le richieste sospette di XSS provenienti da siti non fidati">
+<!ENTITY noscriptOptFilterXPost "Neutralizza le richieste POST (upload) sospette di XSS provenienti da siti non fidati">
+<!ENTITY noscriptShowConsole "Mostra Console…">
+<!ENTITY noscriptShowConsole.accesskey "C">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "FAQ sul XSS…">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Ricarica senza protezione">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Eccezioni alla protezione XSS">
+<!ENTITY noscriptXssExceptions.description "Le destinazioni che corrispondono a queste espressioni regolari NON riceveranno protezione XSS.">
+<!ENTITY noscriptMatchSample "Esempio di corrispondenza:">
+<!ENTITY noscriptReset "Ripristina">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Ripristina i valori originali">
+<!ENTITY noscriptResetDef.accesskey "R">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revoca i permessi temporanei">
+<!ENTITY noscriptRevokeTemp.accesskey "t">
+<!ENTITY noscriptNoUntrustedPlaceholder "Non mostrare icona sostitutiva per elementi segnalati come non fidati">
+<!ENTITY noscriptCollapseBlockedObjects "Comprimi lo spazio occupato dagli oggetti bloccati">
+<!ENTITY noscriptExceptions "Eccezioni…">
+<!ENTITY noscriptBlockedObjects "Oggetti bloccati">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Blocca tutti gli oggetti provenienti da siti segnalati come non fidati">
+<!ENTITY noscriptTempAllowPage "Permetti temporaneamente tutta la pagina">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Permetti tutta la pagina">
+<!ENTITY noscriptAllowPage.accesskey "a">
+<!ENTITY noscriptTempToPerm "Rendi permanenti i permessi della pagina">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "FAQ su HTTPS…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Comportamento">
+<!ENTITY noscriptHttps.cookies "Cookie">
+<!ENTITY noscriptHttps.description "Proibisci i contenuti attivi dal web non serviti da HTTPS">
+<!ENTITY noscriptHttps.never "Mai">
+<!ENTITY noscriptHttps.proxy "Quando uso un proxy (raccomandato con Tor)">
+<!ENTITY noscriptHttps.always "Sempre">
+<!ENTITY noscriptHttpsForced "Costringi i seguenti siti a usare connessioni sicure (HTTPS):">
+<!ENTITY noscriptHttpsForcedExceptions "Non forzare mai connessioni sicure (HTTPS) per i seguenti siti:">
+<!ENTITY noscriptSecureCookies "Abilita la gestione automatica dei cookie sicuri">
+<!ENTITY noscriptSecureCookiesForced "Forza connessioni sicure per tutti i cookie creati in HTTPS dai seguenti siti:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignora i cookie non sicuri creati in HTTPS dai seguenti siti:">
+<!ENTITY noscriptClearClickTitle "Avviso di ClearClick">
+<!ENTITY noscriptClearClickHeader "Possibile tentativo di &quot;clickjacking&quot; o camuffamento">
+<!ENTITY noscriptClearClickDescription "NoScript ha intercettato un&apos;interazione del mouse o della tastiera con un elemento parzialmente nascosto. Cliccare sull&apos;immagine sotto per confrontare la versione ostruita con quella svelata.">
+<!ENTITY noscriptClearClickOpt "Abilita la protezione ClearClick sulle pagine…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "fidate">
+<!ENTITY noscriptUntrustedPagesAdj "non fidate">
+<!ENTITY noscriptKeepLocked "Mantieni bloccato questo elemento (consigliabile)">
+<!ENTITY noscriptEmbeddings "Oggetti incorporati">
+<!ENTITY noscriptPrev "Precedente">
+<!ENTITY noscriptNext "Successivo">
+<!ENTITY noscriptFrameOptErr.title "Questo contenuto non può essere caricato in un frame">
+<!ENTITY noscriptFrameOptErr.desc "Per proteggere la vostra sicurezza, l'autore di questo contenuto non permette che esso sia caricato in un frame.">
+<!ENTITY noscriptFrameOptErr.link "Cliccare qui per aprire questo contenuto in una nuova finestra.">
+<!ENTITY noscriptBookmarkSync "Copia la configurazione di NoScript in un segnalibro sincronizzabile">
+<!ENTITY noscriptShowReleaseNotes "Mostra le informazioni sulla versione dopo ogni aggiornamento">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Gruppi di regole:">
+<!ENTITY ABE.enabled.label "Abilita ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Permetti ai siti web di configurare le proprie regole">
+<!ENTITY ABE.edit.label "Modifica…">
+<!ENTITY ABE.edit.accesskey "M">
+<!ENTITY ABE.enable.label "Abilita">
+<!ENTITY ABE.enable.accesskey "A">
+<!ENTITY ABE.disable.label "Disabilita">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Aggiorna">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Disinstalla">
+<!ENTITY noscriptRecentBlocked "Siti bloccati di recente">
+<!ENTITY noscriptExternalFilters "Filtri esterni">
+<!ENTITY noscriptEF.enable "Abilita i filtri esterni">
+<!ENTITY noscriptEF.add "Crea filtro…">
+<!ENTITY noscriptEF.executable "File eseguibile:">
+<!ENTITY noscriptEF.browse "Sfoglia…">
+<!ENTITY noscriptEF.contentType "Tipo di contenuto (MIME) da filtrare (confronto esatto o espressione regolare):">
+<!ENTITY noscriptEF.exceptions "Non filtrare gli oggetti provenienti dai seguenti siti:">
+<!ENTITY noscriptEF.remove "Rimuovi">
+<!ENTITY noscriptPreset "Livello di sicurezza">
+<!ENTITY noscriptPreset.off "Nessuno (stai scherzando?!)">
+<!ENTITY noscriptPreset.low "Spensierato (Blacklist + Sicurezza Web)">
+<!ENTITY noscriptPreset.medium "Classico (Whitelist + Sicurezza Web)">
+<!ENTITY noscriptPreset.high "Fortezza (Protezione completa)">
+<!ENTITY noscript.hoverUI "Apri il menù dei permessi quando il mouse sorvola l'icona di NoScript">
+<!ENTITY noscriptDonate "Donazione">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Propaga i permessi del documento principale a tutti i sottodocumenti e agli script esterni">
+<!ENTITY noscriptRestrictSubdocScripting "Blocca gli script dei sottodocumenti se il documento principale non è nella whitelist">
+<!ENTITY noscriptGlobalHttpsWhitelist "Permetti automaticamente gli script HTTPS inclusi in documenti HTTPS">
+<!ENTITY noscriptPermanentInPrivate "Comandi &quot;Permetti&quot; permanenti nelle finestre private">
diff --git a/extensions/noscript/chrome/locale/it/noscript/noscript.properties b/extensions/noscript/chrome/locale/it/noscript/noscript.properties
new file mode 100644
index 0000000..bb11225
--- /dev/null
+++ b/extensions/noscript/chrome/locale/it/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Permetti gli script globalmente (pericoloso)
+forbidGlobal=Disabilita gli script globalmente (consigliato)
+allowLocal=Permetti %S
+allowTemp=Permetti %S temporaneamente
+forbidLocal=Vieta %S
+allowed.glb=Pericolo! Script abilitati globalmente
+allowed.yes=Esecuzione script attualmente permessa
+allowed.prt=Esecuzione script parzialmente permessa
+allowed.no=Esecuzione script attualmente vietata
+global.warning.title=Attenzione!
+global.warning.text=L'esecuzione degli script sta per essere abilitata globalmente (per tutti i siti).\n Si tratta di un'azione potenzialmente pericolosa.\nSi vuole davvero procedere?
+audio.samples=Campioni audio
+confirm=Sei sicuro?
+alwaysAsk=Chiedi sempre conferma
+notifyHide=Nascondi dopo %S secondi
+trust=Considera %S fidato
+distrust=Non fidarti di %S
+untrustedOrigin=una origine non fidata
+xss.notify.generic=NoScript ha filtrato un potenziale tentativo di cross-site scripting (XSS) da parte di %S. Vedere la Console per dettagli.
+xss.notify.showConsole=Mostra Console…
+xss.notify.showConsole.accessKey=C
+xss.reason.filterXGet=Richiesta sospetta filtrata. URL originale [%1$S] richiesto da [%2$S]. URL filtrato: [%3$S].
+xss.reason.filterXGetRef=Referente sospetto filtrato. URL [%1$S] richiesto da [%2$S]. Referente filtrato: [%3$S].
+xss.reason.filterXPost=Upload sospetto verso [%1$S] da [%2$S] bloccato e trasformato in una richiesta GET innocua.
+unsafeReload.warning=Sto per ricaricare SENZA FILTRI un\n\n%1$S [ %2$S ]\n\nDA [ %3$S ]\n\nNoScript NON proteggerà questa richiesta!\n
+metaRefresh.notify=Noscript ha bloccato un reindirizzamento <META> contenuto in un elemento <NOSCRIPT>: %S in %S secondi
+metaRefresh.notify.follow=Segui il reindirizzamento
+metaRefresh.notify.follow.accessKey=S
+notify.options=Opzioni
+notify.options.accessKey=O
+reset.title=Ripristino di NoScript
+reset.warning=Tutte le opzioni di NoScript, permessi inclusi, saranno ripristinate immediatamente al loro valore originale.\nQuesta azione non può essere invertita.\nSi vuole davvero continuare?
+bookmarkSync.title=Configurazione di NoScript
+bookmarkSync.message=Questo segnalibro non è pensato per essere aperto direttamente, ma per essere sincronizzato attraverso un servizio di sincronizzazione come Weave o l'estensione XMarks.
+bookmarkSync.confirm=NoScript ha trovato un segnalibro di configurazione apparentemente salvato in data\n%S.\nSi desidera davvero sovrascrivere la configurazione locale di NoScript con il contenuto di questo segnalibro?
+ABE.notify=Richiesta %1$S filtrata da ABE: <%2$S> %3$S
+ABE.chooseEditor=Scegliere un editor di testo per modificare le regole di ABE
+allowFrom=Permetti tutto da %S
+allowTempFrom=Permetti tutto da %S temporaneamente
+siteInfo.confirm=Stai per chiedere informazioni sul sito "%1$S"\neffettuando una richiesta a %2$S.\nVuoi continuare?
+siteInfo.tooltip=Per informazioni sul sito, clicca col pulsante centrale o premendo "maiuscole"...
+ABE.syntaxError=Errore di sintassi nelle regole ABE!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+ef.activate=Filtra %S
+ef.options=Opzioni di %S...
+ef.newName=Inserisci il nome del nuovo filtro:
+ef.locateExe=Seleziona l'eseguibile per il filtro %S
+disable=Disabilita %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/ja-JP/noscript/about.properties b/extensions/noscript/chrome/locale/ja-JP/noscript/about.properties
new file mode 100644
index 0000000..1a18d37
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ja-JP/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Firefoxã‚’ã•ã‚‰ã«å®‰å…¨ã«ã—ã¾ã™: NoScriptã¯JavaScript, Java(ãŠã‚ˆã³ãã®ä»–ã®ãƒ—ラグイン)をã€ï¼ˆã‚ãªãŸãŒä½¿ã†ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ãƒãƒ³ã‚­ãƒ³ã‚°ã‚µã‚¤ãƒˆãªã©ï¼‰ã‚ãªãŸãŒé¸ã‚“ã ä¿¡é ¼ã§ãるサイトã§ã®ã¿å®Ÿè¡Œå¯èƒ½ã«ã—ã¾ã™ã€‚ã“ã®ãƒ›ãƒ¯ã‚¤ãƒˆãƒªã‚¹ãƒˆã«ã‚ˆã‚‹äºˆé˜²çš„ブロック手法ã«ã‚ˆã£ã¦ã€æ©Ÿèƒ½æ€§ã‚’減ã˜ã‚‹ã“ã¨ãªã
+aboutTitle=%S ã«ã¤ã„ã¦
+extensionContributors=貢献者:
+extensionContributors.tip=People you should thank for this extension
+extensionCreatorLabel=作者:
+changelog=変更履歴
+changelog.tip=変更履歴を表示ã™ã‚‹
+license=ライセンス
+license.tip=ライセンスを読む
+logo.tip=拡張機能ã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’表示ã™ã‚‹
+sponsor.tip=スãƒãƒ³ã‚µãƒ¼ã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’表示ã™ã‚‹
+informaction.tip=InformActionã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’表示ã™ã‚‹
+extensionHomepage.tip=拡張機能ã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’表示ã™ã‚‹
+extensionCreator.tip=作者ã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’表示ã™ã‚‹
+version=ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %S
diff --git a/extensions/noscript/chrome/locale/ja-JP/noscript/noscript.dtd b/extensions/noscript/chrome/locale/ja-JP/noscript/noscript.dtd
new file mode 100644
index 0000000..fc889e9
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ja-JP/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "オプション...">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript オプション">
+<!ENTITY noscriptAbout "NoScript 5.1.8.5ã«ã¤ã„ã¦...">
+<!ENTITY noscriptPermissionsText "JavaScriptを許å¯ã™ã‚‹ã‚µã‚¤ãƒˆã‚’指定ã™ã‚‹äº‹ãŒã§ãã¾ã™ã€‚許å¯ã—ãŸã„サイトã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‹ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’入力ã—ã¦ã€ãƒœã‚¿ãƒ³ã‚’押ã—ã¦ãã ã•ã„。(例: &quot;http://www.site.com&quot; ã¾ãŸã¯ &quot;site.com&quot;)">
+<!ENTITY noscriptWebAddress "ウェブサイトã®ã‚¢ãƒ‰ãƒ¬ã‚¹:">
+<!ENTITY noscriptAllow "許å¯ã™ã‚‹">
+<!ENTITY noscriptAllow.accesskey "A">
+<!ENTITY noscriptForbid "ç¦æ­¢ã™ã‚‹">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "信頼済ã¿ã‚µã‚¤ãƒˆã«ã™ã‚‹">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "ä¿¡é ¼ã—ã¦ã„ãªã„サイトã«ã™ã‚‹">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "é¸æŠžä¸­ã®ã‚µã‚¤ãƒˆã‚’削除">
+<!ENTITY noscriptGloballyEnabled "ã™ã¹ã¦ã®ã‚µã‚¤ãƒˆã®JavaScriptを許å¯ã™ã‚‹ (å±é™º)">
+<!ENTITY noscriptAutoReload "許å¯è¨­å®šã‚’変更ã—ãŸã¨ãã«ãƒšãƒ¼ã‚¸ã‚’自動的ã«å†èª­è¾¼ã™ã‚‹">
+<!ENTITY noscriptGeneral "全般">
+<!ENTITY noscriptAppearance "インターフェース">
+<!ENTITY noscriptShow "外観...">
+<!ENTITY noscriptCtxMenu "コンテキストメニュー">
+<!ENTITY noscriptStatusIcon "ステータスãƒãƒ¼ã‚¢ã‚¤ã‚³ãƒ³">
+<!ENTITY noscriptFullAddr "フルアドレス (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "フルドメイン (www.noscript.net)">
+<!ENTITY noscriptBaseDom "セカンドレベル ドメイン (noscript.net)">
+<!ENTITY noscriptTempCmd "一時的ã«è¨±å¯ã™ã‚‹ [...]">
+<!ENTITY noscriptSound "スクリプトをブロックã—ãŸã¨ãã«ã‚µã‚¦ãƒ³ãƒ‰ã§é€šçŸ¥ã™ã‚‹">
+<!ENTITY noscriptImport "インãƒãƒ¼ãƒˆ">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "エクスãƒãƒ¼ãƒˆ">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "スクリプトをブロックã—ãŸã¨ãã«æƒ…報を表示ã™ã‚‹">
+<!ENTITY noscriptNotify.bottom "情報を下部ã«è¡¨ç¤ºã™ã‚‹">
+<!ENTITY noscriptSound.choose "é¸æŠž">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "å†ç”Ÿ">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "設定をリセット">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "詳細設定">
+<!ENTITY noscriptAdditionalPermissions "信頼済ã¿ã‚µã‚¤ãƒˆã¸ã®è¨±å¯ã®è¿½åŠ ">
+<!ENTITY noscriptAllowClipboard "クリップボードã‹ã‚‰ãƒªãƒƒãƒãƒ†ã‚­ã‚¹ãƒˆã®ã‚³ãƒ”ーã¨ãƒšãƒ¼ã‚¹ãƒˆã‚’å¯èƒ½ã«ã™ã‚‹">
+<!ENTITY noscriptAdditionalRestrictions "ä¿¡é ¼ã—ã¦ã„ãªã„サイトã¸ã®åˆ¶é™ã®è¿½åŠ ">
+<!ENTITY noscriptPlugins "プラグイン">
+<!ENTITY noscriptContentBlocker "ä¿¡é ¼ã—ã¦ã„るサイトã«ã‚‚ã“れらã®åˆ¶é™ã‚’é©ç”¨ã™ã‚‹">
+<!ENTITY noscriptForbidJava "Javaâ„¢ ã®ç¦æ­¢">
+<!ENTITY noscriptForbidXSLT "XSLT ã®ç¦æ­¢">
+<!ENTITY noscriptForbidSilverlight "Microsoft® Silverlightâ„¢ ã®ç¦æ­¢">
+<!ENTITY noscriptForbidIFrames "&lt;IFRAME&gt; ã®ç¦æ­¢">
+<!ENTITY noscriptForbidFrames "&lt;FRAMES&gt; ã®ç¦æ­¢">
+<!ENTITY noscriptForbidFlash "Adobe® Flash® ã®ç¦æ­¢">
+<!ENTITY noscriptForbidPlugins "ãã®ä»–ã®ãƒ—ラグインã®ç¦æ­¢">
+<!ENTITY noscriptReloadWarn "ã“れらã®ã‚ªãƒ—ションã¯æ–°ãŸã«é–‹ã„ãŸãƒšãƒ¼ã‚¸ã€ã¾ãŸã¯å†èª­è¾¼ã—ãŸãƒšãƒ¼ã‚¸ã§æœ‰åŠ¹ã«ãªã‚Šã¾ã™">
+<!ENTITY noscriptConfirmUnblock "オブジェクトを一時的ã«è¨±å¯ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹">
+<!ENTITY noscriptStatusLabel "ステータスãƒãƒ¼ãƒ©ãƒ™ãƒ«">
+<!ENTITY noscriptForbidBookmarklets "ブックマークレットã®ç¦æ­¢">
+<!ENTITY noscriptShowPlaceholder "プレースホルダーアイコンを表示ã™ã‚‹">
+<!ENTITY noscriptTruncateTitle "ページタイトルを切り詰ã‚ã‚‹">
+<!ENTITY noscriptFixLinks "JavaScriptリンクã®ä¿®æ­£ã‚’試ã¿ã‚‹">
+<!ENTITY noscriptAllowBookmarks "ブックマークã«ã‚ã‚‹å…¨ã¦ã®ã‚µã‚¤ãƒˆã‚’許å¯ã™ã‚‹">
+<!ENTITY noscriptAllowViaBookmarks "ブックマークã‹ã‚‰é–‹ã„ãŸã‚µã‚¤ãƒˆã‚’許å¯ã™ã‚‹">
+<!ENTITY noscriptAllowPing "&lt;A PING...&gt;を許å¯ã™ã‚‹">
+<!ENTITY noscriptAllowLocalLinks "ローカルリンクを許å¯ã™ã‚‹">
+<!ENTITY noscriptForbidPing "&lt;A PING...&gt;ã‚’ç¦æ­¢ã™ã‚‹">
+<!ENTITY noscriptForbidMetaRefresh "&lt;NOSCRIPT&gt;è¦ç´ å†…ã§ã®METAリダイレクションをç¦æ­¢ã™ã‚‹">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptWhitelist "ホワイトリスト">
+<!ENTITY noscriptPermissions "アクセス許å¯">
+<!ENTITY noscriptRefresh "æ›´æ–°">
+<!ENTITY noscriptNotifications "通知">
+<!ENTITY noscriptToolbarToggle "NoScriptツールãƒãƒ¼ãƒœã‚¿ãƒ³ã®å·¦ã‚¯ãƒªãƒƒã‚¯ã§ç¾åœ¨ã®ãƒˆãƒƒãƒ—レベルサイトã®è¨±å¯è¨­å®šã‚’トグルã™ã‚‹">
+<!ENTITY noscriptTrusted "信頼済ã¿">
+<!ENTITY noscriptUntrusted "ä¿¡é ¼ã—ã¦ã„ãªã„">
+<!ENTITY noscriptUnknown "ä¸æ˜Ž">
+<!ENTITY noscriptAdd "追加">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "é–‰ã˜ã‚‹">
+<!ENTITY noscriptSiteManager "サイト管ç†è€…">
+<!ENTITY noscriptSecurityManager "セキュリティ管ç†è€…">
+<!ENTITY noscriptPolicies "ãƒãƒªã‚·ãƒ¼">
+<!ENTITY noscriptDefaultPolicies "デフォルトãƒãƒªã‚·ãƒ¼">
+<!ENTITY noscriptSitePolicies "サイト固有ã®ãƒãƒªã‚·ãƒ¼">
+<!ENTITY noscriptNselNever "&lt;NOSCRIPT&gt;è¦ç´ ã‚’éš ã™">
+<!ENTITY noscriptNselForce "ブロックã—ãŸ&lt;SCRIPT&gt;ã«å¼•ã続ã&lt;NOSCRIPT&gt;を表示ã™ã‚‹">
+<!ENTITY noscriptAutoAllowTopLevel "トップレベルサイトã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ä¸€æ™‚çš„ã«è¨±å¯ã™ã‚‹">
+<!ENTITY noscriptDescription "Firefoxã‚’ã•ã‚‰ã«å®‰å…¨ã«ã—ã¾ã™: NoScriptã¯JavaScript, Java(ãŠã‚ˆã³ãã®ä»–ã®ãƒ—ラグイン)をã€ï¼ˆã‚ãªãŸãŒä½¿ã†ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ãƒãƒ³ã‚­ãƒ³ã‚°ã‚µã‚¤ãƒˆãªã©ï¼‰ã‚ãªãŸãŒé¸ã‚“ã ä¿¡é ¼ã§ãるサイトã§ã®ã¿å®Ÿè¡Œå¯èƒ½ã«ã—ã¾ã™ã€‚ã“ã®ãƒ›ãƒ¯ã‚¤ãƒˆãƒªã‚¹ãƒˆã«ã‚ˆã‚‹äºˆé˜²çš„ブロック手法ã«ã‚ˆã£ã¦ã€æ©Ÿèƒ½æ€§ã‚’減ã˜ã‚‹ã“ã¨ãªã(既知ã®ã‚‚ã®ã§ã‚‚未知ã®ã‚‚ã®ã§ã‚‚!)セキュリティ脆弱性ã¸ã®æ”»æ’ƒã‚’阻止ã—ã¾ã™...専門家ã¯ã€NoScriptã«ã‚ˆã£ã¦FireFoxãŒæœ¬å½“ã«ã‚ˆã‚Šå®‰å…¨ã«ãªã‚‹ã¨è¨€ã†ã“ã¨ã«åŒæ„ã™ã‚‹ã§ã—ょã†:-)">
+<!ENTITY noscriptOptBlockCssScanners "CSSベースã®ã‚¹ã‚­ãƒ£ãƒŠã‚’ブロックã™ã‚‹">
+<!ENTITY noscriptOptFilterXGet "クロスサイトã®ç–‘ã„ã®ã‚るリクエストをサニタイズã™ã‚‹">
+<!ENTITY noscriptOptFilterXPost "クロスサイトã®POSTリクエストをã€åŒã˜æƒ…報をæŒã¤GETリクエストã«å¤‰æ›ã™ã‚‹">
+<!ENTITY noscriptShowConsole "エラーコンソールを表示ã™ã‚‹...">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "安全ã§ãªã„å†èª­ã¿è¾¼ã¿">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "対XSSä¿è­·ã®ä¾‹å¤–設定">
+<!ENTITY noscriptXssExceptions.description "ã“れらã®æ­£è¦è¡¨ç¾ã«ãƒžãƒƒãƒãƒ³ã‚°ã™ã‚‹é€ã‚Šå…ˆã¯XSSã‹ã‚‰ä¿è­·ã•ã‚Œã¾ã›ã‚“">
+<!ENTITY noscriptMatchSample "パターンマッãƒãƒ³ã‚°ã®ä¾‹:">
+<!ENTITY noscriptReset "リセット">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "デフォルトã«åˆæœŸåŒ–">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "一時的ãªè¨±å¯ã‚’å–り消ã™">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "ä¿¡é ¼ã§ããªã„ã¨è¨˜éŒ²ã•ã‚ŒãŸã‚µã‚¤ãƒˆã‹ã‚‰ã®ã‚ªãƒ–ジェクトã«ã¯ãƒ—レースホルダーを表示ã—ãªã„">
+<!ENTITY noscriptCollapseBlockedObjects "ブロックã—ãŸã‚ªãƒ–ジェクトを折りãŸãŸã‚€">
+<!ENTITY noscriptExceptions "例外...">
+<!ENTITY noscriptBlockedObjects "ブロックã—ãŸã‚ªãƒ–ジェクト">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "ä¿¡é ¼ã§ããªã„ã¨è¨˜éŒ²ã•ã‚ŒãŸã‚µã‚¤ãƒˆã‹ã‚‰ã®å…¨ã¦ã®ã‚ªãƒ–ジェクトをブロックã™ã‚‹">
+<!ENTITY noscriptTempAllowPage "ã“ã®ãƒšãƒ¼ã‚¸ã®å…¨ã¦ã‚’一時的ã«è¨±å¯ã™ã‚‹">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "ã“ã®ãƒšãƒ¼ã‚¸ã®å…¨ã¦ã‚’許å¯ã™ã‚‹">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "ページã®è¨±å¯è¨­å®šã‚’æ’ä¹…çš„ã«ã™ã‚‹">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ...">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "振る舞ã„">
+<!ENTITY noscriptHttps.cookies "Cookie">
+<!ENTITY noscriptHttps.description "セキュアãª(HTTPS)接続ã«ã‚ˆã‚‰ãªã„動的コンテンツを:">
+<!ENTITY noscriptHttps.never "常ã«è¨±å¯ã™ã‚‹">
+<!ENTITY noscriptHttps.proxy "プロキシを使ã£ã¦ã„ã‚‹ã¨ãã«ç¦æ­¢ã™ã‚‹(Torã§ã®æŽ¨å¥¨)">
+<!ENTITY noscriptHttps.always "常ã«ç¦æ­¢ã™ã‚‹">
+<!ENTITY noscriptHttpsForced "以下ã®ã‚µã‚¤ãƒˆã«å¯¾ã—ã¦ã¯ã‚»ã‚­ãƒ¥ã‚¢ãª(HTTPS)接続を強制ã™ã‚‹:">
+<!ENTITY noscriptHttpsForcedExceptions "以下ã®ã‚µã‚¤ãƒˆã«å¯¾ã—ã¦ã¯ã‚»ã‚­ãƒ¥ã‚¢ãª(HTTPS)接続を強制ã—ãªã„:">
+<!ENTITY noscriptSecureCookies "自動セキュアCookie管ç†ã‚’有効ã«ã™ã‚‹">
+<!ENTITY noscriptSecureCookiesForced "以下ã®ã‚µã‚¤ãƒˆã‹ã‚‰ã®HTTPSã«ã‚ˆã£ã¦ã‚»ãƒƒãƒˆã•ã‚ŒãŸå…¨ã¦ã®cookieã®æš—å·åŒ–を強制ã™ã‚‹:">
+<!ENTITY noscriptSecureCookiesExceptions "以下ã®ã‚µã‚¤ãƒˆã‹ã‚‰ã®HTTPSã«ã‚ˆã£ã¦ã‚»ãƒƒãƒˆã•ã‚ŒãŸå®‰å…¨ã§ãªã„cookieを無視ã™ã‚‹:">
+<!ENTITY noscriptClearClickTitle "ClearClick警告">
+<!ENTITY noscriptClearClickHeader "Clickjacking / UI Redressingã®å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™!">
+<!ENTITY noscriptClearClickDescription "NoScriptã¯éƒ¨åˆ†çš„ã«éš ã•ã‚ŒãŸè¦ç´ ã¸ã®ãƒžã‚¦ã‚¹ã‚„キーボードã®é–¢ä¸Žã‚’阻止ã—ã¾ã—ãŸã€‚上部ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’クリックã™ã‚‹ã“ã¨ã§ã€é®ã‚‰ã‚Œã¦ã„る版ã¨é®ã‚‰ã‚Œã¦ã„ãªã„版を交互ã«è¡¨ç¤ºã—ã¾ã™ã€‚">
+<!ENTITY noscriptClearClickOpt "ClearClickä¿è­·ã‚’è¡Œã†:">
+<!ENTITY noscriptClearClickReport "レãƒãƒ¼ãƒˆ">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "レãƒãƒ¼ãƒˆID:">
+<!ENTITY noscriptTrustedPagesAdj "ä¿¡é ¼ã—ã¦ã„るページ">
+<!ENTITY noscriptUntrustedPagesAdj "ä¿¡é ¼ã—ã¦ã„ãªã„ページ">
+<!ENTITY noscriptKeepLocked "ã“ã®è¦ç´ ã‚’ロックã—ãŸã¾ã¾ã«ã™ã‚‹(推奨)">
+<!ENTITY noscriptEmbeddings "埋ã‚è¾¼ã¿ã‚ªãƒ–ジェクト">
+<!ENTITY noscriptPrev "å‰">
+<!ENTITY noscriptNext "次">
+<!ENTITY noscriptFrameOptErr.title "ã“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¯ãƒ•ãƒ¬ãƒ¼ãƒ å†…ã«è¡¨ç¤ºã§ãã¾ã›ã‚“">
+<!ENTITY noscriptFrameOptErr.desc "セキュリティをä¿è­·ã™ã‚‹ãŸã‚ã«ã€ã“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®ç™ºè¡Œè€…ã¯ã‚³ãƒ³ãƒ†ãƒ³ãƒ„をフレーム内ã«è¡¨ç¤ºã™ã‚‹ã“ã¨ã‚’ç¦æ­¢ã—ã¦ã„ã¾ã™ã€‚">
+<!ENTITY noscriptFrameOptErr.link "ã“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã‚’æ–°ã—ã„ウィンドウã§é–‹ãã«ã¯ã€ã“ã“をクリックã—ã¾ã™">
+<!ENTITY noscriptBookmarkSync "ç°¡å˜ã«åŒæœŸã§ãるよã†ã«ã€NoScriptã®è¨­å®šã‚’ブックマークã«ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã—ã¾ã™">
+<!ENTITY noscriptShowReleaseNotes "アップデート時ã«ãƒªãƒªãƒ¼ã‚¹ãƒŽãƒ¼ãƒˆã‚’表示ã™ã‚‹">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "ルールセット:">
+<!ENTITY ABE.enabled.label "ABE(Application Boundaries Enforcer)を有効ã«ã™ã‚‹">
+<!ENTITY ABE.siteEnabled.label "サイトãŒè‡ªåˆ†è‡ªèº«ã®ãƒ«ãƒ¼ãƒ«ã‚»ãƒƒãƒˆã‚’プッシュã™ã‚‹ã®ã‚’許å¯ã™ã‚‹">
+<!ENTITY ABE.edit.label "編集...">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "有効">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "無効">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "æ›´æ–°">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "アンインストール">
+<!ENTITY noscriptRecentBlocked "最近ブロックã—ãŸã‚µã‚¤ãƒˆ">
+<!ENTITY noscriptForbidFonts "@font-face ã®ç¦æ­¢">
+<!ENTITY noscriptForbidWebGL "WebGL ã®ç¦æ­¢">
+<!ENTITY noscriptForbidMedia "&lt;AUDIO&gt; / &lt;VIDEO&gt; ã®ç¦æ­¢">
+<!ENTITY noscriptNotifyMeta "ブロックã—ãŸãƒ¡ã‚¿ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã«ã¤ã„ã¦ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã™ã‚‹">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptExternalFilters "外部フィルタ">
+<!ENTITY noscriptEF.enable "外部フィルタを有効ã«ã™ã‚‹">
+<!ENTITY noscriptEF.add "æ–°ã—ã„フィルタ...">
+<!ENTITY noscriptEF.executable "実行å¯â€‹â€‹èƒ½ãƒ•ã‚¡ã‚¤ãƒ«ï¼š">
+<!ENTITY noscriptEF.browse "å‚ç…§...">
+<!ENTITY noscriptEF.contentType "コンテンツタイプ(MIME)ã«ã‚ˆã‚‹ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ï¼ˆå®Œå…¨ä¸€è‡´ã¾ãŸã¯æ­£è¦è¡¨ç¾ï¼‰ï¼š">
+<!ENTITY noscriptEF.exceptions "ã“れらã®ã‚µã‚¤ãƒˆã‹ã‚‰ã®ãƒ•ã‚£ãƒ«ã‚¿ã‚ªãƒ–ジェクトã¯ã—ãªã„:">
+<!ENTITY noscriptEF.remove "削除">
+<!ENTITY noscriptPreset "セキュリティレベル">
+<!ENTITY noscriptPreset.off "オフ(本気?!)">
+<!ENTITY noscriptPreset.low "ç°¡å˜ã«ï¼ˆãƒ–ラックリスト+Webセキュリティ)">
+<!ENTITY noscriptPreset.medium "クラシック(ホワイトリスト+Webセキュリティ)">
+<!ENTITY noscriptPreset.high "è¦å¡žï¼ˆå…¨ã¦ç¦æ­¢ï¼‰">
+<!ENTITY noscript.hoverUI "NoScriptアイコンã®ä¸Šã«ãƒžã‚¦ã‚¹ã‚’移動ã—ãŸæ™‚ã«ã‚¢ã‚¯ã‚»ã‚¹è¨±å¯ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’é–‹ã">
+<!ENTITY noscriptDonate "寄付">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/ja-JP/noscript/noscript.properties b/extensions/noscript/chrome/locale/ja-JP/noscript/noscript.properties
new file mode 100644
index 0000000..1fbbc84
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ja-JP/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=ã™ã¹ã¦ã®ã‚µã‚¤ãƒˆã®JavaScriptを許å¯ã™ã‚‹ (å±é™º)
+forbidGlobal=ã™ã¹ã¦ã®ã‚µã‚¤ãƒˆã®JavaScriptã‚’ç¦æ­¢ã™ã‚‹ (推奨)
+allowLocal=%Sを許å¯
+allowTemp=%Sを一時的ã«è¨±å¯
+forbidLocal=%Sã‚’ç¦æ­¢
+allowed.glb=å±é™º! JavaScriptã¯ã™ã¹ã¦ã®ã‚µã‚¤ãƒˆã§æœ‰åŠ¹ã§ã™
+allowed.yes=JavaScriptã¯ç¾åœ¨è¨±å¯ã•ã‚Œã¦ã„ã¾ã™
+allowed.prt=JavaScriptã¯ä¸€éƒ¨è¨±å¯ã•ã‚Œã¦ã„ã¾ã™
+allowed.no=JavaScriptã¯ç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™
+global.warning.title=警告!
+global.warning.text=JavaScriptã‚’ã™ã¹ã¦ã®ã‚µã‚¤ãƒˆã§è¨±å¯ã—ã¾ã™ã€‚\nã“ã‚Œã¯ã‚‚ã—ã‹ã™ã‚‹ã¨å±é™ºãªã“ã¨ã§ã™ã€‚\n本当ã«ç¶šè¡Œã—ã¾ã™ã‹?
+audio.samples=オーディオ サンプル
+confirm=本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹?
+alwaysAsk=常ã«ç¢ºèªã™ã‚‹
+notifyHide=%S 秒後ã«éš ã™
+trust=%Sã‚’ä¿¡é ¼ã™ã‚‹
+distrust=%Sã‚’ä¿¡é ¼ã§ããªã„サイトã¨ã—ã¦è¨˜éŒ²ã™ã‚‹
+untrustedOrigin=ä¿¡é ¼ã§ããªã„原因
+xss.notify.generic=NoScriptã¯%Sã‹ã‚‰ã®ã‚¯ãƒ­ã‚¹ã‚µã‚¤ãƒˆã‚¹ã‚¯ãƒªãƒ—ティング(XSS)ã®å¯èƒ½æ€§ã®ã‚るアクセスをé®æ–­ã—ã¾ã—ãŸã€‚技術的ãªè©³ç´°ã¯ã‚¨ãƒ©ãƒ¼ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã«è¨˜éŒ²ã•ã‚Œã¦ã„ã¾ã™ã€‚
+xss.notify.showConsole=エラーコンソールã®è¡¨ç¤º...
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=ç–‘ã‚ã—ã„リクエストをサニタイズã—ã¾ã—ãŸã€‚å…ƒã®URLã¯[%2$S]ã‹ã‚‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆã•ã‚ŒãŸ[%1$S]。サニタイズã—ãŸURL: [%3$S]
+xss.reason.filterXGetRef=ç–‘ã‚ã—ã„リファラをサニタイズã—ã¾ã—ãŸã€‚[%2$S]ã‹ã‚‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆã•ã‚ŒãŸURL[%1$S]。サニタイズã—ãŸãƒªãƒ•ã‚¡ãƒ¬ãƒ³ã‚¹: [%3$S]
+xss.reason.filterXPost=[%2$S]ã‹ã‚‰[%1$S]ã¸ã®ç–‘ã‚ã—ã„アップロードをサニタイズã—ã¾ã—ãŸ: ダウンロードã®ã¿ã®GETリクエストã«å¤‰æ›ã—ã¾ã—ãŸã€‚
+unsafeReload.warning=UNSAFELY reloading a suspicious\n\n%1$S [%2$S]\n\nFROM [%3$S]\n\nNoScriptã¯ã“ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’ä¿è­·ã—ã¾ã›ã‚“ï¼\n
+metaRefresh.notify=NoScriptã¯<NOSCRIPT>è¦ç´ å†…ã®<META>リダイレクトをブロックã—ã¾ã—ãŸ: %S ã« %S 秒後ã«ç§»å‹•ã€‚
+metaRefresh.notify.follow=リダイレクトã«å¾“ã†
+metaRefresh.notify.follow.accessKey=F
+notify.options=オプション
+notify.options.accessKey=O
+reset.title=NoScriptã®ãƒªã‚»ãƒƒãƒˆ
+reset.warning=NoScriptã®å…¨ã¦ã®è¨­å®šã¨ã‚µã‚¤ãƒˆã¸ã®è¨±å¯ã¯ç›´ã¡ã«ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ã«åˆæœŸåŒ–ã•ã‚Œã€å…ƒã«ã¯æˆ»ã›ã¾ã›ã‚“。\n本当ã«å®Ÿè¡Œã—ã¾ã™ã‹ï¼Ÿ
+bookmarkSync.title=NoScript設定ã®ãƒ–ックマーク
+bookmarkSync.message=ã“ã®ãƒ–ックマークã¯ãƒšãƒ¼ã‚¸ã‚’é–‹ããŸã‚ã®ã‚‚ã®ã§ã¯ãªãã€Weaveã‚„XMarksæ‹¡å¼µã®ã‚ˆã†ãªã‚µãƒ¼ãƒ“スを使ã£ã¦åŒæœŸã™ã‚‹ãŸã‚ã®ã‚‚ã®ã§ã™ã€‚
+bookmarkSync.confirm=NoScriptã¯%Sã«ä¿å­˜ã•ã‚ŒãŸã‚‰ã—ã„設定ブックマークを発見ã—ã¾ã—ãŸã€‚\n
+ABE.notify=è¦æ±‚%1$Sã¯ABEã«ã‚ˆã£ã¦ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã•ã‚Œã¾ã—ãŸ: <%2$S> %3$S
+ABE.chooseEditor=ABEルールセットã®ãŸã‚ã®ãƒ†ã‚­ã‚¹ãƒˆã‚¨ãƒ‡ã‚£ã‚¿ã‚’é¸æŠžã—ã¦ãã ã•ã„
+allowFrom=%Sã‹ã‚‰ã®å…¨ã¦ã‚’許å¯ã™ã‚‹
+allowTempFrom=%Sã‹ã‚‰ã®å…¨ã¦ã‚’一時的ã«è¨±å¯ã™ã‚‹
+ABE.syntaxError=ABEルールセットã®æ§‹æ–‡ã‚¨ãƒ©ãƒ¼ã§ã™ï¼
+ABE.wanIpAsLocal=WAN IP (%S) ∈ ローカル
+siteInfo.confirm=ã‚ãªãŸãŒè¨ªå•ã™ã‚‹ã‚µã‚¤ãƒˆ"%1$S"ã§ã¯\n%2$Sã«ã‚¯ã‚¨ãƒªã‚’é€ä¿¡ã—ã¾ã™ã€‚\n続行ã—ã¾ã™ã‹ï¼Ÿ
+siteInfo.tooltip=ミドルクリックã¾ãŸã¯shift+クリックã§ã‚µã‚¤ãƒˆæƒ…å ±...
+ef.activate=フィルター%S
+ef.options=%Sオプション...
+ef.newName=æ–°ã—ã„フィルタã®åå‰ã‚’入力:
+ef.locateExe=%Sã®ãƒ•ã‚£ãƒ«ã‚¿ã®å®Ÿè¡Œå¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã™ã‚‹
+disable=無効%S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/kk-KZ/noscript/about.properties b/extensions/noscript/chrome/locale/kk-KZ/noscript/about.properties
new file mode 100644
index 0000000..6a4f7de
--- /dev/null
+++ b/extensions/noscript/chrome/locale/kk-KZ/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Firefox үшін ÑкÑтра қорғаныÑ: NoScript көмегімен Ñіз JavaScript, Java (және баÑқа плагиндер) орындалуын тек өзіңіз көрÑеткен домендер үшін Ñ€Ò±Ò›Ñат ете алаÑыз (мыÑалы, өзіңіздің веб-Ñайтыңыз). РұқÑат етілген тізім, алдын-ала блоктауға негізделіп, функционалдылыққа Ó™Ñер етпей-ақ оÑалдылықтардың алдын алуға көмектеÑеді (белгілі және белгіÑіз!)… Мамандар келіÑеді: NoScript қолдану Firefox жұмыÑын қауіпÑіз етеді:-)
+aboutTitle=%S туралы
+extensionContributors=ҮлеÑін қоÑқандар:
+extensionContributors.tip=ОÑÑ‹ кеңейтуді жаÑауға көмектеÑкендер
+extensionCreatorLabel=Ðвторы:
+changelog=ÐÒ±Ñқалар тарихы
+changelog.tip=ÐÒ±Ñқалар тарихын көрÑету
+license=ЛицензиÑÑÑ‹
+license.tip=Пайдаланушы лицензиÑÑын оқу
+logo.tip=Кеңейтудің үй парағы
+sponsor.tip=Демеушілердің үй парағы
+informaction.tip=InformAction үй парағы
+extensionHomepage.tip=Кеңейтудің үй парағы
+extensionCreator.tip=Ðвтордың үй парағы
+version=%S нұÑқаÑÑ‹
diff --git a/extensions/noscript/chrome/locale/kk-KZ/noscript/noscript.dtd b/extensions/noscript/chrome/locale/kk-KZ/noscript/noscript.dtd
new file mode 100644
index 0000000..35f54c4
--- /dev/null
+++ b/extensions/noscript/chrome/locale/kk-KZ/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Баптаулары">
+<!ENTITY noscriptOptions.accesskey "Б">
+<!ENTITY noscriptOptionsLong "NoScript баптаулары">
+<!ENTITY noscriptAbout "NoScript 5.1.8.5 туралы...">
+<!ENTITY noscriptPermissionsText "Қай Ñайттарға JavaScript орындауға Ñ€Ò±Ò›Ñат екенін көрÑете алаÑыз. РұқÑат етілетін Ñайттың домен адреÑін енгізіңіз (мыÑалы, &quot;http://www.site.com&quot; немеÑе &quot;site.com&quot;), Ñодан кейін РұқÑат ету баÑыңыз.">
+<!ENTITY noscriptWebAddress "Веб-Ñайт адреÑÑ–:">
+<!ENTITY noscriptAllow "РұқÑат ету">
+<!ENTITY noscriptAllow.accesskey "Р">
+<!ENTITY noscriptForbid "Тыйым Ñалу">
+<!ENTITY noscriptForbid.accesskey "Ñ‹">
+<!ENTITY noscriptTrust "РұқÑат етілген деп белгілеу">
+<!ENTITY noscriptTrust.accesskey "Ñ">
+<!ENTITY noscriptUntrust "Тыйым Ñалынған деп белгілеу">
+<!ENTITY noscriptUntrust.accesskey "н">
+<!ENTITY noscriptRemoveSelected "Ерекшеленген Ñайттарды өшіру">
+<!ENTITY noscriptGloballyEnabled "JavaScript толық Ñ€Ò±Ò›Ñат етілген (қауіпті)">
+<!ENTITY noscriptAutoReload "Ережелер өзгергенде оған қатыÑÑ‚Ñ‹ парақтарды жаңарту">
+<!ENTITY noscriptGeneral "Жалпы">
+<!ENTITY noscriptAppearance "Түрі">
+<!ENTITY noscriptShow "КөрÑету...">
+<!ENTITY noscriptCtxMenu "КонтекÑÑ‚ мәзірінде көрÑету">
+<!ENTITY noscriptStatusIcon "Қалып-күй жолағында көрÑету">
+<!ENTITY noscriptFullAddr "ÐдреÑтер толығымен (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Домендер толығымен (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Базалық 2-ші деңгейлі домендер (noscript.net)">
+<!ENTITY noscriptTempCmd "Уақытша Ñ€Ò±Ò›Ñат ету […]">
+<!ENTITY noscriptSound "Скриптерді блоктау кезінде аудио Ñигнал беру">
+<!ENTITY noscriptImport "Импорт">
+<!ENTITY noscriptImport.accesskey "м">
+<!ENTITY noscriptExport "ЭкÑпорт">
+<!ENTITY noscriptExport.accesskey "к">
+<!ENTITY noscriptNotify "Блокталған Ñкриптер туралы хабарлама көрÑету">
+<!ENTITY noscriptNotify.bottom "Терезенің аÑтынан хабарлама көрÑету">
+<!ENTITY noscriptSound.choose "Таңдау">
+<!ENTITY noscriptSound.choose.accesskey "д">
+<!ENTITY noscriptSound.play "Ойнау">
+<!ENTITY noscriptSound.play.accesskey "й">
+<!ENTITY noscriptSound.reset "БаÑтапқы түріне келтіру">
+<!ENTITY noscriptSound.reset.accesskey "Ñ€">
+<!ENTITY noscriptAdvanced "Кеңейтілген">
+<!ENTITY noscriptAdditionalPermissions "Сенімді Ñайттар үшін кеңейтілген баптаулар">
+<!ENTITY noscriptAllowClipboard "Сыртқы алмаÑу буферінен көшіру/кіріÑтіруді Ñ€Ò±Ò›Ñат ету">
+<!ENTITY noscriptAdditionalRestrictions "СенімÑіз Ñайттар үшін кеңейтілген баптаулар">
+<!ENTITY noscriptPlugins "Плагиндер">
+<!ENTITY noscriptContentBlocker "Бұл шектеулерді Ñенімді Ñайттар үшін де қолдану">
+<!ENTITY noscriptForbidJava "Javaâ„¢-ға тыйым Ñалу">
+<!ENTITY noscriptForbidXSLT "XSLT үшін тыйым Ñалу">
+<!ENTITY noscriptForbidSilverlight "Microsoft® Silverlightâ„¢-қа тыйым Ñалу">
+<!ENTITY noscriptForbidIFrames "&lt;IFRAME&gt; тыйым Ñалу">
+<!ENTITY noscriptForbidFrames "&lt;FRAME&gt; тыйым Ñалу">
+<!ENTITY noscriptForbidFonts "@font-face тыйым Ñалу">
+<!ENTITY noscriptForbidWebGL "WebGL тыйым Ñалу">
+<!ENTITY noscriptForbidMedia "&lt;AUDIO&gt; / &lt;VIDEO&gt; тыйым Ñалу">
+<!ENTITY noscriptForbidFlash "Adobe® Flash® тыйым Ñалу">
+<!ENTITY noscriptForbidPlugins "БаÑқа плагиндерге тыйым Ñалу">
+<!ENTITY noscriptReloadWarn "Бұл баптаулар тек жаңа ашылған немеÑе қайта жүктелген (қолмен) парақтар үшін Ñ–Ñтейді">
+<!ENTITY noscriptConfirmUnblock "Объектті уақытша Ñ€Ò±Ò›Ñат ету алдында раÑтауды Ñұрау">
+<!ENTITY noscriptStatusLabel "Қалып-күй жолағындағы хабарламалар">
+<!ENTITY noscriptForbidBookmarklets "Bookmarklets қолдануға тыйым Ñалу">
+<!ENTITY noscriptShowPlaceholder "Блокталған Ñлементтің орнын қоршаумен көрÑету">
+<!ENTITY noscriptTruncateTitle "Құжаттың тым ұзын атын қыÑқарту">
+<!ENTITY noscriptFixLinks "JavaScript Ñілтемелерін өндеуді қолдану">
+<!ENTITY noscriptAllowBookmarks "Бетбелгілерден ашылған Ñайтқа Ñ€Ò±Ò›Ñат ету">
+<!ENTITY noscriptAllowViaBookmarks "Бетбелгілерден ашылған Ñайтқа Ñ€Ò±Ò›Ñат ету">
+<!ENTITY noscriptAllowPing "&lt;A PING…&gt; Ñ€Ò±Ò›Ñат ету">
+<!ENTITY noscriptAllowLocalLinks "Жергілікті Ñілтемелерді Ñ€Ò±Ò›Ñат ету">
+<!ENTITY noscriptForbidPing "&lt;A PING…&gt; тыйым Ñалу">
+<!ENTITY noscriptForbidMetaRefresh "&lt;NOSCRIPT&gt; Ñлементінің ішінде META бағдарлауды оқшаулау">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "ш">
+<!ENTITY noscriptNotifyMeta "Блокталған META бағдарлаулар жөнінде хабарлау">
+<!ENTITY noscriptNotifyMeta.accesskey "о">
+<!ENTITY noscriptWhitelist "РұқÑат етілген тізім">
+<!ENTITY noscriptPermissions "РұқÑаттар">
+<!ENTITY noscriptRefresh "Жаңарту">
+<!ENTITY noscriptNotifications "Хабарламалар">
+<!ENTITY noscriptToolbarToggle "NoScript таңбашаÑына шерту арқылы Ñайт үшін Ñ€Ò±Ò›Ñаттарды ауыÑтыру">
+<!ENTITY noscriptTrusted "Сенімді">
+<!ENTITY noscriptUntrusted "СенімÑіз">
+<!ENTITY noscriptUnknown "БелгіÑіз">
+<!ENTITY noscriptAdd "ҚоÑу">
+<!ENTITY noscriptAdd.accesskey "Ñ">
+<!ENTITY noscriptClose "Жабу">
+<!ENTITY noscriptSiteManager "Сайт менеджері">
+<!ENTITY noscriptSecurityManager "ҚауіпÑіздік менджері">
+<!ENTITY noscriptPolicies "Ережелер">
+<!ENTITY noscriptDefaultPolicies "БаÑтапқы ережелер">
+<!ENTITY noscriptSitePolicies "Сайтқа қатыÑÑ‚Ñ‹ ережелер">
+<!ENTITY noscriptNselNever "&lt;NOSCRIPT&gt; Ñлементтерін жаÑыру">
+<!ENTITY noscriptNselForce "Блокталған &lt;SCRIPT&gt; Ñоңынан келген &lt;NOSCRIPT&gt; Ñлементін көрÑету">
+<!ENTITY noscriptAutoAllowTopLevel "Уақытша жоғарғы деңгейлі Ñайттарға Ñ€Ò±Ò›Ñат беру">
+<!ENTITY noscriptDescription "Firefox үшін ÑкÑтра қорғаныÑ: NoScript көмегімен Ñіз JavaScript, Java (және баÑқа плагиндер) орындалуын тек өзіңіз көрÑеткен домендер үшін Ñ€Ò±Ò›Ñат ете алаÑыз (мыÑалы, өзіңіздің веб-Ñайтыңыз). РұқÑат етілген тізім, алдын-ала блоктауға негізделіп, мүмкіндіктерге Ó™Ñер етпей-ақ, оÑалдылықтардың алдын алуға көмектеÑеді (белгілі және белгіÑіз!)… Мамандар келіÑеді: NoScript қолдану Firefox жұмыÑын қауіпÑіз етеді:-)">
+<!ENTITY noscriptOptBlockCssScanners "CSS-негізделген Ñканерлерді оқшаулау">
+<!ENTITY noscriptOptFilterXGet "CSS Ñұранымдарын оқшаулау">
+<!ENTITY noscriptOptFilterXPost "Сайт аралық POST Ñұранымдарын мәліметі жоқ GET Ñұранымдарына айналдыру">
+<!ENTITY noscriptShowConsole "КонÑольді көрÑету...">
+<!ENTITY noscriptShowConsole.accesskey "у">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "Ð¥">
+<!ENTITY noscriptXssFaq "XSS жиі қойылатын Ñұрақтары...">
+<!ENTITY noscriptXssFaq.accesskey "й">
+<!ENTITY noscriptUnsafeReload "ҚауіпÑіз ÐµÐ¼ÐµÑ Ò›Ð°Ð¹Ñ‚Ð° жүктелу">
+<!ENTITY noscriptUnsafeReload.accesskey "з">
+<!ENTITY noscriptXssExceptions "Ðнти-XSS қорғаудың ерекше ережелері">
+<!ENTITY noscriptXssExceptions.description "Бұл маÑкаларға ÑÓ™Ð¹ÐºÐµÑ ÐºÐµÐ»ÐµÑ‚Ñ–Ð½ объектілер XSS қарÑÑ‹ ҚОРҒÐЛМÐЙДЫ.">
+<!ENTITY noscriptMatchSample "Шаблон мыÑалы:">
+<!ENTITY noscriptReset "ТаÑтау">
+<!ENTITY noscriptReset.accesskey "Ñ">
+<!ENTITY noscriptResetDef "БаÑтапқы түріне келтіру">
+<!ENTITY noscriptResetDef.accesskey "н">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Уақытша Ñ€Ò±Ò›Ñаттарды қайта шақыру">
+<!ENTITY noscriptRevokeTemp.accesskey "Ñ€">
+<!ENTITY noscriptNoUntrustedPlaceholder "СенімÑіз деп белгіленген Ñайттан келген объектілер үшін қоршау жоқ">
+<!ENTITY noscriptCollapseBlockedObjects "Блокталған объектілерді жинау">
+<!ENTITY noscriptExceptions "Ерекше ережелер...">
+<!ENTITY noscriptBlockedObjects "Блокталған объектілер">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "СенімÑіз деп белгіленген Ñайттан келген әр объектті блоктау">
+<!ENTITY noscriptTempAllowPage "Бұл парақтағы барлығына Ñ€Ò±Ò›Ñат ету">
+<!ENTITY noscriptTempAllowPage.accesskey "Ñ‚">
+<!ENTITY noscriptAllowPage "Бұл парақтағы бар құрамаÑына Ñ€Ò±Ò›Ñат ету">
+<!ENTITY noscriptAllowPage.accesskey "е">
+<!ENTITY noscriptTempToPerm "Орнатылған Ñ€Ò±Ò›Ñаттарды Ñақтау">
+<!ENTITY noscriptTempToPerm.accesskey "у">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS жиі қойылатын Ñұрақтары...">
+<!ENTITY noscriptHttpsFaq.accesskey "и">
+<!ENTITY noscriptHttps.behavior "Әрекеттері">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Қорғалған Ð±Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ (HTTPS) болмаÑа, активті веб-құраманы оқшаулау:">
+<!ENTITY noscriptHttps.never "Ешқашан">
+<!ENTITY noscriptHttps.proxy "ПрокÑи қолданған кезде (Tor Ò±Ñынылады)">
+<!ENTITY noscriptHttps.always "Әрқашан">
+<!ENTITY noscriptHttpsForced "КелеÑÑ– Ñайттар үшін қорғалған Ð±Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ (HTTPS) талап ету:">
+<!ENTITY noscriptHttpsForcedExceptions "КелеÑÑ– Ñайттар үшін қорғалған Ð±Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ (HTTPS) талап етпеу:">
+<!ENTITY noscriptSecureCookies "Automatic Secure Cookies Management қоÑу">
+<!ENTITY noscriptSecureCookiesForced "КелеÑÑ– Ñайттардан HTTPS арқылы алынатын cookies үшін шифрлеуді талап ету:">
+<!ENTITY noscriptSecureCookiesExceptions "КелеÑÑ– Ñайттардан HTTPS арқылы алынатын қауіпÑіз емеÑе cookies елемеу:">
+<!ENTITY noscriptClearClickTitle "ClearClick еÑкертулері">
+<!ENTITY noscriptClearClickHeader "Clickjacking мүмкін/UI өзгерту талабы">
+<!ENTITY noscriptClearClickDescription "NoScript жартылай жаÑырын Ñлементпен әрекетті шектеді. Ðйырмашылыған көру үшін Ñуреттерге шертіңіз.">
+<!ENTITY noscriptClearClickOpt "Парақтардағы ClearClick-қорғаныÑÑ‹...">
+<!ENTITY noscriptClearClickReport "Хабарлау">
+<!ENTITY noscriptClearClickReport.accesskey "Ñ€">
+<!ENTITY noscriptClearClickReportId "Хабарлау нөмірі:">
+<!ENTITY noscriptTrustedPagesAdj "Ñенімді">
+<!ENTITY noscriptUntrustedPagesAdj "ÑенімÑіз">
+<!ENTITY noscriptKeepLocked "Бұл Ñлементті блокталған күйінде қалдыру (Ò±Ñынылады)">
+<!ENTITY noscriptEmbeddings "ÒšÒ±Ñ€Ð°Ð¼Ð´Ð°Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ñ‚ÐµÑ€">
+<!ENTITY noscriptPrev "ÐлдыңғыÑÑ‹">
+<!ENTITY noscriptNext "КелеÑÑ–">
+<!ENTITY noscriptFrameOptErr.title "Бұл қарама фрейм ішінде көрÑетілмейді">
+<!ENTITY noscriptFrameOptErr.desc "Сіздің қауіпÑіздігіңізді еÑкере отырып, құраманы жариÑлаушы фреймде көрÑетілуді Ñ€Ò±Ò›Ñат етпейді.">
+<!ENTITY noscriptFrameOptErr.link "Бұл құраманы жаңа терезеде ашу үшін, оÑында шертіңіз">
+<!ENTITY noscriptBookmarkSync "NoScript баптауларын жеңіл ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ò¯ÑˆÑ–Ð½ кеңейту ішінде Ñақтау">
+<!ENTITY noscriptShowReleaseNotes "Жаңарту кезінде тарихын көрÑету">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "Ð">
+<!ENTITY ABE.rulesets.label "Ережелер жинақтары:">
+<!ENTITY ABE.enabled.label "ABE Ñ–Ñке қоÑу (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Сайттарға өздерінің ережелерін қолдануға Ñ€Ò±Ò›Ñат беру">
+<!ENTITY ABE.edit.label "Тузету...">
+<!ENTITY ABE.edit.accesskey "е">
+<!ENTITY ABE.enable.label "ҚоÑу">
+<!ENTITY ABE.enable.accesskey "Ñ">
+<!ENTITY ABE.disable.label "Сөндіру">
+<!ENTITY ABE.disable.accesskey "Ñ€">
+<!ENTITY ABE.refresh.label "Жаңарту">
+<!ENTITY ABE.refresh.accesskey "Ñ‚">
+<!ENTITY noscriptUninstall "Өшіру">
+<!ENTITY noscriptRecentBlocked "Соңғы блокталған Ñайттар">
+<!ENTITY noscriptExternalFilters "Сыртқы фильтрлер">
+<!ENTITY noscriptEF.enable "Сыртқы фильтрлерді Ñ–Ñке қоÑу">
+<!ENTITY noscriptEF.add "Жаңа фильтр…">
+<!ENTITY noscriptEF.executable "Орындалатын файл:">
+<!ENTITY noscriptEF.browse "Қалап шығу…">
+<!ENTITY noscriptEF.contentType "Фильтрленетін құрама түрі (MIME) (дәл ÑәйкеÑтік не қалыпты өрнек):">
+<!ENTITY noscriptEF.exceptions "Бұл Ñайттардан келген объекттерді фильтрлемеу:">
+<!ENTITY noscriptEF.remove "Өшіру">
+<!ENTITY noscriptPreset "ҚауіпÑіздік деңгейі">
+<!ENTITY noscriptPreset.off "Сөндіру (Шынымен ба?!)">
+<!ENTITY noscriptPreset.low "Жеңіл (Блоктізім + Веб қауіпÑіздігі)">
+<!ENTITY noscriptPreset.medium "Қалыпты (РұқÑат тізімі + Веб қауіпÑіздігі)">
+<!ENTITY noscriptPreset.high "Қамал (Қатаң)">
+<!ENTITY noscript.hoverUI "Тышқан NoScript таңбашаÑынан өткен кезде Ñ€Ò±Ò›Ñаттар мәзірін ашу">
+<!ENTITY noscriptDonate "Ðқшалай көмектеÑу">
+<!ENTITY noscriptDonate.accesskey "ш">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/kk-KZ/noscript/noscript.properties b/extensions/noscript/chrome/locale/kk-KZ/noscript/noscript.properties
new file mode 100644
index 0000000..056f3b8
--- /dev/null
+++ b/extensions/noscript/chrome/locale/kk-KZ/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=JavaScript толық Ñ€Ò±Ò›Ñат ету (қауіпті)
+forbidGlobal=JavaScript толық тыйым Ñалу (Ò±Ñынылады)
+allowLocal=%S Ñ€Ò±Ò›Ñат ету
+allowTemp=%S уақытша Ñ€Ò±Ò›Ñат ету
+forbidLocal=%S тыйым Ñалу
+allowed.glb=Ðазар аудырыңыз! JavaScript толық Ñ€Ò±Ò›Ñат етілген
+allowed.yes=JavaScript оÑÑ‹ парақта Ñ€Ò±Ò›Ñат етілген
+allowed.prt=JavaScript жартылай Ñ€Ò±Ò›Ñат етілген
+allowed.no=JavaScript оÑÑ‹ парақта тыйым Ñалынған
+global.warning.title=Ðазар аударыңыз!
+global.warning.text=JavaScript толығымен Ñ€Ò±Ò›Ñат етіледі (барлық веб-Ñайттар үшін).\n Бұл - қауіпті әрекет.\nШынымен жалғаÑтыруды қалайÑыз ба?
+audio.samples=Ðудио мыÑалы
+confirm=ОÑыны шынымен қалайÑыз ба?
+alwaysAsk=Әрқашан Ñ€Ò±Ò›Ñат Ñұрау
+notifyHide=%S Ñекундтан кейін жаÑыру
+trust=%S Ñ€Ò¯Ò›Ñат етілген деп белгілеу
+distrust=%S Ñ€Ò±Ò›Ñат етілмеген деп белгілеу
+untrustedOrigin=ÑенімÑіз көзі ретінде
+xss.notify.generic=NoScript мүмкін болған XSS-шабуылын (Ñайтаралық Ñкриптинг) %S адреÑінен оқшаулады. Техникалық ақпарат конÑольге жазылды.
+xss.notify.showConsole=КонÑольді көрÑету...
+xss.notify.showConsole.accessKey=К
+xss.reason.filterXGet=Күдікті Ñұраным оқшауланды. URL: [%1$S]. Сұраным келеÑÑ– парақтан Ñ‚Ò¯ÑÑ‚Ñ–: [%2$S]. Фильтрленген адреÑ: [%3$S]
+xss.reason.filterXGetRef=Күдікті Ñұраным көзі оқшауланды («referer»): URL: [%1$S] келеÑÑ– парақтан [%2$S]. Фильтрленген адреÑ: [%3$S]
+xss.reason.filterXPost=[%2$S] адреÑінен [%1$S] адреÑіне Ñ‚Ò¯Ñкен күдікті жүктеме оқшауланды: жүктелетін GET Ñұранымына ауыÑтырылды.
+unsafeReload.warning=ҚауіпÑіз ÐµÐ¼ÐµÑ Ò›Ð°Ð¹Ñ‚Ð° жүктеу талабы \n\n%1$S [%2$S]\n\nКелеÑіден [%3$S]\n\nNoScript бұл Ñұранымды қорғай ÐЛМÐЙДЫ!\n
+metaRefresh.notify=NoScript <NOSCRIPT> Ñлементінің ішінде <META>-бағдарлауды оқшаулады: %S, %S Ñек ішінде.
+metaRefresh.notify.follow=Бағдарлауға өту
+metaRefresh.notify.follow.accessKey=Ñ‚
+notify.options=Баптаулар
+notify.options.accessKey=Б
+reset.title=NoScript таÑтау
+reset.warning=БÐРЛЫҚ NoScript баптаулары мен Ñайттар үшін Ñ€Ò±Ò›Ñаттар баÑтапқы түріне келеді.\nБұл әрекетті қайтаруға болмайды.\nЖалғаÑтыру керек пе?
+bookmarkSync.title=NoScript баптау бетбелгіÑÑ–
+bookmarkSync.message=Бұл бетбелгі ашылуды ЕМЕС, бірақ Weave немеÑе XMarks кеңейтулері көмегімен Ñинхрондауды белгілейді.
+bookmarkSync.confirm=NoScript келеÑÑ– жерде Ñақталған бапталар бетбелгіÑін тапты\n%S.\nБұл бетбелгінің ұүрамамен өзіңіздің NoScript баптауларыңызды алмаÑтыруды шынымен қалайÑыз ба?
+ABE.notify=%1$S Ñұранымын ABE болдырмаған: <%2$S> %3$S
+ABE.chooseEditor=ABE ережелер жинақтары үшін мәтіндік редакторын таңдаңыз
+ABE.syntaxError=ABE ережеÑінде ÑинтакÑÐ¸Ñ Ò›Ð°Ñ‚ÐµÑÑ–!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=%S үшін барлығына Ñ€Ò±Ò›Ñат ету
+allowTempFrom=%S үшін барлығына уақытша Ñ€Ò±Ò›Ñат ету
+siteInfo.confirm=Сіз "%1$S" Ñайты туралы %2$S үшін Ñұранымды\nжіберуді қалағанÑыз. ЖалғаÑтырамыз ба?
+siteInfo.tooltip=Сайт ақпаратын қарау үшін ортамен не shift Ò±Ñтап шертіңіз...
+ef.activate=%S фильтрлеу
+ef.options=%S баптаулары...
+ef.newName=Жаңа фильтрдің атын енгізіңіз:
+ef.locateExe=%S фильтрі үшін орындалатын файлды таңдаңыз
+disable=%S Ñөндіру
+disable.accessKey=д
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/km-KH/noscript/about.properties b/extensions/noscript/chrome/locale/km-KH/noscript/about.properties
new file mode 100644
index 0000000..c380467
--- /dev/null
+++ b/extensions/noscript/chrome/locale/km-KH/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality... Experts will agree: Firefox is really safer with NoScript :-)
+aboutTitle=About %S
+extensionContributors=Contributors:
+extensionContributors.tip=People you should thank for this extension
+extensionCreatorLabel=Author:
+changelog=Changelog
+changelog.tip=Show changelog
+license=License
+license.tip=Read end-user license
+logo.tip=Visit extension home page
+sponsor.tip=Visit sponsor home page
+informaction.tip=Visit InformAction home page
+extensionHomepage.tip=Visit extension home page
+extensionCreator.tip=Visit author home page
+version=Version %S
diff --git a/extensions/noscript/chrome/locale/km-KH/noscript/noscript.dtd b/extensions/noscript/chrome/locale/km-KH/noscript/noscript.dtd
new file mode 100644
index 0000000..ac1170b
--- /dev/null
+++ b/extensions/noscript/chrome/locale/km-KH/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Options...">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript Options">
+<!ENTITY noscriptAbout "About NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. &quot;http://www.site.com&quot; or &quot;site.com&quot;) of the site you want to allow and then click Allow.">
+<!ENTITY noscriptWebAddress "Address of web site:">
+<!ENTITY noscriptAllow "Allow">
+<!ENTITY noscriptAllow.accesskey "A">
+<!ENTITY noscriptForbid "Forbid">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Mark as Trusted">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Mark as Untrusted">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Remove Selected Sites">
+<!ENTITY noscriptGloballyEnabled "Scripts Globally Allowed (dangerous)">
+<!ENTITY noscriptAutoReload "Automatically reload affected pages when permissions change">
+<!ENTITY noscriptGeneral "General">
+<!ENTITY noscriptAppearance "Appearance">
+<!ENTITY noscriptShow "Show...">
+<!ENTITY noscriptCtxMenu "Contextual menu">
+<!ENTITY noscriptStatusIcon "Status bar icon">
+<!ENTITY noscriptFullAddr "Full Addresses (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Full Domains (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Base 2nd level Domains (noscript.net)">
+<!ENTITY noscriptTempCmd "Temporarily allow [...]">
+<!ENTITY noscriptSound "Audio feedback when scripts are blocked">
+<!ENTITY noscriptImport "Import">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Export">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Show message about blocked scripts">
+<!ENTITY noscriptNotify.bottom "Place message at the bottom">
+<!ENTITY noscriptSound.choose "Choose">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Play">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Reset default">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Advanced">
+<!ENTITY noscriptAdditionalPermissions "Additional permissions for trusted sites">
+<!ENTITY noscriptAllowClipboard "Allow rich text copy and paste from external clipboard">
+<!ENTITY noscriptAdditionalRestrictions "Additional restrictions for untrusted sites">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Apply these restrictions to trusted sites too">
+<!ENTITY noscriptForbidJava "Forbid Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Forbid XSLT">
+<!ENTITY noscriptForbidSilverlight "Forbid Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Forbid &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Forbid &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Forbid @font-face">
+<!ENTITY noscriptForbidWebGL "Forbid WebGL">
+<!ENTITY noscriptForbidMedia "Forbid &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Forbid Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Forbid other plugins">
+<!ENTITY noscriptReloadWarn "These options will take effect on new or (manually) reloaded pages">
+<!ENTITY noscriptConfirmUnblock "Ask for confirmation before temporarily unblocking an object">
+<!ENTITY noscriptStatusLabel "Status bar label">
+<!ENTITY noscriptForbidBookmarklets "Forbid bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Show placeholder icon">
+<!ENTITY noscriptTruncateTitle "Truncate document titles">
+<!ENTITY noscriptFixLinks "Attempt to fix JavaScript links">
+<!ENTITY noscriptAllowBookmarks "Allow sites opened through bookmarks">
+<!ENTITY noscriptAllowViaBookmarks "Allow sites opened through bookmarks">
+<!ENTITY noscriptAllowPing "Allow &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Allow local links">
+<!ENTITY noscriptForbidPing "Forbid &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Forbid META redirections inside &lt;NOSCRIPT&gt; elements">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptWhitelist "Whitelist">
+<!ENTITY noscriptPermissions "Permissions">
+<!ENTITY noscriptRefresh "Refresh">
+<!ENTITY noscriptNotifications "Notifications">
+<!ENTITY noscriptToolbarToggle "Left clicking on NoScript toolbar button toggles permissions for current top-level site">
+<!ENTITY noscriptTrusted "Trusted">
+<!ENTITY noscriptUntrusted "Untrusted">
+<!ENTITY noscriptUnknown "Unknwon">
+<!ENTITY noscriptAdd "Add">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Close">
+<!ENTITY noscriptSiteManager "Site Manager">
+<!ENTITY noscriptSecurityManager "Security Manager">
+<!ENTITY noscriptPolicies "Policies">
+<!ENTITY noscriptDefaultPolicies "Default Policies">
+<!ENTITY noscriptSitePolicies "Site Specific Policies">
+<!ENTITY noscriptNselNever "Hide &lt;NOSCRIPT&gt; elements">
+<!ENTITY noscriptNselForce "Show the &lt;NOSCRIPT&gt; element which follows a blocked &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Temporarily allow top-level sites by default">
+<!ENTITY noscriptDescription "Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality... Experts will agree: Firefox is really safer with NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Block CSS-based scanners">
+<!ENTITY noscriptOptFilterXGet "Sanitize cross-site suspicious requests">
+<!ENTITY noscriptOptFilterXPost "Turn cross-site POST requests into data-less GET requests">
+<!ENTITY noscriptShowConsole "Show Console...">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Unsafe Reload">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Anti-XSS Protection Exceptions">
+<!ENTITY noscriptXssExceptions.description "Destinations matching these regular expressions will NOT be protected against XSS">
+<!ENTITY noscriptMatchSample "Pattern matching sample:">
+<!ENTITY noscriptReset "Reset">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Reset to defaults">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revoke Temporary Permissions">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "No placeholder for objects coming from sites marked as untrusted">
+<!ENTITY noscriptCollapseBlockedObjects "Collapse blocked objects">
+<!ENTITY noscriptExceptions "Exceptions...">
+<!ENTITY noscriptBlockedObjects "Blocked Objects">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Block every object coming from a site marked as untrusted">
+<!ENTITY noscriptTempAllowPage "Temporarily allow all this page">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Allow all this page">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Make page permissions permanent">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behavior">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image above to cycle beetween the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Embedded Objects">
+<!ENTITY noscriptPrev "Previuous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/km-KH/noscript/noscript.properties b/extensions/noscript/chrome/locale/km-KH/noscript/noscript.properties
new file mode 100644
index 0000000..35e928f
--- /dev/null
+++ b/extensions/noscript/chrome/locale/km-KH/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Allow Scripts Globally (dangerous)
+forbidGlobal=Forbid Scripts Globally (advised)
+allowLocal=Allow %S
+allowTemp=Temporarily allow %S
+forbidLocal=Forbid %S
+allowed.glb=Danger! Scripts Globally Allowed
+allowed.yes=Scripts Currently Allowed
+allowed.prt=Scripts Partially Allowed
+allowed.no=Scripts Currently Forbidden
+global.warning.title=Warning!
+global.warning.text=Scripts are going to be allowed globally (for every site).\nThis is a potentially dangerous action.\nDo you really want to proceed?
+audio.samples=Audio samples
+confirm=Are you sure?
+alwaysAsk=Always ask for confirmation
+notifyHide=Hide after %S seconds
+trust=Trust %S
+distrust=Mark %S as Untrusted
+untrustedOrigin=an untrusted origin
+xss.notify.generic=NoScript filtered a potential cross-site scripting (XSS) attempt from %S. Technical details have been logged to the Console.
+xss.notify.showConsole=Show Console…
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Sanitized suspicious request. Original URL [%1$S] requested from [%2$S]. Sanitized URL: [%3$S].
+xss.reason.filterXGetRef=Sanitized suspicious request referer. URL [%1$S] requested from [%2$S]. Sanitized Referrer: [%3$S].
+xss.reason.filterXPost=Sanitized suspicious upload to [%1$S] from [%2$S]: transformed into a download-only GET request.
+unsafeReload.warning=UNSAFELY reloading a suspicious\n\n%1$S [%2$S]\n\nFROM [%3$S]\n\nNoScript will NOT protect this request!\n
+metaRefresh.notify=NoScript blocked a <META> redirection inside a <NOSCRIPT> element: %S in %S seconds.
+metaRefresh.notify.follow=Follow Redirection
+metaRefresh.notify.follow.accessKey=F
+notify.options=Options
+notify.options.accessKey=O
+reset.title=NoScript Reset
+reset.warning=ALL the NoScript preferences and site permissions will be reset to their default values immediately.\nThis action cannot be reverted.\nDo you want to continue?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark\'s content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You\'re about to ask for information about the \"%1$S\" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/ko-KR/noscript/about.properties b/extensions/noscript/chrome/locale/ko-KR/noscript/about.properties
new file mode 100644
index 0000000..39aa97a
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ko-KR/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=FireFox(불여우)를 위한 한층 ê°•í™”ëœ ë³´ì•ˆ 기능: NoScript를 사용하면 ì—¬ëŸ¬ë¶„ì´ ì„ íƒí•œ 신뢰할 수 있는 ë„ë©”ì¸(예를 들면, ì¸í„°ë„· 뱅킹 웹 사ì´íŠ¸)ì— ëŒ€í•´ì„œë§Œ JavaScript와 Java(ë˜í•œ ê·¸ ë°–ì˜ í”ŒëŸ¬ê·¸ì¸ë“¤ í¬í•¨)를 허용합니다. ì‚¬ìš©ìž ì§€ì • 목ë¡(whitelist)ì— ê¸°ë°˜ì„ ë‘” ì„ ì í˜• 차단 ì ‘ê·¼ ë°©ì‹ì„ 통해 ê¸°ëŠ¥ì— ì œì•½ì„ ë°›ì§€ ì•Šê³  보안 위협 요소들(알려진 위협 요소 ë¿ë§Œ ì•„ë‹ˆë¼ ì•Œë ¤ì§€ì§€ ì•Šì€ ìœ„í˜‘ 요소까지ë„!)ì„ ì‚¬ì „ì— ì°¨ë‹¨í•©ë‹ˆë‹¤. 전문가들 ì—­ì‹œ "NoScript를 사용하면 FireFoxê°€ ì¢€ë” ì•ˆì „í•´ì§‘ë‹ˆë‹¤!"ë¼ê³  ë§í•˜ê³  있습니다. :-)
+aboutTitle=%S ì •ë³´
+extensionContributors=ë„ì›€ì„ ì£¼ì‹  분들:
+extensionContributors.tip=확장 ê¸°ëŠ¥ì„ ë§Œë“  사람들
+extensionCreatorLabel=작성ìž:
+changelog=변경기ë¡
+changelog.tip=ë³€ê²½ê¸°ë¡ ë³´ê¸°
+license=ë¼ì´ì„¼ìŠ¤
+license.tip=ì‚¬ìš©ìž ë¼ì´ì„¼ìŠ¤ ì½ê¸°
+logo.tip=확장 기능 홈페ì´ì§€ 방문
+sponsor.tip=스í°ì„œ 홈페ì´ì§€ 방문
+informaction.tip=InformAction 홈페ì´ì§€ 방문
+extensionHomepage.tip=확장기능 홈페ì´ì§€ 방문
+extensionCreator.tip=ìž‘ì„±ìž í™ˆíŽ˜ì´ì§€ 방문
+version=버전 %S
diff --git a/extensions/noscript/chrome/locale/ko-KR/noscript/noscript.dtd b/extensions/noscript/chrome/locale/ko-KR/noscript/noscript.dtd
new file mode 100644
index 0000000..53e0bd1
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ko-KR/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "옵션...">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript 옵션">
+<!ENTITY noscriptAbout "NoScript 5.1.8.5 ì •ë³´...">
+<!ENTITY noscriptPermissionsText "스í¬ë¦½íŠ¸ ì‹¤í–‰ì„ í—ˆìš©í•  웹 사ì´íŠ¸ë¥¼ 지정할 수 있습니다. 스í¬ë¦½íŠ¸ë¥¼ 허용할 사ì´íŠ¸ì˜ 주소나 ë„ë©”ì¸ (예를 들면, &quot;http://www.site.com&quot; ë˜ëŠ” &quot;site.com&quot;)ì„ ìž…ë ¥í•œ 후 [허용] ë²„íŠ¼ì„ í´ë¦­í•©ë‹ˆë‹¤.">
+<!ENTITY noscriptWebAddress "웹 사ì´íŠ¸ 주소">
+<!ENTITY noscriptAllow "허용">
+<!ENTITY noscriptAllow.accesskey "l">
+<!ENTITY noscriptForbid "금지">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "신뢰할 수 있는 사ì´íŠ¸ë¡œ 지정">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "신뢰할 수 없는 사ì´íŠ¸ë¡œ 지정">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "ì„ íƒëœ 사ì´íŠ¸ ì‚­ì œ">
+<!ENTITY noscriptGloballyEnabled "스í¬ë¦½íŠ¸ ì „ë©´ 허용(위험)">
+<!ENTITY noscriptAutoReload "허용 ì •ì±…ì´ ë³€ê²½ë˜ë©´ 해당 페ì´ì§€ë¥¼ ìžë™ìœ¼ë¡œ 다시 ì½ê¸°">
+<!ENTITY noscriptGeneral "ì¼ë°˜">
+<!ENTITY noscriptAppearance "모양">
+<!ENTITY noscriptShow "ë‹¤ìŒ ê¸°ëŠ¥ë“¤ì„ ë³´ì—¬ì¤ë‹ˆë‹¤...">
+<!ENTITY noscriptCtxMenu "ìƒí™©ì— 따른 메뉴">
+<!ENTITY noscriptStatusIcon "ìƒíƒœí‘œì‹œì¤„ ì•„ì´ì½˜">
+<!ENTITY noscriptFullAddr "전체 주소(http://www.noscript.net)">
+<!ENTITY noscriptFullDom "ì „ì²´ ë„ë©”ì¸(www.noscript.net)">
+<!ENTITY noscriptBaseDom "2수준 ë„ë©”ì¸(noscript.net)">
+<!ENTITY noscriptTempCmd "임시 허용[...]">
+<!ENTITY noscriptSound "스í¬ë¦½íŠ¸ê°€ 차단ë˜ì—ˆì„ ë•Œ 소리로 알림">
+<!ENTITY noscriptImport "가져오기">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "내보내기">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "ì°¨ë‹¨ëœ ìŠ¤í¬ë¦½íŠ¸ì— 대한 ì •ë³´ 보여주기">
+<!ENTITY noscriptNotify.bottom "í•˜ë‹¨ì— ë©”ì‹œì§€ 표시">
+<!ENTITY noscriptSound.choose "ì„ íƒ">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "재ìƒ">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "기본 설정으로 ë³µì›">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "고급">
+<!ENTITY noscriptAdditionalPermissions "신뢰할 수 있는 사ì´íŠ¸ì— 대해서 다ìŒì„ 추가ì ìœ¼ë¡œ 허용">
+<!ENTITY noscriptAllowClipboard "외부 í´ë¦½ë³´ë“œë¡œë¶€í„° 리치 í…스트 복사 ë° ë¶™ì—¬ë„£ê¸° 허용">
+<!ENTITY noscriptAdditionalRestrictions "신뢰할 수 없는 사ì´íŠ¸ì— 대한 추가ì ì¸ 제한 조치">
+<!ENTITY noscriptPlugins "플러그ì¸">
+<!ENTITY noscriptContentBlocker "ì´ ì œí•œ 조치를 신뢰할 수 있는 사ì´íŠ¸ì—ë„ ì ìš©">
+<!ENTITY noscriptForbidJava "Java™ 금지">
+<!ENTITY noscriptForbidXSLT "XSLT 금지">
+<!ENTITY noscriptForbidSilverlight "Microsoft® Silverlight™ 금지">
+<!ENTITY noscriptForbidIFrames "&lt;IFRAME&gt; 금지">
+<!ENTITY noscriptForbidFrames "&lt;FRAME&gt; 금지">
+<!ENTITY noscriptForbidFonts "@font-face 금지">
+<!ENTITY noscriptForbidWebGL "WebGL 금지">
+<!ENTITY noscriptForbidMedia "&lt;AUDIO&gt; / &lt;VIDEO&gt; 금지">
+<!ENTITY noscriptForbidFlash "Adobe® Flash® 금지">
+<!ENTITY noscriptForbidPlugins "다른 í”ŒëŸ¬ê·¸ì¸ ê¸ˆì§€">
+<!ENTITY noscriptReloadWarn "ì´ ì˜µì…˜ì€ ìƒˆë¡œìš´ 페ì´ì§€ ë˜ëŠ” (수ë™ìœ¼ë¡œ) 페ì´ì§€ë¥¼ 다시 ì½ì–´ë“¤ì¼ ë•Œ ì ìš©ë©ë‹ˆë‹¤.">
+<!ENTITY noscriptConfirmUnblock "ì¼ì‹œì ìœ¼ë¡œ 개체를 허용할 것ì¸ì§€ë¥¼ 확ì¸í•©ë‹ˆë‹¤.">
+<!ENTITY noscriptStatusLabel "ìƒíƒœë°” ë ˆì´ë¸”">
+<!ENTITY noscriptForbidBookmarklets "ë¶ë§ˆí¬ë¦¿(bookmarklets) 금지">
+<!ENTITY noscriptShowPlaceholder "플레ì´ìŠ¤í™€ë” ì•„ì´ì½˜ 표시">
+<!ENTITY noscriptTruncateTitle "문서 제목ì—ì„œ 양쪽ëì— ìžˆëŠ” ê³µë°±ì„ ì œê±°">
+<!ENTITY noscriptFixLinks "JavaScript ë§í¬ 수정 ì‹œë„">
+<!ENTITY noscriptAllowBookmarks "ë¶ë§ˆí¬ë¥¼ ì´ìš©í•œ 사ì´íŠ¸ 열기 허용">
+<!ENTITY noscriptAllowViaBookmarks "ë¶ë§ˆí¬ë¥¼ ì´ìš©í•œ 사ì´íŠ¸ 열기 허용">
+<!ENTITY noscriptAllowPing "&lt;A PING...&gt; 허용">
+<!ENTITY noscriptAllowLocalLinks "로컬 ë§í¬ 허용">
+<!ENTITY noscriptForbidPing "&lt;A PING...&gt; 금지">
+<!ENTITY noscriptForbidMetaRefresh "&lt;NOSCRIPT&gt; 요소 ë‚´ì— ìžˆëŠ” META 리디렉션 제거">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptWhitelist "ì‚¬ìš©ìž ì§€ì • 목ë¡">
+<!ENTITY noscriptPermissions "허용">
+<!ENTITY noscriptRefresh "새로고침">
+<!ENTITY noscriptNotifications "알림">
+<!ENTITY noscriptToolbarToggle "NoScript 툴바 ë²„íŠ¼ì„ ë§ˆìš°ìŠ¤ 왼쪽버튼으로 í´ë¦­í•˜ë©´ 현재 최ìƒìœ„ 사ì´íŠ¸ì— 대한 허용 ìƒíƒœë¥¼ 허용/비허용으로 변경합니다.">
+<!ENTITY noscriptTrusted "신뢰할 수 있는 사ì´íŠ¸">
+<!ENTITY noscriptUntrusted "신뢰할 수 없는 사ì´íŠ¸">
+<!ENTITY noscriptUnknown "알려지지 ì•ŠìŒ">
+<!ENTITY noscriptAdd "추가">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "닫기">
+<!ENTITY noscriptSiteManager "사ì´íŠ¸ 관리ìž">
+<!ENTITY noscriptSecurityManager "보안 관리ìž">
+<!ENTITY noscriptPolicies "ì •ì±…">
+<!ENTITY noscriptDefaultPolicies "기본 정책">
+<!ENTITY noscriptSitePolicies "사ì´íŠ¸ë³„ ì •ì±…">
+<!ENTITY noscriptNselNever "&lt;NOSCRIPT&gt; 요소를 숨김">
+<!ENTITY noscriptNselForce "ì°¨ë‹¨ëœ &lt;SCRIPT&gt; 다ìŒì— 오는 &lt;NOSCRIPT&gt; 요소 표시">
+<!ENTITY noscriptAutoAllowTopLevel "ì¼ì‹œì ìœ¼ë¡œ 최ìƒìœ„ 사ì´íŠ¸ë¥¼ 허용">
+<!ENTITY noscriptDescription "FireFox(불여우)를 위한 한층 ê°•í™”ëœ ë³´ì•ˆ 기능: NoScript를 사용하면 ì—¬ëŸ¬ë¶„ì´ ì„ íƒí•œ 신뢰할 수 있는 ë„ë©”ì¸(예를 들면, ì¸í„°ë„· 뱅킹 웹 사ì´íŠ¸)ì— ëŒ€í•´ì„œë§Œ JavaScript와 Java(ë˜í•œ ê·¸ ë°–ì˜ í”ŒëŸ¬ê·¸ì¸ë“¤ í¬í•¨)를 허용합니다. ì‚¬ìš©ìž ì§€ì • 목ë¡(whitelist)ì— ê¸°ë°˜ì„ ë‘” ì„ ì í˜• 차단 ì ‘ê·¼ ë°©ì‹ì„ 통해 ê¸°ëŠ¥ì— ì œì•½ì„ ë°›ì§€ ì•Šê³  보안 위협 요소들(알려진 위협 요소 ë¿ë§Œ ì•„ë‹ˆë¼ ì•Œë ¤ì§€ì§€ ì•Šì€ ìœ„í˜‘ 요소까지ë„!)ì„ ì‚¬ì „ì— ì°¨ë‹¨í•©ë‹ˆë‹¤. 전문가들 ì—­ì‹œ &quot;NoScript를 사용하면 FireFoxê°€ ì¢€ë” ì•ˆì „í•´ì§‘ë‹ˆë‹¤!&quot;ë¼ê³  ë§í•˜ê³  있습니다. :-)">
+<!ENTITY noscriptOptBlockCssScanners "CSS ê¸°ë°˜ì˜ ìŠ¤ìºë„ˆ 차단">
+<!ENTITY noscriptOptFilterXGet "ì˜ì‹¬ìŠ¤ëŸ¬ìš´ í¬ë¡œìŠ¤-사ì´íŠ¸ 요청 차단">
+<!ENTITY noscriptOptFilterXPost "í¬ë¡œìŠ¤-사ì´íŠ¸ POST ìš”ì²­ì„ ë°ì´í„° ì†ì‹¤ì´ 없는 GET 요청으로 변환">
+<!ENTITY noscriptShowConsole "콘솔 보기...">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ…">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "안전하지 ì•Šì€ ìƒíƒœë¡œ 다시 ì½ê¸°">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "안티-XSS 보호 예외 ì ìš©">
+<!ENTITY noscriptXssExceptions.description "ë‹¤ìŒ ì •ê·œ 표현ì‹ê³¼ ì¼ì¹˜í•˜ëŠ” 대ìƒì€ XSS로부터 보호하지 않습니다">
+<!ENTITY noscriptMatchSample "패턴 매칭 예제:">
+<!ENTITY noscriptReset "설정 ë³µì›">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "기본 설정으로 ë³µì›">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "ì¼ì‹œì ì¸ 허용 취소">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "신뢰할 수 없는 사ì´íŠ¸ë¡œ 등ë¡ëœ 사ì´íŠ¸ì˜ ê°œì²´ì— ëŒ€í•´ì„œëŠ” 플레ì´ìŠ¤í™€ë” 표시하지 ì•ŠìŒ">
+<!ENTITY noscriptCollapseBlockedObjects "ì°¨ë‹¨ëœ ê°œì²´ëŠ” 사용하지 ì•ŠìŒ">
+<!ENTITY noscriptExceptions "예외...">
+<!ENTITY noscriptBlockedObjects "ì°¨ë‹¨ëœ ê°œì²´ë“¤">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "신뢰할 수 ì—†ìŒìœ¼ë¡œ í‘œì‹œëœ ì‚¬ì´íŠ¸ì˜ 모든 개체를 차단">
+<!ENTITY noscriptTempAllowPage "ì¼ì‹œì ìœ¼ë¡œ 허용">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "ì´ íŽ˜ì´ì§€ ëª¨ë‘ í—ˆìš©">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "페ì´ì§€ ê¶Œí•œì„ ì˜êµ¬ì ìœ¼ë¡œ 저장하기">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS ìžì£¼ë¬»ëŠ”질문...">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "행위">
+<!ENTITY noscriptHttps.cookies "쿠키">
+<!ENTITY noscriptHttps.description "안전한(HTTPS) ì—°ê²°ì— ëŒ€í•´ì„œë§Œ 웹 컨í…츠 활성화 허용:">
+<!ENTITY noscriptHttps.never "í•­ìƒ ì•„ë‹˜">
+<!ENTITY noscriptHttps.proxy "프ë½ì‹œë¥¼ 사용할 ë•Œ(Tor 추천)">
+<!ENTITY noscriptHttps.always "í•­ìƒ">
+<!ENTITY noscriptHttpsForced "ë‹¤ìŒ ì‚¬ì´íŠ¸ì— 대해서 강제로 안전한(HTTPS) ì—°ê²° ì‹œë„:">
+<!ENTITY noscriptHttpsForcedExceptions "ë‹¤ìŒ ì‚¬ì´íŠ¸ì— 대해서는 안전한(HTTPS) ì—°ê²° ì‹œë„ ì•ˆí•¨:">
+<!ENTITY noscriptSecureCookies "ìžë™ 보안 쿠기 ê´€ë¦¬ìž í™œì„±í™”">
+<!ENTITY noscriptSecureCookiesForced "ë‹¤ìŒ ì‚¬ì´íŠ¸ì— 대해서는 HTTPS ìƒì˜ 모든 쿠키를 강제로 암호화:">
+<!ENTITY noscriptSecureCookiesExceptions "ë‹¤ìŒ ì‚¬ì´íŠ¸ì— 대해서는 HTTPS ìƒì˜ 안전하지 ì•Šì€ ì¿ í‚¤ë¥¼ 무시:">
+<!ENTITY noscriptClearClickTitle "ClearClick 경고">
+<!ENTITY noscriptClearClickHeader "잠재ì ì¸ í´ë¦­ìž¬í‚¹(Clickjacking) ë˜ëŠ” UI 변경 ì‹œë„!">
+<!ENTITY noscriptClearClickDescription "NoScriptê°€ 숨겨진 요소ì—ì„œ 처리하는 마우스나 키보드 ìž‘ë™ì„ 가로챘습니다. ìƒë‹¨ì— 있는 ì´ë¯¸ì§€ë¥¼ í´ë¦­í•˜ì—¬ ì°¨ë‹¨ëœ ë²„ì „ê³¼ 그렇지 ì•Šì€ ë²„ì „ê°„ì— ì „í™˜í•  수 있습니다.">
+<!ENTITY noscriptClearClickOpt "페ì´ì§€ì— 대해서 ClearClick 보호 수행...">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "ì‹ ë¢°ëœ íŽ˜ì´ì§€">
+<!ENTITY noscriptUntrustedPagesAdj "신뢰ë˜ì§€ ì•Šì€ íŽ˜ì´ì§€">
+<!ENTITY noscriptKeepLocked "ì´ ìš”ì†Œë¥¼ 잠금니다(추천)">
+<!ENTITY noscriptEmbeddings "í¬í•¨ëœ ê°ì²´ë“¤">
+<!ENTITY noscriptPrev "Previuous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/ko-KR/noscript/noscript.properties b/extensions/noscript/chrome/locale/ko-KR/noscript/noscript.properties
new file mode 100644
index 0000000..7cfd317
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ko-KR/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=스í¬ë¦½íŠ¸ ì „ë©´ 허용(위험)
+forbidGlobal=스í¬ë¦½íŠ¸ ì „ë©´ 금지(권장 사항)
+allowLocal=%S 허용
+allowTemp=%S 임시 허용
+forbidLocal=%S 금지
+allowed.glb=위험합니다! 스í¬ë¦½íŠ¸ê°€ ì „ë©´ì ìœ¼ë¡œ 허용ë˜ì—ˆìŠµë‹ˆë‹¤.
+allowed.yes=스í¬ë¦½íŠ¸ê°€ 허용ë˜ì—ˆìŠµë‹ˆë‹¤.
+allowed.prt=스í¬ë¦½íŠ¸ê°€ 부분ì ìœ¼ë¡œ 허용ë˜ì—ˆìŠµë‹ˆë‹¤.
+allowed.no=스í¬ë¦½íŠ¸ê°€ 금지ë˜ì—ˆìŠµë‹ˆë‹¤.
+global.warning.title=경고!
+global.warning.text=스í¬ë¦½íŠ¸ê°€ ì „ë©´ì ìœ¼ë¡œ(모든 사ì´íŠ¸ì— 대해서) í—ˆìš©ë  ì˜ˆì •ìž…ë‹ˆë‹¤.\nì´ë¡œì¸í•´ 잠재ì ì¸ ìœ„í—˜ì´ ë°œìƒí•  수 있습니다.\n진행하시겠습니까?
+audio.samples=오디오 샘플
+confirm=확실합니까?
+alwaysAsk=í•­ìƒ í™•ì¸
+notifyHide=%S초 후 숨김
+trust=%S를 신뢰합니다.
+distrust=%S를 신뢰할 수 없는 사ì´íŠ¸ë¡œ 지정
+untrustedOrigin=신뢰할 수 없는 출처
+xss.notify.generic=NoScriptê°€ %Sì—ì„œ ì‹œë„ëœ í¬ë¡œìŠ¤-사ì´íŠ¸ 스í¬ë¦½íŒ… (CSS)를 í•„í„°ë§í–ˆìŠµë‹ˆë‹¤. 기술ì ì¸ 세부 ì‚¬í•­ì€ ì½˜ì†”ì—ì„œ 확ì¸í•  수 있습니다.
+xss.notify.showConsole=콘솔 보기...
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=ì˜ì‹¬ìŠ¤ëŸ¬ìš´ ìš”ì²­ì„ ì²˜ë¦¬í–ˆìŠµë‹ˆë‹¤. [%2$S]ì—ì„œ ìš”ì²­ëœ ì›ë³¸ URLì€ [%1$S] , ì²˜ë¦¬ëœ URL: [%3$S]
+xss.reason.filterXGetRef=ì˜ì‹¬ìŠ¤ëŸ¬ìš´ ë ˆí¼ëŸ¬ ìš”ì²­ì„ ì²˜ë¦¬í–ˆìŠµë‹ˆë‹¤. [%2$S]ì—ì„œ ìš”ì²­ëœ URL: [%1$S] , ì²˜ë¦¬ëœ ë ˆí¼ëŸ¬: [%3$S]
+xss.reason.filterXPost=[%2$S]ì—ì„œ [%1$S]ë¡œ 업로드하는 ê²ƒì„ ì²˜ë¦¬í–ˆìŠµë‹ˆë‹¤. 다운로드만 가능한 GET 요청으로 변형ë˜ì—ˆìŠµë‹ˆë‹¤.
+unsafeReload.warning=[%3$S]ì—ì„œ\n\nì˜ì‹¬ìŠ¤ë¡œìš´ %1$S [%2$S]를 다시 ì½ê³  있습니다.\n\nNoScript는 ì´ ìš”ì²­ì„ ë³´í˜¸í•˜ì§€ ì•Šì„ ê²ƒìž…ë‹ˆë‹¤!\n
+metaRefresh.notify=NoScriptê°€ <NOSCRIPT>ì— ìžˆëŠ” <META> ë¦¬ë””ë ‰ì…˜ì„ ì°¨ë‹¨í–ˆìŠµë‹ˆë‹¤. %S(%Sì´ˆ).
+metaRefresh.notify.follow=리디렉션 ë”°ë¼ê°€ê¸°
+metaRefresh.notify.follow.accessKey=F
+notify.options=옵션
+notify.options.accessKey=O
+reset.title=NoScript 설정 ë³µì›
+reset.warning=ì´ì œ NoScriptì˜ ëª¨ë“  설정과 사ì´íŠ¸ 허용 ì •ë³´ê°€ 기본 값으로 ë³µì›ë©ë‹ˆë‹¤.\nì´ ìž‘ì—…ì€ ì·¨ì†Œí•  수 없습니다.\nê³„ì† í•˜ì‹œê² ìŠµë‹ˆê¹Œ?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark's content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/lt/noscript/about.properties b/extensions/noscript/chrome/locale/lt/noscript/about.properties
new file mode 100644
index 0000000..7745d71
--- /dev/null
+++ b/extensions/noscript/chrome/locale/lt/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Papildoma apsauga jūsų Firefox naršyklei: NoScript leidžia vykdyti JavaScript, Java (ir kitus įskiepius) tik jūsų pasirinktiems ir patikimiems domenams (pvz., jūsų banko interneto svetainei). Ši baltuoju sąrašu pagrįsta išankstinio blokavimo taktika neleidžia išnaudoti saugumo skylių (žinomų ir net nežinomų!) neprarandant funkcionalumo... Ekspertai pritaria: Firefox tikrai saugesnis su NoScript :-)
+aboutTitle=Apie %S
+extensionContributors=Pagalbininkai:
+extensionContributors.tip=Žmonės, kuriems reikia dėkoti už šį papildinį
+extensionCreatorLabel=Autorius:
+changelog=Keitimų žurnalas
+changelog.tip=Rodyti keitimų žurnalą
+license=Licencija
+license.tip=Perskaityti vartotojo licencijÄ…
+logo.tip=Aplankyti papildinio interneto svetainÄ™
+sponsor.tip=Aplankyti rÄ—mÄ—jo interneto svetainÄ™
+informaction.tip=Aplankyti InformAction interneto svetainÄ™
+extensionHomepage.tip=Aplankyti papildinio interneto svetainÄ™
+extensionCreator.tip=Aplankyti autoriaus interneto svetainÄ™
+version=Versija %S
diff --git a/extensions/noscript/chrome/locale/lt/noscript/noscript.dtd b/extensions/noscript/chrome/locale/lt/noscript/noscript.dtd
new file mode 100644
index 0000000..aee6d5c
--- /dev/null
+++ b/extensions/noscript/chrome/locale/lt/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Nuostatos...">
+<!ENTITY noscriptOptions.accesskey "N">
+<!ENTITY noscriptOptionsLong "NoScript nuostatos">
+<!ENTITY noscriptAbout "Apie NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Jūs galite nurodyti, kurioms interneto svetainėms suteikiamas leidimas vykdyti programinius kodus. Įveskite adresą arba domeną (pvz., &quot;http://www.svetaine.lt&quot; arba &quot;svetaine.lt&quot;) svetainės, kuriai norite suteikti leidimą ir spauskite Leisti.">
+<!ENTITY noscriptWebAddress "Interneto svetainÄ—s adresas:">
+<!ENTITY noscriptAllow "Leisti">
+<!ENTITY noscriptAllow.accesskey "L">
+<!ENTITY noscriptForbid "Drausti">
+<!ENTITY noscriptForbid.accesskey "D">
+<!ENTITY noscriptTrust "Pažymėti patikimu">
+<!ENTITY noscriptTrust.accesskey "P">
+<!ENTITY noscriptUntrust "Pažymėti nepatikimu">
+<!ENTITY noscriptUntrust.accesskey "N">
+<!ENTITY noscriptRemoveSelected "Pašalinti pažymėtas svetaines">
+<!ENTITY noscriptGloballyEnabled "Programiniai kodai leidžiami visuotinai (pavojinga)">
+<!ENTITY noscriptAutoReload "Kai leidimai puslapiams pasikeiÄia, automatiÅ¡kai įkelti puslapius iÅ¡ naujo">
+<!ENTITY noscriptGeneral "Bendrosios">
+<!ENTITY noscriptAppearance "IÅ¡vaizda">
+<!ENTITY noscriptShow "Rodyti...">
+<!ENTITY noscriptCtxMenu "Kontekstinį meniu">
+<!ENTITY noscriptStatusIcon "BÅ«senos juostos piktogramÄ…">
+<!ENTITY noscriptFullAddr "Pilniems adresams (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Pilniems domenams (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Antrojo lygio domenams (noscript.net)">
+<!ENTITY noscriptTempCmd "Laikinai leisti [...]">
+<!ENTITY noscriptSound "Groti garsinį pranešimą, kai programiniai kodai blokuojami">
+<!ENTITY noscriptImport "Importuoti">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Eksportuoti">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Rodyti pranešimą apie blokuotus programinius kodus">
+<!ENTITY noscriptNotify.bottom "Patalpinti praneÅ¡imÄ… apaÄioje">
+<!ENTITY noscriptSound.choose "Pasirinkti">
+<!ENTITY noscriptSound.choose.accesskey "P">
+<!ENTITY noscriptSound.play "Groti">
+<!ENTITY noscriptSound.play.accesskey "G">
+<!ENTITY noscriptSound.reset "Atstatyti">
+<!ENTITY noscriptSound.reset.accesskey "A">
+<!ENTITY noscriptAdvanced "Papildomi">
+<!ENTITY noscriptAdditionalPermissions "Papildomi leidimai patikimoms svetainÄ—ms">
+<!ENTITY noscriptAllowClipboard "Leisti formatuoto teksto kopijavimą ir įterpimą iš iškarpinės">
+<!ENTITY noscriptAdditionalRestrictions "Papildomi draudimai nepatikimoms svetainÄ—ms">
+<!ENTITY noscriptPlugins "Įskiepiai">
+<!ENTITY noscriptContentBlocker "Pritaikyti Å¡iuos draudimus taip pat ir patikimoms svetainÄ—ms">
+<!ENTITY noscriptForbidJava "Uždrausti Java™">
+<!ENTITY noscriptForbidXSLT "Uždrausti XSLT">
+<!ENTITY noscriptForbidWebGL "Uždrausti WebGL">
+<!ENTITY noscriptForbidSilverlight "Uždrausti Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Uždrausti &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Uždrausti &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Uždrausti @font-face">
+<!ENTITY noscriptForbidMedia "Uždrausti &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Uždrausti Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Uždrausti kitus įskiepius">
+<!ENTITY noscriptReloadWarn "Šios nuostatos įsigalios naujoms arba rankiniu būdu įkrautoms iš naujo svetainėms">
+<!ENTITY noscriptConfirmUnblock "Prašyti patvirtinimo prieš laikinai atblokuojant objektą">
+<!ENTITY noscriptStatusLabel "Būsenos juostos žymą">
+<!ENTITY noscriptForbidBookmarklets "Uždrausti JavaScript kuriamus adresyno įrašus">
+<!ENTITY noscriptShowPlaceholder "Rodyti puslapio talpintojo piktogramÄ…">
+<!ENTITY noscriptTruncateTitle "Nerodyti dokumentų pavadinimų">
+<!ENTITY noscriptFixLinks "Bandyti sutaisyti JavaScript nuorodas">
+<!ENTITY noscriptAllowBookmarks "Suteikti leidimą svetainėms, atidarytoms iš adresyno">
+<!ENTITY noscriptAllowViaBookmarks "Suteikti leidimą svetainėms, atidarytoms iš adresyno">
+<!ENTITY noscriptAllowPing "Leisti &lt;A PING...&gt; elementus">
+<!ENTITY noscriptAllowLocalLinks "Leisti nuorodas į vietines bylas">
+<!ENTITY noscriptForbidPing "Uždrausti &lt;A PING...&gt; elementus">
+<!ENTITY noscriptForbidMetaRefresh "Uždrausti META peradresavimus &lt;NOSCRIPT&gt; elementuose">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "Ž">
+<!ENTITY noscriptNotifyMeta "Rodyti pranešimus apie užblokuotus META peradresavimus">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "Baltasis sąrašas">
+<!ENTITY noscriptPermissions "Leidimai">
+<!ENTITY noscriptRefresh "Atnaujinti">
+<!ENTITY noscriptNotifications "Pranešimai">
+<!ENTITY noscriptToolbarToggle "Kairysis paspaudimas ant NoScript įrankių juostos mygtuko keiÄia atidarytos svetainÄ—s leidimus">
+<!ENTITY noscriptTrusted "Patikimi">
+<!ENTITY noscriptUntrusted "Nepatikimi">
+<!ENTITY noscriptUnknown "Nežinomi">
+<!ENTITY noscriptAdd "PridÄ—ti">
+<!ENTITY noscriptAdd.accesskey "P">
+<!ENTITY noscriptClose "Uždaryti">
+<!ENTITY noscriptSiteManager "Svetainių vadovas">
+<!ENTITY noscriptSecurityManager "Saugumo vadovas">
+<!ENTITY noscriptPolicies "Nuostatos">
+<!ENTITY noscriptDefaultPolicies "Numatytos nuostatos">
+<!ENTITY noscriptSitePolicies "Specifinės svetainių nuostatos">
+<!ENTITY noscriptNselNever "PaslÄ—pti &lt;NOSCRIPT&gt; elementus">
+<!ENTITY noscriptNselForce "Rodyti &lt;NOSCRIPT&gt; elementus, kurie eina po blokinio &lt;SCRIPT&gt; elemento">
+<!ENTITY noscriptAutoAllowTopLevel "Pagal nutylÄ—jimÄ…, laikinai suteikti leidimÄ… aukÅ¡Äiausiojo lygio svetainių adresams">
+<!ENTITY noscriptDescription "Papildoma apsauga jūsų Firefox naršyklei: NoScript leidžia JavaScript, Java (ir kitus įskiepius) tik jūsų pasirinktiems patikimiems domenams (pvz. jūsų banko interneto svetainei). Ši baltuoju sąrašu pagrįsta išankstinio blokavimo taktika neleidžia panaudoti saugumo skylių (žinomų ir net nežinomų!) neprarandant funkcionalumo... Ekspertai pritaria: Firefox tikrai saugesnis su NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Blokuoti ieškiklius, pagrįstus CSS">
+<!ENTITY noscriptOptFilterXGet "Nukenksminti įtartinas tarp-svetainines užklausas">
+<!ENTITY noscriptOptFilterXPost "Paversti tarp-svetainines POST užklausas į tuÅ¡Äias GET užklausas">
+<!ENTITY noscriptShowConsole "Rodyti konsolÄ™">
+<!ENTITY noscriptShowConsole.accesskey "K">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS DPK...">
+<!ENTITY noscriptXssFaq.accesskey "D">
+<!ENTITY noscriptUnsafeReload "Nesaugus perkrovimas">
+<!ENTITY noscriptUnsafeReload.accesskey "P">
+<!ENTITY noscriptXssExceptions "Anti-XSS apsaugos išimtys">
+<!ENTITY noscriptXssExceptions.description "Adresai, atitinkantys šias reguliarias išraiškas, NEBUS apsaugoti nuo XSS">
+<!ENTITY noscriptMatchSample "Adreso pavyzdys:">
+<!ENTITY noscriptReset "Atstatyti">
+<!ENTITY noscriptReset.accesskey "A">
+<!ENTITY noscriptResetDef "Atstatyti į pradines reikšmes">
+<!ENTITY noscriptResetDef.accesskey "Ä®">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Atšaukti laikinus leidimus">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "Be puslapio laikytojų, objektam iš nepatikimų svetainių">
+<!ENTITY noscriptCollapseBlockedObjects "Suskleisti blokuotus objektus">
+<!ENTITY noscriptExceptions "IÅ¡imtys...">
+<!ENTITY noscriptBlockedObjects "Užblokuoti objektai">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Užblokuoti visus objektus atkeliaujanÄius iÅ¡ nepatikimos svetainÄ—s">
+<!ENTITY noscriptTempAllowPage "Å ioje svetainÄ—je laikinai leisti viskÄ…">
+<!ENTITY noscriptTempAllowPage.accesskey "L">
+<!ENTITY noscriptAllowPage "Å iame puslapyje leisti viskÄ…">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Padaryti puslapio leidimus nuolatiniais">
+<!ENTITY noscriptTempToPerm.accesskey "M">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS DUK…">
+<!ENTITY noscriptHttpsFaq.accesskey "D">
+<!ENTITY noscriptHttps.behavior "Elgsena">
+<!ENTITY noscriptHttps.cookies "Slapukai">
+<!ENTITY noscriptHttps.description "Uždrausti aktyvų interneto turinį, nebent jis atkeliauja iš saugaus (HTTPS) prisijungimo:">
+<!ENTITY noscriptHttps.never "Niekada">
+<!ENTITY noscriptHttps.proxy "Kai naudojamas tarpinis serveris (rekomenduojama su Tor)">
+<!ENTITY noscriptHttps.always "Visada">
+<!ENTITY noscriptHttpsForced "Priversti Å¡ias svetaines naudoti saugius (HTTPS) prisijungimus:">
+<!ENTITY noscriptHttpsForcedExceptions "Šias svetaines niekada neversti naudoti saugių (HTTPS) prisijungimų:">
+<!ENTITY noscriptSecureCookies "Įgalinti automatinį saugių slapukų tvarkymą">
+<!ENTITY noscriptSecureCookiesForced "Priverstinai šifruoti visus slapukus perduotus per HTTPS iš šių svetainių:">
+<!ENTITY noscriptSecureCookiesExceptions "Nepaisyti nesaugių slapukų perduotų HTTPS iš šių svetainių:">
+<!ENTITY noscriptClearClickTitle "ClearClick Įspėjimas">
+<!ENTITY noscriptClearClickHeader "Potencialus Clickjacking / Bandymas peradresuoti VS(UI)!">
+<!ENTITY noscriptClearClickDescription "NoScript perÄ—mÄ— pelÄ—s ar klaviatÅ«ros sÄ…veikÄ… su dalinai paslÄ—ptu elementu. Paspauskite aukÅ¡Äiau esantį paveikslÄ—lį perjungimui tarp Å¡varios ir neaiÅ¡kios versijos.">
+<!ENTITY noscriptClearClickOpt "ClearClick apsauga puslapiuose...">
+<!ENTITY noscriptClearClickReport "Pranešti">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Pranešimo ID:">
+<!ENTITY noscriptTrustedPagesAdj "patikimas">
+<!ENTITY noscriptUntrustedPagesAdj "nepatikimas">
+<!ENTITY noscriptKeepLocked "Laikyti šį elementą užrakintą (rekomenduojama)">
+<!ENTITY noscriptEmbeddings "Įterpimai">
+<!ENTITY noscriptPrev "Ankstesnis">
+<!ENTITY noscriptNext "Sekantis">
+<!ENTITY noscriptFrameOptErr.title "Šio turinio neįmanoma atvaizduoti rėmelyje">
+<!ENTITY noscriptFrameOptErr.desc "Siekiant apsaugoti jus, šio turinio skleidėjas neleidžia jo atvaizduoti rėmelyje.">
+<!ENTITY noscriptFrameOptErr.link "Paspauskite Äia norÄ—dami atverti šį turinį naujame lange">
+<!ENTITY noscriptBookmarkSync "Atsarginė NoScript kopija žymelėje, kad būtų lengva sinchronizuoti">
+<!ENTITY noscriptShowReleaseNotes "Atnaujinant parodyti leidimo pastabas">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "TaisyklÄ—s:">
+<!ENTITY ABE.enabled.label "Įjungti ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Leisti svetainėms siūlyti jų savus taisyklių rinkinius">
+<!ENTITY ABE.edit.label "Taisa...">
+<!ENTITY ABE.edit.accesskey "T">
+<!ENTITY ABE.enable.label "Įjungti">
+<!ENTITY ABE.enable.accesskey "g">
+<!ENTITY ABE.disable.label "IÅ¡jungti">
+<!ENTITY ABE.disable.accesskey "j">
+<!ENTITY ABE.refresh.label "Atnaujinti">
+<!ENTITY ABE.refresh.accesskey "A">
+<!ENTITY noscriptUninstall "IÅ¡diegti">
+<!ENTITY noscriptRecentBlocked "Nesenai užblokuotos svetainės">
+<!ENTITY noscriptExternalFilters "IÅ¡oriniai filtrai">
+<!ENTITY noscriptEF.enable "Įjungti išorinius filtrus">
+<!ENTITY noscriptEF.add "Naujas filtras...">
+<!ENTITY noscriptEF.executable "Vykdomasis failas:">
+<!ENTITY noscriptEF.browse "Naršyti...">
+<!ENTITY noscriptEF.contentType "Turinio tipas (MIME) kuris turi būti filtruojamas (sutampantis ar reguliariosios išraiškos):">
+<!ENTITY noscriptEF.exceptions "Nefiltruoti objektų atkeliaujanÄių iÅ¡ Å¡ių puslapių:">
+<!ENTITY noscriptEF.remove "Pašalinti">
+<!ENTITY noscriptPreset "Saugumo lygis">
+<!ENTITY noscriptPreset.off "IÅ¡jungti (jÅ«s Äia rimtai?!)">
+<!ENTITY noscriptPreset.low "Lengvas (Juodasis sąrašas + Web saugumas)">
+<!ENTITY noscriptPreset.medium "Klasikinis (Baltasis sąrašas + Web saugumas)">
+<!ENTITY noscriptPreset.high "Tvirtovė (Visiškas užsidarymas)">
+<!ENTITY noscript.hoverUI "Atverkite leidimų meniu, kai pelė užvedama virš NoScript piktogramos">
+<!ENTITY noscriptDonate "Paaukoti">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/lt/noscript/noscript.properties b/extensions/noscript/chrome/locale/lt/noscript/noscript.properties
new file mode 100644
index 0000000..999caf3
--- /dev/null
+++ b/extensions/noscript/chrome/locale/lt/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Leisti programinius kodus visuotinai (pavojinga)
+forbidGlobal=Drausti programinius kodus visuotinai (patartina)
+allowLocal=Leisti %S
+allowTemp=Laikinai leisti %S
+forbidLocal=Drausti %S
+allowed.glb=Pavojinga! Programiniai kodai visuotinai leidžiami
+allowed.yes=Dabar leidžiami programiniai kodai
+allowed.prt=Iš dalies leidžiami programiniai kodai
+allowed.no=Dabar draudžiami programiniai kodai
+global.warning.title=Įspėjimas!
+global.warning.text=Programiniai kodai bus leidžiami visuotinai (visoms svetainėms).\n Tai gali būti pavojinga.\nAr tikrai norite tęsti?
+audio.samples=Audio pavyzdžiai
+confirm=Ar jūs tikras?
+alwaysAsk=Visada prašyti pavirtinti
+notifyHide=Paslėpti po %S sekundžių
+trust=PasitikÄ—ti %S
+distrust=Pažymėti %S nepatikimu
+untrustedOrigin=nepatikimas Å¡altinis
+xss.notify.generic=NoScript nufiltravo galimą mėginimą paleisti tarp-svetaininį programinį kodą (XSS) iš %S. Techninė informacija įrašyta į konsolę.
+xss.notify.showConsole=Rodyti konsolÄ™...
+xss.notify.showConsole.accessKey=k
+xss.reason.filterXGet=Nukenksminta įtartina užklausa. Pradinis URL [%1$S] užklaustas iš [%2$S]. Nukenksmintas URL: [%3$S].
+xss.reason.filterXGetRef=Nukenksmintas įtartinas užklausos siuntėjas. URL [%1$S] užklaustas iš [%2$S]. Nukenksmintas siuntėjas: [%3$S].
+xss.reason.filterXPost=Nukenksmintas įtartinas duomenų siuntimas į [%1$S] iš [%2$S]: paversta į GET užklausą, skirtą tik duomenų gavimui.
+unsafeReload.warning=Iš naujo NESAUGIAI įkeliama įtartina \n\n%1$S [%2$S]\n\n IŠ [%3$S]\n\nNoScript NEAPSAUGOS šios užklausos!\n
+metaRefresh.notify=NoScript blokavo <META> peradresavimą <NOSCRIPT> elemente: %S po %S sekundžių.
+metaRefresh.notify.follow=Tęsti peradresavimą
+metaRefresh.notify.follow.accessKey=T
+notify.options=Nuostatos
+notify.options.accessKey=N
+reset.title=Atstatyti NoScript
+reset.warning=VISOS NoScript nuostatos ir svetainių leidimai bus iš karto atstatyti į pradines reikšmes.\nŠis veiksmas neatšaukiamas.\nAr norite tęsti?
+bookmarkSync.title=NoScript konfigūracijos žyma
+bookmarkSync.message=Ši žyma NEskirta atverti, ji skirta sinchronizavimui naudojant Weave ar XMarks plėtinius.
+bookmarkSync.confirm=Noscript rado dalinai išsaugotą konfigūracijos žymą \n\n%S.\nAr tikrai norite perrašyti savo vietinę konfigūraciją su šios žymos turiniu?
+ABE.notify=Užklausimo %1$S neleido ABE: <%2$S> %3$S
+ABE.chooseEditor=Pasirinkite tekstinį redaktorių skirtą ABE taisyklių redagvimui
+ABE.syntaxError=ABE taisyklių nustatyme aptikta sintaksės klaida!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Leisti iš visų %S
+allowTempFrom=Laikinai leisti iš visų %S
+siteInfo.confirm=JÅ«s ruoÅ¡iatÄ—s užklausti informacijos apie „%1$S“ puslapį\niÅ¡siunÄiant užklausimÄ… į %2$S.\nAr norite tÄ™sti?
+siteInfo.tooltip=Svetainės informacijai „vidurinysis pelės mygtukas“ ar „shift+paspaudimas“...
+ef.activate=Filtras %S
+ef.options=%S parinktys...
+ef.newName=Įveskite naujo filtro pavadinimą:
+ef.locateExe=Pasirinkite vykdomąjį failą skirtą %S filtrui
+disable=IÅ¡jungti %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/mk-MK/noscript/about.properties b/extensions/noscript/chrome/locale/mk-MK/noscript/about.properties
new file mode 100644
index 0000000..a5eb31f
--- /dev/null
+++ b/extensions/noscript/chrome/locale/mk-MK/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Додатна заштита за вашиот прелиÑтувач Firefox:NoScript дозволува JavaScript, Java (и други додатоци) Ñамо за домени од доверба по ваш избор (на пр. Ñтраницата од вашата банка). Овај приÑтап базиран на блокирање брз база на бела лиÑта ги Ñпречува иÑкориÑтувањата на ÑигурноÑните ÑлабоÑти (познати и непознати!) без загуба на функционалноÑÑ‚... Екпертите ќе Ñе ÑоглаÑат: Firefox е навиÑтина поÑигурен Ñо NoScript :-)
+aboutTitle=За %S
+extensionContributors=Соработници:
+extensionContributors.tip=Луѓе на кои би Ñакале да им Ñе заблагодарите за ова проширување.
+extensionCreatorLabel=Ðвтор:
+changelog=Промени
+changelog.tip=Покажи ги промените
+license=Дозвола
+license.tip=Прочитајте ја дозволата за употреба
+logo.tip=ПоÑетете ја интернет Ñтраницата на проширувањето
+sponsor.tip=ПоÑетете ја интернет Ñтраницата на Ñпонзорот
+informaction.tip=ПоÑетете ја интернет Ñтраницата на InformAction
+extensionHomepage.tip=ПоÑетете ја интернет Ñтраницата на проширувањето
+extensionCreator.tip=ПоÑетете ја интернет Ñтраницата на авторот
+version=Верзија %S
diff --git a/extensions/noscript/chrome/locale/mk-MK/noscript/noscript.dtd b/extensions/noscript/chrome/locale/mk-MK/noscript/noscript.dtd
new file mode 100644
index 0000000..d51b003
--- /dev/null
+++ b/extensions/noscript/chrome/locale/mk-MK/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Опции...">
+<!ENTITY noscriptOptions.accesskey "О">
+<!ENTITY noscriptOptionsLong "NoScript Опции">
+<!ENTITY noscriptAbout "За NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Можете да ги назначите Ñтраните, на кои што Ñкриптите ќе бидат дозволени. Ðапишете ја дозволената адреÑа (на пример http://www.site.com или site.com) и кликнете „Дозволи“">
+<!ENTITY noscriptWebAddress "ÐдреÑа на дозволената веб Ñтрана:">
+<!ENTITY noscriptAllow "Дозволи">
+<!ENTITY noscriptAllow.accesskey "Д">
+<!ENTITY noscriptForbid "Забрани">
+<!ENTITY noscriptForbid.accesskey "З">
+<!ENTITY noscriptTrust "Обележи како Ñтрана од доверба">
+<!ENTITY noscriptTrust.accesskey "д">
+<!ENTITY noscriptUntrust "Обележи како Ñтрана без доверба">
+<!ENTITY noscriptUntrust.accesskey "б">
+<!ENTITY noscriptRemoveSelected "ОтÑтрани ги избраните Ñтраници од лиÑтата на дозволени">
+<!ENTITY noscriptGloballyEnabled "Општо овозможени Ñкрипти (можноÑÑ‚ за опаÑноÑÑ‚)">
+<!ENTITY noscriptAutoReload "ÐвтоматÑко превчитување на Ñтраните при промена на дозволата">
+<!ENTITY noscriptGeneral "Општо">
+<!ENTITY noscriptAppearance "Изглед">
+<!ENTITY noscriptShow "Прикажи...">
+<!ENTITY noscriptCtxMenu "КонтекÑтуално мени (при деÑен клик)">
+<!ENTITY noscriptStatusIcon "Икона на ÑтатуÑната лента">
+<!ENTITY noscriptFullAddr "ЦелоÑни адреÑи (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "ЦелоÑни домени (www.noscript.net)">
+<!ENTITY noscriptBaseDom "ОÑнова на доменот (noscript.net)">
+<!ENTITY noscriptTempCmd "Привремено дозволи за [...]">
+<!ENTITY noscriptSound "Звук при блокирање на Ñкрипти">
+<!ENTITY noscriptImport "Увези лиÑта на дозволени адреÑи">
+<!ENTITY noscriptImport.accesskey "У">
+<!ENTITY noscriptExport "Извези">
+<!ENTITY noscriptExport.accesskey "И">
+<!ENTITY noscriptNotify "Порака при блокирање на Ñкрипти">
+<!ENTITY noscriptNotify.bottom "СмеÑти ја пораката на дното">
+<!ENTITY noscriptSound.choose "Одберете звук">
+<!ENTITY noscriptSound.choose.accesskey "О">
+<!ENTITY noscriptSound.play "Пушти го звукот">
+<!ENTITY noscriptSound.play.accesskey "ш">
+<!ENTITY noscriptSound.reset "Врати го оÑновниот звук">
+<!ENTITY noscriptSound.reset.accesskey "Ñ€">
+<!ENTITY noscriptAdvanced "Ðапредно">
+<!ENTITY noscriptAdditionalPermissions "Додатни овлаÑтувања за одобрени Ñтраници">
+<!ENTITY noscriptAllowClipboard "Дозволи вметнување на форматиран текÑÑ‚ (на пример ХТМЛ)">
+<!ENTITY noscriptAdditionalRestrictions "Додатни забрани за неодобрени Ñтраници">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Примени ги овие ограничувања иÑто така и за Ñтраниците од доверба">
+<!ENTITY noscriptForbidJava "Оневозможи Јава (Java™)">
+<!ENTITY noscriptForbidXSLT "Оневозможи Јава (XSLT)">
+<!ENTITY noscriptForbidSilverlight "Оневозможи Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Оневозможи &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Оневозможи &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Оневозможи @font-face">
+<!ENTITY noscriptForbidWebGL "Оневозможи WebGL">
+<!ENTITY noscriptForbidMedia "Оневозможи &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Оневозможи Макромедија Флеш (Macromedia® Flash®)">
+<!ENTITY noscriptForbidPlugins "Оневозможи ги другите додатоци">
+<!ENTITY noscriptReloadWarn "Овие подеÑувања ќе важат при Ñледното вчитување на Ñтраниците">
+<!ENTITY noscriptConfirmUnblock "Побарај одобрување пред привремено одблокирање на објектот">
+<!ENTITY noscriptStatusLabel "Информација на ÑтатуÑната лента">
+<!ENTITY noscriptForbidBookmarklets "Оневозможи зачувување на врÑката">
+<!ENTITY noscriptShowPlaceholder "Покажи икона на резервираното меÑто">
+<!ENTITY noscriptTruncateTitle "Скрати ги наÑловите на документите">
+<!ENTITY noscriptFixLinks "Обиди Ñе да ги поправиш JavaScript линковите">
+<!ENTITY noscriptAllowBookmarks "Дозволи ги Ñтраниците отворени преку обележувачите">
+<!ENTITY noscriptAllowViaBookmarks "Дозволи ги Ñтраниците отворени преку обележувачите">
+<!ENTITY noscriptAllowPing "Овозможи Ñледење на вашите кликови преку атрибутот „ping“ (&lt;a ping=...&gt;)">
+<!ENTITY noscriptAllowLocalLinks "Дозволи local links">
+<!ENTITY noscriptForbidPing "Оневозможи Ñледење на вашите кликови преку атрибутот „ping“ (&lt;a ping=...&gt;)">
+<!ENTITY noscriptForbidMetaRefresh "Забрани „META“ пренаÑочувања во &lt;noscript&gt; елементи">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "З">
+<!ENTITY noscriptNotifyMeta "Покажи порака за блокираните „META“ пренаÑочувања">
+<!ENTITY noscriptNotifyMeta.accesskey "П">
+<!ENTITY noscriptWhitelist "Бела лиÑта">
+<!ENTITY noscriptPermissions "Дозволи">
+<!ENTITY noscriptRefresh "ОÑвежи">
+<!ENTITY noscriptNotifications "ИзвеÑтувања">
+<!ENTITY noscriptToolbarToggle "Со лев клик на копчето „NoScript“ од алатникот Ñе менуваат дозволите за моментно отворената Ñтрана (главниот домен)">
+<!ENTITY noscriptTrusted "Со доверба">
+<!ENTITY noscriptUntrusted "Без доверба">
+<!ENTITY noscriptUnknown "Ðепознато">
+<!ENTITY noscriptAdd "Додади">
+<!ENTITY noscriptAdd.accesskey "Д">
+<!ENTITY noscriptClose "Затвори">
+<!ENTITY noscriptSiteManager "Организатор на меÑта">
+<!ENTITY noscriptSecurityManager "БезбедноÑен управител">
+<!ENTITY noscriptPolicies "Ðачела">
+<!ENTITY noscriptDefaultPolicies "ОÑновни начела">
+<!ENTITY noscriptSitePolicies "ПоÑебни начела за меÑтото">
+<!ENTITY noscriptNselNever "Ðикогаш не покажувај &lt;noscript&gt; елементи">
+<!ENTITY noscriptNselForce "Покажувај ги &lt;noscript&gt; елементите што Ñе по блокирани &lt;SCRIPT&gt; елементи">
+<!ENTITY noscriptAutoAllowTopLevel "Привремено дозволи за Ñите главни домени">
+<!ENTITY noscriptDescription "Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality... Experts will agree: Firefox is really safer with NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Block CSS-based scanners">
+<!ENTITY noscriptOptFilterXGet "Sanitize cross-site suspicious requests">
+<!ENTITY noscriptOptFilterXPost "Turn cross-site POST requests into data-less GET requests">
+<!ENTITY noscriptShowConsole "Покажи ја Конзолата...">
+<!ENTITY noscriptShowConsole.accesskey "П">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Ðебезбедно Вчитување">
+<!ENTITY noscriptUnsafeReload.accesskey "Ð’">
+<!ENTITY noscriptXssExceptions "Anti-XSS Protection Exceptions">
+<!ENTITY noscriptXssExceptions.description "Destinations matching these regular expressions will NOT be protected aginst XSS">
+<!ENTITY noscriptMatchSample "Примерок кој одговара на шемата:">
+<!ENTITY noscriptReset "Врати ги Ñтарите вредноÑти">
+<!ENTITY noscriptReset.accesskey "Ð’">
+<!ENTITY noscriptResetDef "Врати ги Ñтарите вредноÑти">
+<!ENTITY noscriptResetDef.accesskey "Ñ">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Отповикај ги Привремените Дозволи">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "No placeholder for objects coming from sites marked as untrusted">
+<!ENTITY noscriptCollapseBlockedObjects "Спушти ги блокираните објекти">
+<!ENTITY noscriptExceptions "ИÑклучоци...">
+<!ENTITY noscriptBlockedObjects "Блокирани Објекти">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Блокирај го Ñекој објект кој доаѓа од Ñтраница означена како без доверба">
+<!ENTITY noscriptTempAllowPage "Привремено дозволи ја целата оваа Ñтраница">
+<!ENTITY noscriptTempAllowPage.accesskey "П">
+<!ENTITY noscriptAllowPage "Дозволи ја целата оваа Ñтраница">
+<!ENTITY noscriptAllowPage.accesskey "Д">
+<!ENTITY noscriptTempToPerm "Ðаправи ги овие дозволи на Ñтраницата трајни">
+<!ENTITY noscriptTempToPerm.accesskey "Ð">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "ОднеÑување">
+<!ENTITY noscriptHttps.cookies "Колачиња">
+<!ENTITY noscriptHttps.description "Забрани активна веб Ñодржина оÑвен ако не доаѓа од безбедно (HTTPS) поврзување:">
+<!ENTITY noscriptHttps.never "Ðикогаш">
+<!ENTITY noscriptHttps.proxy "Кога Ñе кориÑти прокÑи(препорачливо Ñо Tor)">
+<!ENTITY noscriptHttps.always "Секогаш">
+<!ENTITY noscriptHttpsForced "ПриÑили ги Ñледните Ñтраници да кориÑтат безбедни (HTTPS) поврзувања:">
+<!ENTITY noscriptHttpsForcedExceptions "Ðикогаш не приÑилувај безбедни (HTTPS) поврзувања за Ñледните Ñтраници:">
+<!ENTITY noscriptSecureCookies "Овозможи ÐвтоматÑки Менаџмент на Безбедните Колачиња">
+<!ENTITY noscriptSecureCookiesForced "ПриÑили енкрипција за Ñите колачиња поÑтавени од Ñледните Ñтраници преку HTTPS:">
+<!ENTITY noscriptSecureCookiesExceptions "Игнорирај неÑигурни колачиња поÑтавени од Ñледните Ñтраници преку HTTPS:">
+<!ENTITY noscriptClearClickTitle "ClearClick Предупредување">
+<!ENTITY noscriptClearClickHeader "Потенцијален обид за Clickjacking / UI Redressing!">
+<!ENTITY noscriptClearClickDescription "NoScript преÑретна интеракција на глушецот или таÑтатурата Ñо делумно Ñкриен елемент. Кликни на Ñликата погоре за промена помеѓу Ñпречената и чиÑтата верзија.">
+<!ENTITY noscriptClearClickOpt "ClearClick заштита на Ñтраниците...">
+<!ENTITY noscriptClearClickReport "Извештај">
+<!ENTITY noscriptClearClickReport.accesskey "И">
+<!ENTITY noscriptClearClickReportId "Ид. на Извештајот:">
+<!ENTITY noscriptTrustedPagesAdj "Ñо доверба">
+<!ENTITY noscriptUntrustedPagesAdj "без доверба">
+<!ENTITY noscriptKeepLocked "Задржи го овој елемент заклучен (препорачливо)">
+<!ENTITY noscriptEmbeddings "Вградени Објекти">
+<!ENTITY noscriptPrev "Претходно">
+<!ENTITY noscriptNext "Следно">
+<!ENTITY noscriptFrameOptErr.title "Оваа Ñодржина не може да биде прикажана во рамка">
+<!ENTITY noscriptFrameOptErr.desc "За да ја заштити вашата ÑигурноÑÑ‚, издавачот на оваа Ñодржина не дозволува да биде прикажана во рамка.">
+<!ENTITY noscriptFrameOptErr.link "Кликни овде за да ја отвориш оваа Ñодржина во нов прозорец">
+<!ENTITY noscriptBookmarkSync "Ðаправи резервна копија на конфигурацијата на NoScript во обележувач за леÑна Ñинхронизација">
+<!ENTITY noscriptShowReleaseNotes "Прикажи ги белешките за изданието при ажурирање">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Правила:">
+<!ENTITY ABE.enabled.label "Вклучи го ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Дозволи Ñтраниците да притиÑкаат нивни ÑопÑтвени правила">
+<!ENTITY ABE.edit.label "Уреди...">
+<!ENTITY ABE.edit.accesskey "У">
+<!ENTITY ABE.enable.label "Вклучи">
+<!ENTITY ABE.enable.accesskey "к">
+<!ENTITY ABE.disable.label "ИÑклучи">
+<!ENTITY ABE.disable.accesskey "И">
+<!ENTITY ABE.refresh.label "ОÑвежи">
+<!ENTITY ABE.refresh.accesskey "О">
+<!ENTITY noscriptUninstall "ОдинÑталирај">
+<!ENTITY noscriptRecentBlocked "Ðеодамна блокирани Ñтраници">
+<!ENTITY noscriptExternalFilters "Ðадворешни Филтери">
+<!ENTITY noscriptEF.enable "Вклучи ги надворешните филтери">
+<!ENTITY noscriptEF.add "Ðов Филтер…">
+<!ENTITY noscriptEF.browse "ПрелиÑтај…">
+<!ENTITY noscriptEF.remove "ОтÑтрани">
+<!ENTITY noscriptDonate "Донирај">
+<!ENTITY noscriptDonate.accesskey "о">
+<!ENTITY noscriptEF.executable "Извршна датотека:">
+<!ENTITY noscriptPreset "Ðиво на БезбедноÑÑ‚">
+<!ENTITY noscriptPreset.off "ИÑклучи (дали Ñте Ñериозни?!)">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/mk-MK/noscript/noscript.properties b/extensions/noscript/chrome/locale/mk-MK/noscript/noscript.properties
new file mode 100644
index 0000000..2615b91
--- /dev/null
+++ b/extensions/noscript/chrome/locale/mk-MK/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Овозможи ги Ñкриптите општо (непрепорачливо)
+forbidGlobal=Оневозможи ги Ñкриптите (препорачливо)
+allowLocal=Дозволи за %S
+allowTemp=Привремено дозволи за %S
+forbidLocal=Забрани за %S
+allowed.glb=Можна опаÑноÑÑ‚! Скриптите Ñе општо дозволени.
+allowed.yes=Скриптите Ñе заÑега дозволени
+allowed.prt=Скриптите Ñе делумно дозволени
+allowed.no=Скриптите Ñе заÑега забранети
+global.warning.title=Предупредување!
+global.warning.text=Скриптите ќе бидат овозможени општо (за Ñекоја Ñтраница).\n Ова подеÑување ве изложува на познати и непознати опаÑноÑти.\nÐко Ñакате да продолжите, притиÑнете „Во ред“.
+audio.samples=Звуци
+confirm=Дали Ñте Ñигурни?
+alwaysAsk=Секогаш прикажувај ја оваа порака
+notifyHide=Скриј ја по %S Ñекунди
+trust=Верувај му на %S
+distrust=Ðе му верувај на %S
+untrustedOrigin=извор без доверба
+xss.notify.generic=„NoScript“ филтрираше можен обид за меѓумеÑно Ñкриптирање (XSS) од %S. Техничките подробноÑти Ñе запишани во конзолата.
+xss.notify.showConsole=Прикажи ја конзолата...
+xss.notify.showConsole.accessKey=к
+xss.reason.filterXGet=ПрочиÑтено е Ñомнителено барање. Првобитната адреÑа [%1$S] е побарана од [%2$S]. ПрочиÑтената адреÑа е [%3$S].)
+xss.reason.filterXGetRef=ПрочиÑтена е Ñомнителна адреÑа на упатувач. ÐдреÑата [%1$S] е побарана од [%2$S]. ПрочиÑтената адреÑа на упатувачот е [%3$S].)
+xss.reason.filterXPost=ПрочиÑтено е Ñомнително качување на датотека на [%1$S] од [%2$S]: Ñменето е во обично „GET“ барање, што нема можноÑÑ‚ за качување датотеки.
+unsafeReload.warning=ÐЕБЕЗБЕДÐО оÑвежување на \n\n%1$S [%2$S]\n\nод [%3$S]\n\n„NoScript“ ÐЕМРда ве заштити од ова барање.\n
+metaRefresh.notify=„NoScript“ Ñпречи <META> пренаÑочување ÑмеÑтено во <NOSCRIPT> елемент: %S за %S Ñекунди.
+metaRefresh.notify.follow=Следи пренаÑочување
+metaRefresh.notify.follow.accessKey=С
+notify.options=Опции
+notify.options.accessKey=О
+reset.title=Враќање на првобитните поÑтавки на „NoScript“
+reset.warning=СИТЕ подеÑувања на „NoScript“ ќе бидат вратени на нивните првобитни вредноÑти.\nОва дејÑтво не може автоматÑки да Ñе поврати.\nДали Ñепак Ñакате да продолжите?
+bookmarkSync.title=NoScript КонфигурациÑки Обележувач
+bookmarkSync.message=Овај обележувач не е наменет за отворање, туку за Ñинхронизирање кориÑтејќи ÑÐµÑ€Ð²Ð¸Ñ ÐºÐ°ÐºÐ¾ Weave или XMarks екÑтензија.
+bookmarkSync.confirm=NoScript пронајде конфигурациÑки облежувач навидум зачуван на\n%S.\nДали навиÑтина Ñакате да ја презапишите вашата NoScript конфигурација Ñо Ñодржината на овај обележувач?
+ABE.notify=Барањето %1$S е филтрирано од ABE: <%2$S> %3$S
+ABE.chooseEditor=Ве молиме изберете уредувач на текÑÑ‚ за ABE правилата
+allowFrom=Дозволи ги Ñите од %S
+allowTempFrom=Привремено дозволи ги Ñите од %S
+ef.activate=Филтер %S
+ef.options=%S опции...
+ef.newName=ВнеÑете го името на новиот филтер:
+disable=ИÑклучи %S
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.locateExe=Select the executable file for the %S filter
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/ms-MY/noscript/about.properties b/extensions/noscript/chrome/locale/ms-MY/noscript/about.properties
new file mode 100644
index 0000000..328ff1a
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ms-MY/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Perlindungan tambahan untuk Firefox anda: Noscript membenarkan JavaScript, Java (dan plugin-plugin lain) hanya untuk domain yang anda percayai(contoh: laman web bank). Senarai putih berdasarkan pre-emptive menghalang eksploitasi terhadap sekuriti(diketahui atau tidak) tanpa pengurangan fungsi...Pakar-pakar telah menyetujui bahawa: Firefox adalah benar-benar selamat dengan NoScript:-)
+aboutTitle=Tentang %S
+extensionContributors=Penyumbang:
+extensionContributors.tip=Orang yang perlu anda berterima kasih untuk fungsi tambahan ini
+extensionCreatorLabel=Penerbit:
+changelog=Tukarlog
+changelog.tip=Tunjukkan Tukarlog
+license=Lesen
+license.tip=Baca Lesen Pengguna-akhir
+logo.tip=Lawati Laman Web Utama fungsi tambahan
+sponsor.tip=Lawati Laman Web Utama penaja
+informaction.tip=Lawati Laman Web Utama InformAction
+extensionHomepage.tip=Lawati Laman Web Utama fungsi tambahan
+extensionCreator.tip=Lawati Laman Web Utama Penerbit
+version=Versi %S
diff --git a/extensions/noscript/chrome/locale/ms-MY/noscript/noscript.dtd b/extensions/noscript/chrome/locale/ms-MY/noscript/noscript.dtd
new file mode 100644
index 0000000..3adc7d0
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ms-MY/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Tetapan...">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Tetapan NoScript">
+<!ENTITY noscriptAbout "Tentang NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Anda boleh menentukan laman web yang anda benarkan skripnya diproses. Taipkan alamat atau domain(contoh:&quot;http://www.tapak.com&quot; atau &quot;tapak.com&quot;) laman web yang diingini dan klik Benarkan">
+<!ENTITY noscriptWebAddress "Alamat laman web:">
+<!ENTITY noscriptAllow "Benarkan">
+<!ENTITY noscriptAllow.accesskey "I">
+<!ENTITY noscriptForbid "Halang">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Tanda sebagai Dipercayai">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Tanda sebagai Tidak Dipercayai">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Buang laman yang dipilih">
+<!ENTITY noscriptGloballyEnabled "Semua skrip diproses secara biasa (bahaya)">
+<!ENTITY noscriptAutoReload "Muat turun semula muka laman secara automatik apabila tetapan ditukar">
+<!ENTITY noscriptGeneral "Umum">
+<!ENTITY noscriptAppearance "Luaran">
+<!ENTITY noscriptShow "Tunjukkan...">
+<!ENTITY noscriptCtxMenu "Menu konteks">
+<!ENTITY noscriptStatusIcon "Bar status ikon">
+<!ENTITY noscriptFullAddr "Alamat penuh (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Domain penuh (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Dasar sekunder domain(noscript.net)">
+<!ENTITY noscriptTempCmd "Proses[...] buat masa ini">
+<!ENTITY noscriptSound "Terima audio apabila skrip dihalang.">
+<!ENTITY noscriptImport "Impot">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Ekspot">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Tunjukkan mesej tentang skrip yang dihalang">
+<!ENTITY noscriptNotify.bottom "Letakkan mesej dibawah">
+<!ENTITY noscriptSound.choose "Pilih">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Mainkan">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Tetapkan semula kepada asal">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Lanjutan">
+<!ENTITY noscriptAdditionalPermissions "Kebenaran Tambahan untuk sumber dipercayai">
+<!ENTITY noscriptAllowClipboard "Benarkan teks disalin (copy dan paste) untuk clipboard luaran">
+<!ENTITY noscriptAdditionalRestrictions "Syarat tambahan untuk laman Tidak Dipercatai">
+<!ENTITY noscriptPlugins "Plugin">
+<!ENTITY noscriptContentBlocker "Laksanakan syarat ini untuk laman yang dipercayai ini juga">
+<!ENTITY noscriptForbidJava "Halang Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Halang XSLT">
+<!ENTITY noscriptForbidSilverlight "Halang Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Halang &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Halang &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Halang @font-face">
+<!ENTITY noscriptForbidWebGL "Halang WebGL">
+<!ENTITY noscriptForbidMedia "Halang &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Halang Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Halang plugin lain">
+<!ENTITY noscriptReloadWarn "Tetapan ini akan kesan apabila muka laman yang dimuat turun semula.">
+<!ENTITY noscriptConfirmUnblock "Tanya dahulu sebelum objek dihalang untuk sementara">
+<!ENTITY noscriptStatusLabel "Label status bar">
+<!ENTITY noscriptForbidBookmarklets "Halang bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Tunjukkan ikon placeholder">
+<!ENTITY noscriptTruncateTitle "Buang tajuk dokumen">
+<!ENTITY noscriptFixLinks "Cubaan untuk membaiki link JavaScript">
+<!ENTITY noscriptAllowBookmarks "Benarkan laman dibuka melalui bookmarks">
+<!ENTITY noscriptAllowViaBookmarks "Benarkan laman dibuka melalui bookmarks">
+<!ENTITY noscriptAllowPing "Benarkan &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Benarkan link tempatan">
+<!ENTITY noscriptForbidPing "Halang &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Halang META pengarah di dalam unsur &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "Papar mesej tentang META alih arah terhalang">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "Senarai putih">
+<!ENTITY noscriptPermissions "Kebenaran">
+<!ENTITY noscriptRefresh "Pulihkan">
+<!ENTITY noscriptNotifications "Notifikasi">
+<!ENTITY noscriptToolbarToggle "Klik kiri pada butang NoScript toolbar Kebenaran untuk laman top-level semasa">
+<!ENTITY noscriptTrusted "Dipercayai">
+<!ENTITY noscriptUntrusted "Tidak Dipercayai">
+<!ENTITY noscriptUnknown "Tidak Diketahui">
+<!ENTITY noscriptAdd "Tambah">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Tutup">
+<!ENTITY noscriptSiteManager "Laman Pengurusan">
+<!ENTITY noscriptSecurityManager "Pengurusan Sekuriti">
+<!ENTITY noscriptPolicies "Polisi">
+<!ENTITY noscriptDefaultPolicies "Polisi Asal">
+<!ENTITY noscriptSitePolicies "Butiran Polisi Laman">
+<!ENTITY noscriptNselNever "Sembunyikan unsur &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Tunjukkan unsur &lt;NOSCRIPT&gt; apabila &lt;SCRIPT&gt; dihalang">
+<!ENTITY noscriptAutoAllowTopLevel "Benarkan sementara laman top-level secara biasa">
+<!ENTITY noscriptDescription "Perlindungaan tambahan untuk Firefox anda: NoScript membenarkan JavaScript, Java (dan plugin-plugin lain) hanya untuk laman yang anda percayai (contoh:laman web bank). Senarai putih berdasarkan pre-emptive menghalang eksploitasi pada sekuriti (yang diketahui dan tidak diketahui!) tanpa pengurangan fungsi... Pakar-pakar telah menyetujui bahawa: Firefox adalah benar-benar selamat dengan NoScript:-)">
+<!ENTITY noscriptOptBlockCssScanners "Halang pengesan CSS">
+<!ENTITY noscriptOptFilterXGet "Membersihkan laman yang disyaki">
+<!ENTITY noscriptOptFilterXPost "Tukarkan permintaan cross-site POST kepada permintaan data GET">
+<!ENTITY noscriptShowConsole "Tunjukkan Konsol...">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "Soalan Kerap Ditanya XSS">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Muat turun semula secara tidak selamat">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Pengecualian Perlindungan Anti-XSS">
+<!ENTITY noscriptXssExceptions.description "Padanan ekspresi ini tidak akan dilindungi dari XSS">
+<!ENTITY noscriptMatchSample "Sampel padanan paten:">
+<!ENTITY noscriptReset "Tetapan semula">
+<!ENTITY noscriptReset.accesskey "s">
+<!ENTITY noscriptResetDef "Tetapkan kepada asal">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Kembalikan semula Kebenaran Sementara">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "Tiada tempaat letak untuk objek yang datang dari laman ditanda sebagai Tidak Dipercayai">
+<!ENTITY noscriptCollapseBlockedObjects "Musnahkan objek yang dihalang">
+<!ENTITY noscriptExceptions "Pengecualian...">
+<!ENTITY noscriptBlockedObjects "Objek yang Dihalang">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Halang setiap objek yang datang dari laman yang ditanda sebagai Tidak Dipercayai">
+<!ENTITY noscriptTempAllowPage "Benarkan laman ini sementara">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "Benarkan laman ini">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Kekalkan kebenaran laman">
+<!ENTITY noscriptTempToPerm.accesskey "M">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "Soalan Kerap Ditanya HTTPS">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Sifat">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Halang butiran aktif laman melainkan datang dari (HTTPS) yang dipercayai:">
+<!ENTITY noscriptHttps.never "Tidak sama sekali">
+<!ENTITY noscriptHttps.proxy "Apabila menggunakan proxy (disyorkan dengan Tor)">
+<!ENTITY noscriptHttps.always "Sentiasa">
+<!ENTITY noscriptHttpsForced "Paksa hubungan (HTTPS) yang dipercayai untuk laman berikut:">
+<!ENTITY noscriptHttpsForcedExceptions "Jangan paksa hubungan (HTTPS) yang dipercayai untuk laman berikut:">
+<!ENTITY noscriptSecureCookies "Aktifkan Pengurusan Perlindungan Cookies Automatik">
+<!ENTITY noscriptSecureCookiesForced "Paksa enkripsi untuk semua cookies menetapkan HTTPS untuk laman berikut:">
+<!ENTITY noscriptSecureCookiesExceptions "Biarkan cookies yang tidak selamat menetapkan HTTPS untuk laman web berikut:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Keupayaan Clickjacking / Cubaan menukarkan UI!">
+<!ENTITY noscriptClearClickDescription "NoScript diinteraksi bertindih pada tetikus atau papan kekunci dengan sebahagian unsur disembunyikan. Klik pada imej diatas untuk dikitar antara versi yang dihalang atau jelas.">
+<!ENTITY noscriptClearClickOpt "Perlindungan ClearClick pada laman...">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "dipercayai">
+<!ENTITY noscriptUntrustedPagesAdj "tidak dipercayai">
+<!ENTITY noscriptKeepLocked "Sentiasa kunci unsur ini (disyorkan)">
+<!ENTITY noscriptEmbeddings "Objek yang dipasang">
+<!ENTITY noscriptPrev "Previuous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptShowReleaseNotes "Pamerkan nota">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Set aturan:">
+<!ENTITY ABE.enabled.label "Aktifkan ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Benarkan laman mengolah aturan sendiri">
+<!ENTITY ABE.edit.label "Sunting…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Aktifkan">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Matikan">
+<!ENTITY ABE.disable.accesskey "M">
+<!ENTITY ABE.refresh.label "Muat Semua">
+<!ENTITY ABE.refresh.accesskey "u">
+<!ENTITY noscriptUninstall "Buang">
+<!ENTITY noscriptRecentBlocked "Laman telah diblok">
+<!ENTITY noscriptExternalFilters "Penapis luar">
+<!ENTITY noscriptEF.enable "Aktifkan penapis luar">
+<!ENTITY noscriptEF.add "Penapis Baru…">
+<!ENTITY noscriptEF.executable "Fail boleh laksana:">
+<!ENTITY noscriptEF.browse "Cari…">
+<!ENTITY noscriptEF.contentType "Jenis butiran (MIME) akan ditapis (pilihan mutlak atau ekspresi biasa)">
+<!ENTITY noscriptEF.exceptions "Jangan tapis objek datang dari halaman ini:">
+<!ENTITY noscriptEF.remove "Buang">
+<!ENTITY noscriptPreset "Taraf keselamatan">
+<!ENTITY noscriptPreset.off "Matikan (anda serius?!)">
+<!ENTITY noscriptPreset.low "Mudah (Senarai hitam + Keselamatan Web)">
+<!ENTITY noscriptPreset.medium "Klasik (Senarai putih + Keselamatan Web)">
+<!ENTITY noscriptPreset.high "Kubu (Kunci penuh)">
+<!ENTITY noscript.hoverUI "Buka menu keizinan apabila tetikus hover pada ikon NoScript">
+<!ENTITY noscriptDonate "Derma">
+<!ENTITY noscriptDonate.accesskey "D">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/ms-MY/noscript/noscript.properties b/extensions/noscript/chrome/locale/ms-MY/noscript/noscript.properties
new file mode 100644
index 0000000..67416d1
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ms-MY/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Semua skrip diproses secara biasa (bahaya)
+forbidGlobal=Skrip tidak diproses secara biasa (disyorkan)
+allowLocal=Benarkan %S
+allowTemp=Benarkan sementara %S
+forbidLocal=Halang %S
+allowed.glb=Bahaya! Semua skrip diproses
+allowed.yes=Skrip diproses buat masa ini
+allowed.prt=Sebahagian skrip diterima
+allowed.no=Skrip dihalang pada masa ini
+global.warning.title=Amaran!
+global.warning.text=Semua skrip akan diproses (untuk setiap laman web).\nTindakan ini adalah bahaya.\nAdakah anda ingin teruskan?
+audio.samples=Sampel audio
+confirm=Anda pasti?
+alwaysAsk=Sentiasa tanya untuk kepastian
+notifyHide=Sembunyikan selepas %S saat
+trust=Benarkan %S
+distrust=Tandakan %S sebagai tidak dipercayai
+untrustedOrigin=adalah sumber tidak dipercayai
+xss.notify.generic=%S cuba menapis NoScript menggunakan cross-site scripting (XSS). Butiran teknikal telah dilogkan ke konsol.
+xss.notify.showConsole=Tunjukkan konsol
+xss.notify.showConsole.accessKey=T
+xss.reason.filterXGet=Permintaan yang disyakki dibersihkan. URL asal [%1$S] diminta daripada [%2$S].URL dibersihkan: [%3$S].
+xss.reason.filterXGetRef=Perujuk permintaan yanga disyakki dibersihkan.URL [%1$S] diminta daripada [%2$S].Perujuk dibersihkan: [%3$S].
+xss.reason.filterXPost=Membersihkan muat naik sumber disyaki [%1$S] dari [%2$S]: telah ditukar kepada fungsi muat turun permintaan GET
+unsafeReload.warning=Dimuatkan secara TIDAK SELAMAT sumber yang disyak \n\n%1$S [%2$S]\n\nDari [%3$S]\n\nNoScript TIDAK melindungi permintaan ini!\n
+metaRefresh.notify=NoScript telah menghalang <META> pengarah di dalam unsur <NOSCRIPT>: %S dalam %S saat.
+metaRefresh.notify.follow=Ikut arah
+metaRefresh.notify.follow.accessKey=I
+notify.options=Tetapan
+notify.options.accessKey=e
+reset.title=Tetapkan semula NoScript
+reset.warning=Semua NoScript tetapan dan kebenaran lawan web akan ditetap pada tetapan asal semula.\nTindakan ini tidak boleh dikembalikan.\nIngin teruskan?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark's content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/nb-NO/noscript/about.properties b/extensions/noscript/chrome/locale/nb-NO/noscript/about.properties
new file mode 100644
index 0000000..283d9b1
--- /dev/null
+++ b/extensions/noscript/chrome/locale/nb-NO/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Ekstra beskyttelse for din Firefox: NoScript tillater JavaScript, Java (og andre plugins) kun for sikre domener av ditt valg (f.eks din nettbank). Denne listen forhindrer eksponering av sikkerhetsfeil (kjente og ukjente!) uten tap av funksjonalitet... Ekspertene er enige: Firefox er tryggere med NoScript.
+aboutTitle=Om %S
+extensionContributors=Bidragsytere:
+extensionContributors.tip=Mennesker som du burde takke for denne utvidelsen
+extensionCreatorLabel=Forfatter
+changelog=Endringslogg
+changelog.tip=Vis endringslogg
+license=Lisens
+license.tip=Les sluttbruker lisens
+logo.tip=Besøk hjemmesiden til denne utvidelsen
+sponsor.tip=Besøk sponsorens hjemmeside
+informaction.tip=Besøk InformAction hjemmeside
+extensionHomepage.tip=Besøk hjemmesiden til denne utvidelsen
+extensionCreator.tip=Besøk forfatterens hjemmeside
+version=Versjon %S
diff --git a/extensions/noscript/chrome/locale/nb-NO/noscript/noscript.dtd b/extensions/noscript/chrome/locale/nb-NO/noscript/noscript.dtd
new file mode 100644
index 0000000..a685414
--- /dev/null
+++ b/extensions/noscript/chrome/locale/nb-NO/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Innstillinger">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript Innstillinger">
+<!ENTITY noscriptAbout "Om NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Du kan spesifisere hvilke websider som har tillatelse til å kjøre scritper. Skriv inn adresse, eller domene (F.eks: &quot;http://www.side.no&quot;, eller &amp;quotside.no&quot;) du ønsker å gi tillatelse til, og klikk Tillat.">
+<!ENTITY noscriptWebAddress "Webadresse:">
+<!ENTITY noscriptAllow "Tillat">
+<!ENTITY noscriptAllow.accesskey "I">
+<!ENTITY noscriptForbid "Forby">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Merk som sikker">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Merk som usikker">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Fjern valgte sider">
+<!ENTITY noscriptGloballyEnabled "Scripts er tillat på alle sider (usikkert!)">
+<!ENTITY noscriptAutoReload "Automatisk oppdater gjeldende side når innstillingene er endret">
+<!ENTITY noscriptGeneral "Generelt">
+<!ENTITY noscriptAppearance "Utseende">
+<!ENTITY noscriptShow "Vis">
+<!ENTITY noscriptCtxMenu "Sammendragsmeny">
+<!ENTITY noscriptStatusIcon "Statusbar ikon">
+<!ENTITY noscriptFullAddr "Full adresse (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Fullt domenenavn (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Base 2nd-nivå domener (noscript.net)">
+<!ENTITY noscriptTempCmd "Midlertidig tillat [...]">
+<!ENTITY noscriptSound "Lydbasert tilbakemelding når scripter er blokkert">
+<!ENTITY noscriptImport "Importer">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Eksporter">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Vis melding om blokkerte script">
+<!ENTITY noscriptNotify.bottom "Plasser beskjeden på bunnen">
+<!ENTITY noscriptSound.choose "Velg">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Spill">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Tilbakestill til standard">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Avansert">
+<!ENTITY noscriptAdditionalPermissions "Ekstra tillatelse for trygge sider">
+<!ENTITY noscriptAllowClipboard "Tillat rik tekst kopi, og lim fra eksterne klippebord">
+<!ENTITY noscriptAdditionalRestrictions "Ekstra restriksjoner for usikre sider">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Legg til disse restriksjonene til hvitlistesider (ikke-svarteliste) også">
+<!ENTITY noscriptForbidJava "Forby Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Forby XSLT">
+<!ENTITY noscriptForbidSilverlight "Forby Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Forby &lt;iFrame&gt;">
+<!ENTITY noscriptForbidFrames "Forby &lt;Frame&gt;">
+<!ENTITY noscriptForbidFonts "Forby @font-face">
+<!ENTITY noscriptForbidWebGL "Forby WebGL">
+<!ENTITY noscriptForbidMedia "Forby &lt;Audio&gt;/&lt;Video&gt;">
+<!ENTITY noscriptForbidFlash "Forby Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Forby andre plug-ins">
+<!ENTITY noscriptReloadWarn "Disse innstillingene vil virke på nye, eller (manuelt) oppdaterte sider">
+<!ENTITY noscriptConfirmUnblock "Spør om bekreftelse før midlertidig kjøring av et objekt">
+<!ENTITY noscriptStatusLabel "Status bar merke">
+<!ENTITY noscriptForbidBookmarklets "Forby bokmerkinger">
+<!ENTITY noscriptShowPlaceholder "Vis plassholder ikon">
+<!ENTITY noscriptTruncateTitle "Forkast dokumenttittler">
+<!ENTITY noscriptFixLinks "Forsøk å fikse JavaScript linker">
+<!ENTITY noscriptAllowBookmarks "Tillat sider å åpnes gjennom bokmerker">
+<!ENTITY noscriptAllowViaBookmarks "Tillat sider å åpnes gjennom bokmerker">
+<!ENTITY noscriptAllowPing "Tillat &lt;A PING..&gt;">
+<!ENTITY noscriptAllowLocalLinks "Tillat lokale linker">
+<!ENTITY noscriptForbidPing "Forby &lt;A PING..&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Forby META re-direkting med &lt;NoScript&gt; elementer">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "Vis beskjeder om blokkerte META re-direkting">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "Hvitlisten">
+<!ENTITY noscriptPermissions "Tillatelser">
+<!ENTITY noscriptRefresh "Oppdater">
+<!ENTITY noscriptNotifications "Meldinger">
+<!ENTITY noscriptToolbarToggle "Venstreklikking på NoScript-verktøyknappen skrur på tillatelser for gjeldende top-nivå siden">
+<!ENTITY noscriptTrusted "Sikre">
+<!ENTITY noscriptUntrusted "Usikre">
+<!ENTITY noscriptUnknown "Ukjent">
+<!ENTITY noscriptAdd "Legg til">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Lukk">
+<!ENTITY noscriptSiteManager "Sideinnstillinger">
+<!ENTITY noscriptSecurityManager "Sikkerhetsinnstillinger">
+<!ENTITY noscriptPolicies "Policies">
+<!ENTITY noscriptDefaultPolicies "Standard Policies">
+<!ENTITY noscriptSitePolicies "Sidespesifisert Policies">
+<!ENTITY noscriptNselNever "Gjem &lt;NoScript&gt; elementer">
+<!ENTITY noscriptNselForce "Vis &lt;NoScript&gt; elementer som følge av blokkerte &lt;Scripts&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Midlertidig tillat top-nivå sider som standard">
+<!ENTITY noscriptDescription "Ekstra beskyttelse for Firefox: NoScript tillater JavaScript, Java (og andre plugin) kun for trygge sider som du velger selv (f.eks. din nettbank). Denne hvitlistebaserte blokkeringssnutten forhindrer utnyttelse av sikkerhetshull (kjente og ukjente) uten tap av funksjonalitet. Ekspertene er enige: Firefox er mye tryggere med NoScript.">
+<!ENTITY noscriptOptBlockCssScanners "Blokker CSS-baserte scannere">
+<!ENTITY noscriptOptFilterXGet "Undersøk misstenkelige forespørsler fra kryssende sider">
+<!ENTITY noscriptOptFilterXPost "Turn cross-site POST requests into data-less GET requests">
+<!ENTITY noscriptShowConsole "Vis konsoll...">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS Faq">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Usikker oppdatering">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Anti-XSS beskyttelsesunntak">
+<!ENTITY noscriptXssExceptions.description "Mål som matcher desse regulære uttrykkene vil IKKE være beskyttet mot XSS.">
+<!ENTITY noscriptMatchSample "Mønsterlikhetstreff, eksempel:">
+<!ENTITY noscriptReset "Tilbakestill">
+<!ENTITY noscriptReset.accesskey "s">
+<!ENTITY noscriptResetDef "Tilbakestill til standard">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Tilbakekall midlertidig tillatelse">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ingen plassholder for objekter som kommer fra sider som er merket som usikker">
+<!ENTITY noscriptCollapseBlockedObjects "Bryt ned blokkerte objekter">
+<!ENTITY noscriptExceptions "Unntak...">
+<!ENTITY noscriptBlockedObjects "Blokkerte objekter">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Blokker alle objekter som kommer fra en side som er merket utrygg">
+<!ENTITY noscriptTempAllowPage "Midlertidig tillat all disse sidene">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "Tillat hele denne siden">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "La sidetillatelsen bli permanent">
+<!ENTITY noscriptTempToPerm.accesskey "M">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS Faq">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Oppførsel">
+<!ENTITY noscriptHttps.cookies "Informasjonskapsler (cookies)">
+<!ENTITY noscriptHttps.description "Forby aktiv webinnhold så fremt det ikke kommer fra en sikker (HTTPS) tilkobling:">
+<!ENTITY noscriptHttps.never "Aldri">
+<!ENTITY noscriptHttps.proxy "NÃ¥r proxy brukes (anbefalt med Tor)">
+<!ENTITY noscriptHttps.always "Alltid">
+<!ENTITY noscriptHttpsForced "Tving følgende sider å bruke sikker (HTTPS) tilkobling:">
+<!ENTITY noscriptHttpsForcedExceptions "Aldri tving sikker (HTTPS) tilkobling for følgende sider:">
+<!ENTITY noscriptSecureCookies "Slå på Automatisk Sikkerhetsbearbeidelse for informasjonskapsler">
+<!ENTITY noscriptSecureCookiesForced "Tving kryptering for alle informasjonskapsler sent over HTTPS for følgende sider:">
+<!ENTITY noscriptSecureCookiesExceptions "Overse usikre informasjonskapsler sent over HTTPS for følgende sider:">
+<!ENTITY noscriptClearClickTitle "Fjern Click Advaring">
+<!ENTITY noscriptClearClickHeader "Potensiell Clickjacking / UI adresseendringsforsøk">
+<!ENTITY noscriptClearClickDescription "NiScript forhindret en mus-, eller tastaturhandling fra et delvis gjemt element. Klikk på bildet under for å svitsje mellom sperret, og renset versjon.">
+<!ENTITY noscriptClearClickOpt "Tøm Clickbeskyttelsen på denne siden.">
+<!ENTITY noscriptClearClickReport "Rapporter">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Rapporter ID:">
+<!ENTITY noscriptTrustedPagesAdj "trygge">
+<!ENTITY noscriptUntrustedPagesAdj "utrygge">
+<!ENTITY noscriptKeepLocked "Hold dette elementet låst (anbefalt)">
+<!ENTITY noscriptEmbeddings "Kapsler">
+<!ENTITY noscriptPrev "Forrige">
+<!ENTITY noscriptNext "Neste">
+<!ENTITY noscriptFrameOptErr.title "Innholdet kan ikke vises i en Frame (ramme)">
+<!ENTITY noscriptFrameOptErr.desc "For å bekytte din sikkerhet lar ikke forfatteren av dette innholdet bli vist i en ramme (frame).">
+<!ENTITY noscriptFrameOptErr.link "Klikk her for å åpne innholdet i nytt vindu.">
+<!ENTITY noscriptBookmarkSync "Backup NoScript konfigurasjonen i et bokmerke for enklere synkronisering">
+<!ENTITY noscriptShowReleaseNotes "Vis utgivelsesnotat på oppdateringer">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Regelsett:">
+<!ENTITY ABE.enabled.label "Aktiver ABE (Applikation Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Tillat sider til å sette egne regelsett">
+<!ENTITY ABE.edit.label "Endre...">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Aktiver">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Deaktiver">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Oppdater">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Avinnstaller">
+<!ENTITY noscriptRecentBlocked "Siste blokkerte sider">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/nb-NO/noscript/noscript.properties b/extensions/noscript/chrome/locale/nb-NO/noscript/noscript.properties
new file mode 100644
index 0000000..0871fac
--- /dev/null
+++ b/extensions/noscript/chrome/locale/nb-NO/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Tillat skripter Globalt (Farlig)
+forbidGlobal=Forby skripter Globalt (Anbefalt)
+allowLocal=Tillat %S
+allowTemp=Midlertidig tillat %S
+forbidLocal=Forby %S
+allowed.glb=Advarsel! Skript Globalt er tillatt
+allowed.yes=Skript er for øyeblikket tillatt
+allowed.prt=Skript delvis tillatt
+allowed.no=Skript er for øyeblikket ikke tillatt
+global.warning.title=Advarsel!
+global.warning.text=Skript vil bli tillatt globalt (for alle sider).\n Dette kan være en usikker handling.\nVil du virkelig fortsette?
+audio.samples=Lydeksempler
+confirm=Er du sikker?
+alwaysAsk=Alltid spør om bekreftelse
+notifyHide=Gjem etter %S sekunder
+trust=Stol på %S
+distrust=Merk %S som usikker
+untrustedOrigin=en usikker opprinnelse
+xss.notify.generic=NoScript filtrerte en potensiell kryss-side skriptingsforsøk (XSS) fra %S. Tekniske detaljer har blitt logget til Konsoll.
+xss.notify.showConsole=Vis Konsoll
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Behandlet mistenkelig forespørsel. Opprinnelig URL [%1$S] forespurt fra [%2$S]. Behandlet URL: [%3$S].
+xss.reason.filterXGetRef=Behandlet mistenkelig refferanseforespørsel. URL [%1$S] forespurt fra [%2$S]. Behandlet URL: [%3$S].
+xss.reason.filterXPost=Behandlet mistenkelig opplasting til [%1$S] fra [%2$S]: omformet til en kun-last-ned forespørsel.
+unsafeReload.warning=USIKKER re-innlasting av mistenkelig\n\n%1$S[%2$S]\n\nFRA[%3$S]\n\nNoScript vil IKKE beskytte mot denne forespørselen!\n
+metaRefresh.notify=NoScript blokkerte en <META> re-direkt innvendig et <NOSCRIPT> element: %S på %S sekunder.
+metaRefresh.notify.follow=Følg redirektinga
+metaRefresh.notify.follow.accessKey=F
+notify.options=Valg
+notify.options.accessKey=O
+reset.title=Reset NoScript
+reset.warning=Alle NoScript innstillinger og sideinnstillinger vil bli sett tilbake til standard verdier umiddelbart.\nDu kan ikke angre denne handlingen.\nVil du fortsette?
+bookmarkSync.title=NoScript kongigurasjonsbokmerke
+bookmarkSync.message=Dette bokmerket er IKKE ment for å åpmes, men for å synkroniseres ved å bruke service som Weave eller XMarks utvidelse.
+bookmarkSync.confirm=NoScript fant en konfigurasjonsbokmerke lagret på \n%S.\nVil du overskrive din lokale NoScript konfigurasjonen med inholdet i dette bokmerket?
+ABE.notify=Forespørsel %1$S filtrert av ABE: <%2$S> %3$S
+ABE.chooseEditor=Vennligst velg en teksteditor for ABE regelsett
+allowFrom=Tillat allt fra %S
+allowTempFrom=Midlertidig tillat allt fra %S
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/nl/noscript/about.properties b/extensions/noscript/chrome/locale/nl/noscript/about.properties
new file mode 100644
index 0000000..ab32df4
--- /dev/null
+++ b/extensions/noscript/chrome/locale/nl/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Extra bescherming voor uw Firefox: NoScript staat JavaScript, Java (en andere plug-ins) alleen toe voor zelf gekozen vertrouwde domeinen (zoals uw website voor internetbankieren). Deze op toestemmingslijsten gebaseerde benadering van blokkering voorkomt exploitatie van beveiligingskwetsbaarheden (bekende en zelfs onbekende!) zonder verlies van functionaliteit… Experts zullen het bevestigen: Firefox is echt veiliger met NoScript :-)
+aboutTitle=Over %S
+extensionContributors=Medewerkers:
+extensionContributors.tip=Personen die een bedankje voor deze extensie verdienen
+extensionCreatorLabel=Auteur:
+changelog=Changelog
+changelog.tip=Changelog tonen
+license=Licentie
+license.tip=Eindgebruikerslicentie lezen
+logo.tip=Startpagina van extensie bezoeken
+sponsor.tip=Startpagina van sponsor bezoeken
+informaction.tip=Startpagina van InformAction bezoeken
+extensionHomepage.tip=Startpagina van extensie bezoeken
+extensionCreator.tip=Startpagina van auteur bezoeken
+version=Versie %S
diff --git a/extensions/noscript/chrome/locale/nl/noscript/noscript.dtd b/extensions/noscript/chrome/locale/nl/noscript/noscript.dtd
new file mode 100644
index 0000000..6380753
--- /dev/null
+++ b/extensions/noscript/chrome/locale/nl/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opties…">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript-opties">
+<!ENTITY noscriptAbout "Over NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "U kunt opgeven welke websites scripts mogen gebruiken. Typ het adres of domein (bv. ‘http://www.website.com’ of ‘website.com’) van de website die u wilt toestaan, en klik daarna op Toestaan.">
+<!ENTITY noscriptWebAddress "Adres van website:">
+<!ENTITY noscriptAllow "Toestaan">
+<!ENTITY noscriptAllow.accesskey "T">
+<!ENTITY noscriptForbid "Verbieden">
+<!ENTITY noscriptForbid.accesskey "V">
+<!ENTITY noscriptTrust "Markeren als vertrouwd">
+<!ENTITY noscriptTrust.accesskey "M">
+<!ENTITY noscriptUntrust "Markeren als niet vertrouwd">
+<!ENTITY noscriptUntrust.accesskey "n">
+<!ENTITY noscriptRemoveSelected "Geselecteerde websites verwijderen">
+<!ENTITY noscriptGloballyEnabled "Scripts worden overal toegestaan (gevaarlijk)">
+<!ENTITY noscriptAutoReload "Betrokken pagina’s automatisch vernieuwen als toestemmingen wijzigen">
+<!ENTITY noscriptAutoReload.currentTab "Alleen het huidige tabblad opnieuw laden">
+<!ENTITY noscriptGeneral "Algemeen">
+<!ENTITY noscriptAppearance "Vormgeving">
+<!ENTITY noscriptShow "Tonen…">
+<!ENTITY noscriptCtxMenu "Contextmenu">
+<!ENTITY noscriptStatusIcon "Statusbalkpictogram">
+<!ENTITY noscriptFullAddr "Volledige adressen (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Volledige domeinen (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Basisdomeinen op 2e niveau (noscript.net)">
+<!ENTITY noscriptTempCmd "[…] tijdelijk toestaan">
+<!ENTITY noscriptSound "Geluidsmelding wanneer scripts worden geblokkeerd">
+<!ENTITY noscriptImport "Importeren">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exporteren">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Bericht over geblokkeerde scripts tonen">
+<!ENTITY noscriptNotify.bottom "Bericht onder in het scherm plaatsen">
+<!ENTITY noscriptSound.choose "Kiezen">
+<!ENTITY noscriptSound.choose.accesskey "K">
+<!ENTITY noscriptSound.play "Afspelen">
+<!ENTITY noscriptSound.play.accesskey "A">
+<!ENTITY noscriptSound.reset "Standaardwaarden">
+<!ENTITY noscriptSound.reset.accesskey "S">
+<!ENTITY noscriptAdvanced "Geavanceerd">
+<!ENTITY noscriptAdditionalPermissions "Aanvullende toestemmingen voor vertrouwde websites">
+<!ENTITY noscriptAllowClipboard "Kopiëren en plakken van tekst met opmaakcodes vanaf extern klembord toestaan">
+<!ENTITY noscriptAdditionalRestrictions "Aanvullende beperkingen voor niet-vertrouwde websites">
+<!ENTITY noscriptPlugins "Plug-ins">
+<!ENTITY noscriptContentBlocker "Deze beperkingen ook op vertrouwde websites toepassen">
+<!ENTITY noscriptForbidJava "Javaâ„¢ verbieden">
+<!ENTITY noscriptForbidXSLT "XSLT verbieden">
+<!ENTITY noscriptForbidSilverlight "Microsoft® Silverlight™ verbieden">
+<!ENTITY noscriptForbidIFrames "&lt;IFRAME&gt; verbieden">
+<!ENTITY noscriptForbidFrames "&lt;FRAME&gt; verbieden">
+<!ENTITY noscriptForbidFonts "@font-face verbieden">
+<!ENTITY noscriptForbidWebGL "WebGL verbieden">
+<!ENTITY noscriptForbidMedia "&lt;AUDIO&gt; / &lt;VIDEO&gt; verbieden">
+<!ENTITY noscriptForbidFlash "Adobe® Flash® verbieden">
+<!ENTITY noscriptForbidPlugins "Andere plug-ins verbieden">
+<!ENTITY noscriptReloadWarn "Deze opties worden van kracht op nieuwe of (handmatig) vernieuwde pagina’s">
+<!ENTITY noscriptConfirmUnblock "Om bevestiging vragen voordat een objectblokkering tijdelijk wordt opgeheven">
+<!ENTITY noscriptStatusLabel "Statusbalklabel">
+<!ENTITY noscriptForbidBookmarklets "Bookmarklets verbieden">
+<!ENTITY noscriptShowPlaceholder "Vervangend pictogram tonen">
+<!ENTITY noscriptTruncateTitle "Documenttitels inkorten">
+<!ENTITY noscriptFixLinks "JavaScript-koppelingen proberen te herstellen">
+<!ENTITY noscriptAllowBookmarks "Via bladwijzers geopende websites toestaan">
+<!ENTITY noscriptAllowViaBookmarks "Via bladwijzers geopende websites toestaan">
+<!ENTITY noscriptAllowPing "&lt;A PING…&gt; toestaan">
+<!ENTITY noscriptAllowLocalLinks "Lokale koppelingen toestaan">
+<!ENTITY noscriptForbidPing "&lt;A PING…&gt; verbieden">
+<!ENTITY noscriptForbidMetaRefresh "META-omleidingen in &lt;NOSCRIPT&gt;-elementen verbieden">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "V">
+<!ENTITY noscriptNotifyMeta "Bericht over geblokkeerde META-omleidingen tonen">
+<!ENTITY noscriptNotifyMeta.accesskey "r">
+<!ENTITY noscriptWhitelist "Toestemmingenlijst">
+<!ENTITY noscriptPermissions "Toestemmingen">
+<!ENTITY noscriptRefresh "Vernieuwen">
+<!ENTITY noscriptNotifications "Meldingen">
+<!ENTITY noscriptToolbarToggle "Met de linkermuisknop op de NoScript-werkbalkknop klikken schakelt toestemmingen voor huidige top-levelwebsite in/uit">
+<!ENTITY noscriptTrusted "Vertrouwd">
+<!ENTITY noscriptUntrusted "Niet vertrouwd">
+<!ENTITY noscriptUnknown "Onbekend">
+<!ENTITY noscriptAdd "Toevoegen">
+<!ENTITY noscriptAdd.accesskey "T">
+<!ENTITY noscriptClose "Sluiten">
+<!ENTITY noscriptSiteManager "Websitebeheerder">
+<!ENTITY noscriptSecurityManager "Beveiligingsbeheerder">
+<!ENTITY noscriptPolicies "Beleid">
+<!ENTITY noscriptDefaultPolicies "Standaardbeleid">
+<!ENTITY noscriptSitePolicies "Website-specifiek beleid">
+<!ENTITY noscriptNselNever "&lt;NOSCRIPT&gt;-elementen verbergen">
+<!ENTITY noscriptNselForce "Het &lt;NOSCRIPT&gt;-element dat na een geblokkeerd &lt;SCRIPT&gt; volgt tonen">
+<!ENTITY noscriptAutoAllowTopLevel "Top-levelwebsites standaard tijdelijk toestaan">
+<!ENTITY noscriptDescription "Extra bescherming voor Firefox: NoScript staat JavaScript, Java (en andere plug-ins) alleen toe voor zelf gekozen vertrouwde domeinen (zoals uw website voor internetbankieren). Deze op toestemmingslijsten gebaseerde blokkering voorkomt exploitatie van beveiligingskwetsbaarheden (bekende en zelfs onbekende!) zonder verlies aan functionaliteit… Experts zullen het bevestigen: Firefox is echt veiliger met NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Op cross-site scripting (CSS) gebaseerde scanners blokkeren">
+<!ENTITY noscriptOptFilterXGet "Verdachte cross-site-aanvragen zuiveren">
+<!ENTITY noscriptOptFilterXPost "Cross-site POST-aanvragen omzetten naar gegevensarme GET-aanvragen">
+<!ENTITY noscriptShowConsole "Console tonen…">
+<!ENTITY noscriptShowConsole.accesskey "t">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS-FAQ…">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Onveilig herladen">
+<!ENTITY noscriptUnsafeReload.accesskey "h">
+<!ENTITY noscriptXssExceptions "Uitzonderingen voor Anti-XSS-bescherming">
+<!ENTITY noscriptXssExceptions.description "Bestemmingen die aan deze reguliere expressies voldoen, zullen NIET tegen XSS worden beschermd.">
+<!ENTITY noscriptMatchSample "Voorbeeld van patroonovereenkomst:">
+<!ENTITY noscriptReset "Herstellen">
+<!ENTITY noscriptReset.accesskey "H">
+<!ENTITY noscriptResetDef "Standaardwaarden terugzetten">
+<!ENTITY noscriptResetDef.accesskey "S">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Tijdelijke toestemmingen intrekken">
+<!ENTITY noscriptRevokeTemp.accesskey "s">
+<!ENTITY noscriptNoUntrustedPlaceholder "Geen vervangend pictogram voor objecten afkomstig van als niet vertrouwd gemarkeerde websites">
+<!ENTITY noscriptCollapseBlockedObjects "Geblokkeerde objecten samenvouwen">
+<!ENTITY noscriptExceptions "Uitzonderingen…">
+<!ENTITY noscriptBlockedObjects "Geblokkeerde objecten">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Elk object afkomstig van een als niet vertrouwd gemarkeerde website blokkeren">
+<!ENTITY noscriptTempAllowPage "Alles op deze pagina tijdelijk toestaan">
+<!ENTITY noscriptTempAllowPage.accesskey "t">
+<!ENTITY noscriptAllowPage "Alles op deze pagina toestaan">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Paginatoestemmingen definitief maken">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS-FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Gedrag">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Actieve webinhoud verbieden, tenzij afkomstig van een beveiligde (HTTPS-)verbinding:">
+<!ENTITY noscriptHttps.never "Nooit">
+<!ENTITY noscriptHttps.proxy "Bij gebruik van een proxy (aanbevolen voor Tor)">
+<!ENTITY noscriptHttps.always "Altijd">
+<!ENTITY noscriptHttpsForced "Onderstaande websites dwingen beveiligde (HTTPS-)verbindingen te gebruiken:">
+<!ENTITY noscriptHttpsForcedExceptions "Onderstaande websites NOOIT dwingen beveiligde (HTTPS-)verbindingen te gebruiken:">
+<!ENTITY noscriptSecureCookies "Automatisch beheer van beveiligde cookies inschakelen">
+<!ENTITY noscriptSecureCookiesForced "Alle cookies ingesteld via HTTPS door onderstaande websites dwingen versleuteling te gebruiken:">
+<!ENTITY noscriptSecureCookiesExceptions "Door onderstaande websites via HTTPS ingestelde onveilige cookies negeren:">
+<!ENTITY noscriptClearClickTitle "‘ClearClick’-waarschuwing">
+<!ENTITY noscriptClearClickHeader "Potentiële poging tot ‘Clickjacking’ / aanpassing van gebruikersinterface!">
+<!ENTITY noscriptClearClickDescription "NoScript heeft een muis- of toetsenbordinteractie met een gedeeltelijk verborgen element onderschept. Klik op de onderstaande afbeelding om tussen de belemmerde en de zichtbare versie om te schakelen.">
+<!ENTITY noscriptClearClickOpt "‘ClearClick’-bescherming op pagina’s…">
+<!ENTITY noscriptClearClickReport "Rapport">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Rapport-ID:">
+<!ENTITY noscriptTrustedPagesAdj "vertrouwd">
+<!ENTITY noscriptUntrustedPagesAdj "niet vertrouwd">
+<!ENTITY noscriptKeepLocked "Dit element geblokkeerd houden (aanbevolen)">
+<!ENTITY noscriptEmbeddings "Ingebouwde objecten">
+<!ENTITY noscriptPrev "Vorige">
+<!ENTITY noscriptNext "Volgende">
+<!ENTITY noscriptFrameOptErr.title "Deze inhoud kan niet in een deelvenster worden weergegeven">
+<!ENTITY noscriptFrameOptErr.desc "Om uw veiligheid te beschermen, staat de uitgever van deze inhoud niet toe deze in een deelvenster weer te geven.">
+<!ENTITY noscriptFrameOptErr.link "Klik hier om deze inhoud in een nieuw venster weer te geven">
+<!ENTITY noscriptBookmarkSync "NoScript-configuratie in een bladwijzer opslaan voor eenvoudige synchronisatie">
+<!ENTITY noscriptShowReleaseNotes "Uitgaveopmerkingen weergeven na bijwerken">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Regels:">
+<!ENTITY ABE.enabled.label "ABE (Application Boundaries Enforcer) inschakelen">
+<!ENTITY ABE.siteEnabled.label "Websites toestaan eigen regels door te geven">
+<!ENTITY ABE.edit.label "Wijzigen…">
+<!ENTITY ABE.edit.accesskey "W">
+<!ENTITY ABE.enable.label "Inschakelen">
+<!ENTITY ABE.enable.accesskey "I">
+<!ENTITY ABE.disable.label "Uitschakelen">
+<!ENTITY ABE.disable.accesskey "U">
+<!ENTITY ABE.refresh.label "Vernieuwen">
+<!ENTITY ABE.refresh.accesskey "V">
+<!ENTITY noscriptUninstall "De-installeren">
+<!ENTITY noscriptRecentBlocked "Onlangs geblokkeerde websites">
+<!ENTITY noscriptExternalFilters "Externe filters">
+<!ENTITY noscriptEF.enable "Externe filters inschakelen">
+<!ENTITY noscriptEF.add "Nieuw filter…">
+<!ENTITY noscriptEF.executable "Uitvoerbaar bestand:">
+<!ENTITY noscriptEF.browse "Bladeren…">
+<!ENTITY noscriptEF.contentType "Te filteren inhoudstype (MIME) (exacte overeenkomst of reguliere expressie):">
+<!ENTITY noscriptEF.exceptions "Objecten niet filteren als ze van deze websites afkomstig zijn:">
+<!ENTITY noscriptEF.remove "Verwijderen">
+<!ENTITY noscriptPreset "Beveiligingsniveau">
+<!ENTITY noscriptPreset.off "Uit (sterk afgeraden!)">
+<!ENTITY noscriptPreset.low "Eenvoudig (Blokkeerlijst en webbeveiliging)">
+<!ENTITY noscriptPreset.medium "Klassiek (Toestemmingenlijst + webbeveiliging)">
+<!ENTITY noscriptPreset.high "Zwaar (volledige afsluiting)">
+<!ENTITY noscript.hoverUI "Toestemmingenmenu openen als muis op NoScript-pictogram wordt geplaatst">
+<!ENTITY noscriptDonate "Doneren">
+<!ENTITY noscriptDonate.accesskey "D">
+<!ENTITY noscriptCascadePermissions "Toestemmingen van bovenste document aan scripts van derden doorgeven">
+<!ENTITY noscriptRestrictSubdocScripting "Scripts in toegestane subdocumenten van niet-toegestane pagina’s blokkeren">
+<!ENTITY noscriptGlobalHttpsWhitelist "HTTPS-scripts op HTTPS-documenten overal toestaan">
+<!ENTITY noscriptPermanentInPrivate "Permanente ‘Toestaan’-opdrachten in privévensters">
+<!ENTITY noscriptCustom "Custom">
diff --git a/extensions/noscript/chrome/locale/nl/noscript/noscript.properties b/extensions/noscript/chrome/locale/nl/noscript/noscript.properties
new file mode 100644
index 0000000..1e0bb24
--- /dev/null
+++ b/extensions/noscript/chrome/locale/nl/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Scripts overal toestaan (gevaarlijk)
+forbidGlobal=Scripts overal verbieden (geadviseerd)
+allowLocal=%S toestaan
+allowTemp=%S tijdelijk toestaan
+forbidLocal=%S verbieden
+allowed.glb=Gevaar! Scripts worden overal toegestaan
+allowed.glb-emb=Scripts worden overal toegestaan, maar sommige insluitingen geblokkeerd
+allowed.yes=Scripts worden momenteel toegestaan
+allowed.prt=Scripts worden gedeeltelijk toegestaan
+allowed.no=Scripts worden momenteel niet toegestaan
+global.warning.title=Waarschuwing!
+global.warning.text=Scripts zullen overal worden toegestaan (voor alle websites).\nDit is een potentieel gevaarlijke actie.\nWilt u echt doorgaan?
+audio.samples=Geluidsvoorbeelden
+confirm=Weet u het zeker?
+alwaysAsk=Altijd om bevestiging vragen
+notifyHide=Verbergen na %S seconden
+trust=%S vertrouwen
+distrust=%S markeren als niet vertrouwd
+untrustedOrigin=een niet-vertrouwde oorsprong
+xss.notify.generic=NoScript heeft een potentiële poging tot cross-site scripting (XSS) van %S geblokkeerd. Technische details zijn in de Console vastgelegd.
+xss.notify.showConsole=Console tonen…
+xss.notify.showConsole.accessKey=t
+xss.reason.filterXGet=Verdachte aanvraag opgeschoond. Oorspronkelijke URL [%1$S] opgevraagd vanaf [%2$S]. Opgeschoonde URL: [%3$S].
+xss.reason.filterXGetRef=Verdachte aanvraagverwijzer opgeschoond. URL [%1$S] opgevraagd vanaf [%2$S]. Opgeschoonde verwijzer: [%3$S].
+xss.reason.filterXPost=Verdachte upload naar [%1$S] vanaf [%2$S] opgeschoond: omgezet naar een alleen downloadbare GET-aanvraag.
+unsafeReload.warning=ONVEILIG opnieuw laden van een verdachte\n\n%1$S [%2$S]\n\nVANAF [%3$S]\n\nNoScript zal deze aanvraag NIET blokkeren!\n
+metaRefresh.notify=NoScript heeft een <META>-omleiding binnen een <NOSCRIPT>-element geblokkeerd: %S in %S seconden.
+metaRefresh.notify.follow=Omleiding volgen
+metaRefresh.notify.follow.accessKey=V
+notify.options=Opties
+notify.options.accessKey=O
+reset.title=NoScript-herinitialisatie
+reset.warning=ALLE NoScript-voorkeuren en toestemmingen voor websites zullen onmiddellijk naar hun standaardwaarden worden teruggezet.\nDeze actie kan niet ongedaan worden gemaakt.\nWilt u doorgaan?
+bookmarkSync.title=NoScript-configuratiebladwijzer
+bookmarkSync.message=Deze bladwijzer is NIET bedoeld om te worden geopend, maar om te worden gesynchroniseerd via een service zoals Weave of de XMarks-extensie.
+bookmarkSync.confirm=NoScript heeft een configuratiebladwijzer gevonden die lijkt te zijn opgeslagen op\n%S.\nWilt u echt uw lokale NoScript-configuratie met de inhoud van deze bladwijzer overschrijven?
+ABE.notify=Aanvraag %1$S gefilterd door ABE: <%2$S> %3$S
+ABE.chooseEditor=Kies een teksteditor voor ABE-regelsets
+ABE.syntaxError=Syntaxisfout in ABE-regelset!
+ABE.wanIpAsLocal=WAN-IP (%S) ∈ LOKAAL
+allowFrom=Alles van %S toestaan
+allowTempFrom=Tijdelijk alles van %S toestaan
+siteInfo.confirm=U gaat om informatie vragen over de website ‘%1$S’\ndoor een aanvraag naar %2$S te verzenden.\nWilt u doorgaan?
+siteInfo.tooltip=Klik met de middelste muisknop of druk op shift en klik voor website-informatie...
+ef.activate=%S filteren
+ef.options=%S-opties…
+ef.newName=Voer de naam in van het nieuwe filter:
+ef.locateExe=Selecteer het uitvoerbare bestand voor het filter %S
+disable=%S uitschakelen
+disable.accessKey=u
+removal.title=Waarschuwing voor beveiligingsdowngrade
+removal.message=Door NoScript uit te schakelen of te verwijderen, worden ALLE door NoScript geboden beschermingen stopgezet.\n\nAls u alleen het per website verwerken van alle scripttoestemmingen vervelend vindt, bestaat er een veiligere keuze.\n\nNoScript kan het blokkeren van scripts stoppen, behalve die welke u als niet vertrouwd markeert, terwijl het u toch via de meest geavanceerde beveiligingsmaatregelen beschermt tegen XSS, Clickjacking, CSRF en andere internetdreigingen.\n\nWilt u echt ALLE beschermingen van NoScript verwijderen?\n
+removal.no=Nee, alleen het blokkeren van scripts stoppen
+removal.yes=Ja, ALLE beschermingen verwijderen
+incompatibleOptions.title=Waarschuwing voor incompatibele opties
+incompatibleOptions=‘%1$S’\nis niet compatibel met ‘%2$S’.\bWilt u het vorige inschakelen en het laatste uitschakelen?
diff --git a/extensions/noscript/chrome/locale/pl/noscript/about.properties b/extensions/noscript/chrome/locale/pl/noscript/about.properties
new file mode 100644
index 0000000..6e9e894
--- /dev/null
+++ b/extensions/noscript/chrome/locale/pl/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Zarządza wykonywaniem przez Firefoksa skryptów JavaScript, Flash i innych wtyczek
+aboutTitle=Informacje o %S
+extensionContributors=Współtwórcy:
+extensionContributors.tip=Osoby, którym powinieneś podziękować za to rozszerzenie
+extensionCreatorLabel=Autor:
+changelog=Lista zmian
+changelog.tip=Wyświetla listę zmian
+license=Umowa licencyjna
+license.tip=Przeczytaj umowÄ™ licencyjnÄ…
+logo.tip=Zobacz stronÄ™ domowÄ… rozszerzenia
+sponsor.tip=Zobacz stronÄ™ domowÄ… sponsora
+informaction.tip=Zobacz stronÄ™ domowÄ… InformAction
+extensionHomepage.tip=Zobacz stronÄ™ domowÄ… rozszerzenia
+extensionCreator.tip=Zobacz stronÄ™ domowÄ… autora
+version=Wersja %S
diff --git a/extensions/noscript/chrome/locale/pl/noscript/noscript.dtd b/extensions/noscript/chrome/locale/pl/noscript/noscript.dtd
new file mode 100644
index 0000000..6270c52
--- /dev/null
+++ b/extensions/noscript/chrome/locale/pl/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Ustawienia">
+<!ENTITY noscriptOptions.accesskey "U">
+<!ENTITY noscriptOptionsLong "NoScript – ustawienia">
+<!ENTITY noscriptAbout "NoScript 5.1.8.5 – informacje">
+<!ENTITY noscriptPermissionsText "Tutaj można okreÅ›lić witryny internetowe, które bÄ™dÄ… mogÅ‚y uruchamiać skrypty. ProszÄ™ wprowadzić adres lub domenÄ™ witryny (np: „http://www.witryna.pl†lub „witryna.plâ€) i nacisnąć przycisk Pozwól.">
+<!ENTITY noscriptWebAddress "Adres witryny:">
+<!ENTITY noscriptAllow "Pozwól">
+<!ENTITY noscriptAllow.accesskey "P">
+<!ENTITY noscriptForbid "Zabroń">
+<!ENTITY noscriptForbid.accesskey "Z">
+<!ENTITY noscriptTrust "Oznacz jako zaufanÄ…">
+<!ENTITY noscriptTrust.accesskey "U">
+<!ENTITY noscriptUntrust "Oznacz jako niezaufanÄ…">
+<!ENTITY noscriptUntrust.accesskey "N">
+<!ENTITY noscriptRemoveSelected "Usuń wybrane witryny">
+<!ENTITY noscriptGloballyEnabled "Pozwalaj na wykonywanie skryptów JavaScript (niebezpieczne)">
+<!ENTITY noscriptAutoReload "Automatycznie odświeżaj stronę po zmianie uprawnień">
+<!ENTITY noscriptGeneral "Ogólne">
+<!ENTITY noscriptAppearance "WyglÄ…d">
+<!ENTITY noscriptShow "Wyświetlaj:">
+<!ENTITY noscriptCtxMenu "Menu kontekstowe">
+<!ENTITY noscriptStatusIcon "IkonÄ™ na pasku stanu">
+<!ENTITY noscriptFullAddr "Nie blokuj z […] (pełny adres np. http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Nie blokuj z […] (pełna domena np. www.noscript.net)">
+<!ENTITY noscriptBaseDom "Nie blokuj z […] (podstawa domeny np. noscript.net)">
+<!ENTITY noscriptTempCmd "Tymczasowo nie blokuj z […]">
+<!ENTITY noscriptSound "Odtwarzaj dźwięk, gdy skrypty są blokowane">
+<!ENTITY noscriptImport "Importuj">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Eksportuj">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Wyświetlaj powiadomienie o blokowanych skryptach">
+<!ENTITY noscriptNotify.bottom "Umieszczaj powiadomienie na dole okna przeglÄ…darki">
+<!ENTITY noscriptSound.choose "PrzeglÄ…daj">
+<!ENTITY noscriptSound.choose.accesskey "P">
+<!ENTITY noscriptSound.play "Odtwórz">
+<!ENTITY noscriptSound.play.accesskey "O">
+<!ENTITY noscriptSound.reset "Domyślny">
+<!ENTITY noscriptSound.reset.accesskey "D">
+<!ENTITY noscriptAdvanced "Zaawansowane">
+<!ENTITY noscriptAdditionalPermissions "Dodatkowe uprawnienia dla zaufanych witryn">
+<!ENTITY noscriptAllowClipboard "Pozwalaj na kopiowanie/wklejanie z zewnętrznego schowka w formacie RTF">
+<!ENTITY noscriptAdditionalRestrictions "Dodatkowe ograniczenia dla niezaufanych witryn">
+<!ENTITY noscriptPlugins "Wtyczki">
+<!ENTITY noscriptContentBlocker "Zastosuj te ograniczenia także do zaufanych witryn">
+<!ENTITY noscriptForbidJava "Blokuj aplety Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Blokuj aplety XSLT">
+<!ENTITY noscriptForbidSilverlight "Blokuj aplety Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Blokuj aplety &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Blokuj aplety &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Blokuj aplety @font-face">
+<!ENTITY noscriptForbidWebGL "Blokuj aplety WebGL">
+<!ENTITY noscriptForbidMedia "Blokuj aplety &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Blokuj animacje Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Blokuj inne wtyczki">
+<!ENTITY noscriptReloadWarn "Uwaga! Opcje te będą działały po odświeżeniu stron oraz w nowo otwieranych stronach.">
+<!ENTITY noscriptConfirmUnblock "Pytaj o potwierdzenie przed czasowym odblokowaniem obiektu">
+<!ENTITY noscriptStatusLabel "Informacje na pasku stanu">
+<!ENTITY noscriptForbidBookmarklets "Blokuj skryptozakładki">
+<!ENTITY noscriptShowPlaceholder "Wyświetlaj ikonę zamiennika">
+<!ENTITY noscriptTruncateTitle "Skracaj tytuły dokumentów">
+<!ENTITY noscriptFixLinks "Próbuj przekształcić odnośniki JavaScript w normalne odnośniki">
+<!ENTITY noscriptAllowBookmarks "Pozwalaj na wykonywanie skryptów witrynom otwieranym z folderu Zakładki">
+<!ENTITY noscriptAllowViaBookmarks "Pozwalaj na wykonywanie skryptów witrynom otwieranym z folderu Zakładki">
+<!ENTITY noscriptAllowPing "Pozwalaj na &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Pozwalaj na wykonywanie skryptów lokalnym odnośnikom">
+<!ENTITY noscriptForbidPing "Nie pozwalaj na &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Nie pozwalaj na przekierowania META znajdujÄ…ce siÄ™ wewnÄ…trz elementu HTML &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "Wyświetlaj informacje o zablokowanych przekierowaniach META">
+<!ENTITY noscriptNotifyMeta.accesskey "M">
+<!ENTITY noscriptWhitelist "Zaufane witryny">
+<!ENTITY noscriptPermissions "Zezwolenia">
+<!ENTITY noscriptRefresh "Odświeżanie">
+<!ENTITY noscriptNotifications "Powiadomienia">
+<!ENTITY noscriptToolbarToggle "Naciśnięcie lp. myszy przycisku NoScript zmienia zezwolenia dla aktywnej witryny">
+<!ENTITY noscriptTrusted "Zaufane">
+<!ENTITY noscriptUntrusted "Niezaufane">
+<!ENTITY noscriptUnknown "Nieznana">
+<!ENTITY noscriptAdd "Dodaj">
+<!ENTITY noscriptAdd.accesskey "D">
+<!ENTITY noscriptClose "Zamknij">
+<!ENTITY noscriptSiteManager "Menedżer witryn">
+<!ENTITY noscriptSecurityManager "Menedżer bezpieczeństwa">
+<!ENTITY noscriptPolicies "Działania">
+<!ENTITY noscriptDefaultPolicies "Działania domyślne">
+<!ENTITY noscriptSitePolicies "Działania specyficzne dla danej witryny">
+<!ENTITY noscriptNselNever "Nie wyświetlaj składników pobieranych z elementu HTML &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Wyświetlaj składniki pobierane z blokowanych witryn przez element &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Domyślne, czasowo dozwolone witryny">
+<!ENTITY noscriptDescription "Dodatkowe zabezpieczenie Firefoksa. NoScript pozwala na wykonywanie kodów JavaScript, Java i innych wtyczek tylko wybranym przez użytkownika zaufanym domenom np. strony bankowe. Lista zaufanych domen pozwala zabezpieczyć się przed znanymi i nieznanymi witrynami próbującymi przechwycić dane o użytkowniku. Eksperci potwierdzają, że Firefox z zainstalowanym NoScript jest bezpieczniejszy.">
+<!ENTITY noscriptOptBlockCssScanners "Blokuj skanery oparte na cross-site scripting (XSS)">
+<!ENTITY noscriptOptFilterXGet "Usuwaj podejrzane żądania">
+<!ENTITY noscriptOptFilterXPost "Zamieniaj żądania cross-site POST na data-less GET">
+<!ENTITY noscriptShowConsole "Wyświetl konsolę">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "S">
+<!ENTITY noscriptXssFaq "XSS - Pytania i odpowiedzi…">
+<!ENTITY noscriptXssFaq.accesskey "X">
+<!ENTITY noscriptUnsafeReload "Odśwież bez zabezpieczeń">
+<!ENTITY noscriptUnsafeReload.accesskey "W">
+<!ENTITY noscriptXssExceptions "Wyjątki zabezpieczeń Anty-XSS">
+<!ENTITY noscriptXssExceptions.description "Obiekty odpowiadające tym wyrażeniom regularnym nie będą zabezpieczane przed XSS">
+<!ENTITY noscriptMatchSample "Przykłady wzorców:">
+<!ENTITY noscriptReset "Resetuj">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Przywróć domyślne">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Unieważnij tymczasowe zezwolenia">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "Nie wyświetlaj ikon zamienników dla obiektów pochodzących z witryn oznaczonych jako niezaufane">
+<!ENTITY noscriptCollapseBlockedObjects "Zwijaj zablokowane obiekty">
+<!ENTITY noscriptExceptions "Wyjątki…">
+<!ENTITY noscriptBlockedObjects "Obiekty zablokowane">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Blokuj każdy obiekt pochodzący z witryny oznaczonej jako niezaufana">
+<!ENTITY noscriptTempAllowPage "Tymczasowo nie blokuj na tej stronie">
+<!ENTITY noscriptTempAllowPage.accesskey "M">
+<!ENTITY noscriptAllowPage "Zezwól na wszystko tej stronie">
+<!ENTITY noscriptAllowPage.accesskey "W">
+<!ENTITY noscriptTempToPerm "Określ jako stałe ustawienia dla tej strony">
+<!ENTITY noscriptTempToPerm.accesskey "S">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS – Pytania i odpowiedzi…">
+<!ENTITY noscriptHttpsFaq.accesskey "H">
+<!ENTITY noscriptHttps.behavior "Zachowanie">
+<!ENTITY noscriptHttps.cookies "Ciasteczka">
+<!ENTITY noscriptHttps.description "Działanie aktywnej zawartości, łącznie z pochodzącą z bezpiecznego połączenia:">
+<!ENTITY noscriptHttps.never "Dopuszczaj">
+<!ENTITY noscriptHttps.proxy "Nie dopuszczaj, gdy jest używane proxy (zalecane przy używaniu Tor)">
+<!ENTITY noscriptHttps.always "Nie dopuszczaj">
+<!ENTITY noscriptHttpsForced "Zawsze stosuj bezpieczne połączenia z następującymi witrynami:">
+<!ENTITY noscriptHttpsForcedExceptions "Nigdy nie stosuj bezpiecznych połączeń z następującymi witrynami:">
+<!ENTITY noscriptSecureCookies "ZarzÄ…dzaj automatycznie bezpiecznymi ciasteczkami">
+<!ENTITY noscriptSecureCookiesForced "Stosuj szyfrowanie ciasteczek ustawionych przez HTTPS dla następujących witryn:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignoruj niebezpieczne ciasteczka ustawione przez HTTPS dla następujących witryn:">
+<!ENTITY noscriptClearClickTitle "Ostrzeżenia kliknięć ukrytych obiektów">
+<!ENTITY noscriptClearClickHeader "Potencjalne zagrożenie przechwytywania kliknięć/Próba przywrócenia prawidłowego interfejsu">
+<!ENTITY noscriptClearClickDescription "NoScript przechwycił interakcję myszy lub klawiatury z częściowo ukrytym elementem. Kliknij na powyższym obrazku, aby wyświetlić/schować ukrytą wersję.">
+<!ENTITY noscriptClearClickOpt "Zabezpieczenia kliknięć ukrytych obiektów na stronach internetowych">
+<!ENTITY noscriptClearClickReport "Raport">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "ID raportu:">
+<!ENTITY noscriptTrustedPagesAdj "zaufana">
+<!ENTITY noscriptUntrustedPagesAdj "niezaufana">
+<!ENTITY noscriptKeepLocked "Pozostaw ten element zablokowany (zalecane)">
+<!ENTITY noscriptEmbeddings "Obiekty osadzone">
+<!ENTITY noscriptPrev "Poprzedni">
+<!ENTITY noscriptNext "Następny">
+<!ENTITY noscriptFrameOptErr.title "Ta treść nie może zostać wyświetlona w ramce">
+<!ENTITY noscriptFrameOptErr.desc "Aby chronić twoje bezpieczeństwo, wydawca tej treści nie zezwolił na wyświetlanie jej w ramce.">
+<!ENTITY noscriptFrameOptErr.link "Kliknij tutaj, aby otworzyć tę treść w nowym oknie">
+<!ENTITY noscriptBookmarkSync "Aby łatwo synchronizować ustawienia NoScript, utwórz kopię ustawień jako zakładkę">
+<!ENTITY noscriptShowReleaseNotes "Wyświetlaj informacje o wydaniu po wykonaniu aktualizacji">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Zestaw reguł:">
+<!ENTITY ABE.enabled.label "WÅ‚Ä…cz ABE (Ochroniarz aplikacji)">
+<!ENTITY ABE.siteEnabled.label "Zezwalaj witrynom stosować własne zestawy reguł">
+<!ENTITY ABE.edit.label "Edytuj">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "WÅ‚Ä…cz">
+<!ENTITY ABE.enable.accesskey "W">
+<!ENTITY ABE.disable.label "Wyłącz">
+<!ENTITY ABE.disable.accesskey "C">
+<!ENTITY ABE.refresh.label "Odśwież">
+<!ENTITY ABE.refresh.accesskey "O">
+<!ENTITY noscriptUninstall "Odinstaluj">
+<!ENTITY noscriptRecentBlocked "Ostatnio zablokowane witryny">
+<!ENTITY noscriptExternalFilters "Filtry zewnętrzne">
+<!ENTITY noscriptEF.enable "Włącz filtry zewnętrzne">
+<!ENTITY noscriptEF.add "Nowy filtr…">
+<!ENTITY noscriptEF.executable "Plik wykonywalny:">
+<!ENTITY noscriptEF.browse "Przeglądaj…">
+<!ENTITY noscriptEF.contentType "Zawartość typu (MIME) będzie filtrowana (dokładne dopasowanie lub wyrażenie regularne):">
+<!ENTITY noscriptEF.exceptions "Nie filtruj obiektów przychodzących z następujących witryn:">
+<!ENTITY noscriptEF.remove "Usuń">
+<!ENTITY noscriptPreset "Poziom zabezpieczeń">
+<!ENTITY noscriptPreset.off "Wyłączone (naprawdę?!)">
+<!ENTITY noscriptPreset.low "Niski (lista zabronionych + zabezpieczenia sieciowe)">
+<!ENTITY noscriptPreset.medium "Åšredni (lista dozwolonych + zabezpieczenia sieciowe))">
+<!ENTITY noscriptPreset.high "Wysoki (pełne blokowanie)">
+<!ENTITY noscript.hoverUI "Otwórz menu ustawień po umieszczeniu wskaźnika myszy nad ikoną NoScript">
+<!ENTITY noscriptDonate "Dotacje">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/pl/noscript/noscript.properties b/extensions/noscript/chrome/locale/pl/noscript/noscript.properties
new file mode 100644
index 0000000..a6d935d
--- /dev/null
+++ b/extensions/noscript/chrome/locale/pl/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Wyłącz blokowanie skryptów (niebezpieczne)
+forbidGlobal=Włącz blokowanie skryptów JavaScript (zalecane)
+allowLocal=Nie blokuj z %S
+allowTemp=Tymczasowo nie blokuj z %S
+forbidLocal=Blokuj z %S
+allowed.glb=Niebezpieczeństwo! Wyłączono blokowanie skryptów.
+allowed.yes=Wykonywanie skryptów dozwolone
+allowed.prt=Wykonywanie skryptów tymczasowo dozwolone
+allowed.no=Zablokowane skrypty:
+global.warning.title=Uwaga!
+global.warning.text=Wykonywanie skryptów zostanie dozwolone globalnie (dla każdej strony).\nStanowi to potencjalne zagrożenie. Czy na pewno chcesz kontynuować?
+audio.samples=Pliki dźwiękowe
+confirm=Czy na pewno?
+alwaysAsk=Zawsze pytaj o potwierdzenie
+notifyHide=Ukryj po %S sekundach
+trust=Oznacz %S jako zaufanÄ…
+distrust=Oznacz %S jako niezaufanÄ…
+untrustedOrigin=niezaufane źródło
+xss.notify.generic=NoScript odfiltrował potencjalne próby przechwytywania informacji metodą cross-site scripting (XSS) pochodzące z %S. Dane techniczne zostały zapisane w dzienniku zdarzeń.
+xss.notify.showConsole=Wyświetl konsolę
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Wyczyszczone podejrzane żądania. Oryginalny URL [%1$S] żądany z [%2$S]. Wyczyszczony URL: [%3$S].
+xss.reason.filterXGetRef=Wyczyszczone podejrzane żądania referera. URL [%1$S] żądany z [%2$S]. Wyczyszczony referer: [%3$S].
+xss.reason.filterXPost=Wyczyszczone podejrzane wysyłki do [%1$S] z [%2$S]: zmienione na żądania download-only GET.
+unsafeReload.warning=Niezabezpieczone odświeżanie podejrzanych\n\n%1$S [%2$S]\n\nz [%3$S]\n\nNoScript nie będzie zabezpieczał tych żądań!\n
+metaRefresh.notify=NoScript zablokował przekierowanie <META> znajdujące się wewnątrz elementu <NOSCRIPT>: %S w %S s.
+metaRefresh.notify.follow=Podążaj za przekierowaniem
+metaRefresh.notify.follow.accessKey=P
+notify.options=Opcje
+notify.options.accessKey=O
+reset.title=Przywróć domyślne
+reset.warning=Zostaną przywrócone wartości domyślne ustawień NoScript i zezwoleń witryn.\nTej operacji nie można odwrócić.\nCzy kontynuować?
+bookmarkSync.title=Zakładka konfiguracyjna MoScript
+bookmarkSync.message=To nie jest typowa zakładka i nie służy do otwierania strony. Służy ona do synchronizacji za pomocą serwisu Weave lub rozszerzenia XMarks.
+bookmarkSync.confirm=NoScript znalazł zakładkę konfiguracyjną zapisaną prawdopodobnie w\n%S.\nCzy chcesz zastąpić lokalną konfigurację NoScript zawartością tej zakładki?
+ABE.notify=Żądanie %1$S zostało przefiltrowane przez ABE: <%2$S> %3$S
+ABE.chooseEditor=Wybierz edytor tekstu do edycji zestawu reguł ABE
+ABE.syntaxError=Błąd składni w zestawie reguł ABE!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Nie blokuj wszystkich z %S
+allowTempFrom=Nie blokuj tymczasowo wszystkich z %S
+siteInfo.confirm=Zamierzasz poprosić o informacje o witrynie „%1$Sâ€\nwysyÅ‚ajÄ…c zapytanie do %2$S.\nCzy chcesz kontynuować?
+siteInfo.tooltip=Kliknij prawym przyciskiem myszy lub użyj skrótu Shift+kliknięcie, by uzyskac informacje o witrynie…
+ef.activate=Filtr %S
+ef.options=%S opcji…
+ef.newName=Podaj nazwÄ™ nowego filtru:
+ef.locateExe=Wybierz plik wykonywalny dla filtru %S
+disable=Wyłącz %S
+disable.accessKey=W
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/pt-BR/noscript/about.properties b/extensions/noscript/chrome/locale/pt-BR/noscript/about.properties
new file mode 100644
index 0000000..8b114cb
--- /dev/null
+++ b/extensions/noscript/chrome/locale/pt-BR/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Proteção extra para o seu Firefox: O NoScript permite o uso de JavaScripts, Java (e outros plugins) somente para os domínios confiáveis que você selecionar (por exemplo, no site do seu banco). Esse bloqueio baseado em uma lista branca previne a exploração de vulnerabilidades de segurança (conhecidas e até mesmo desconhecidas!) sem perda de funcionalidades… Usuários e especialistas concordam: o Firefox é realmente mais seguro com o NoScript :-)
+aboutTitle=Sobre %S
+extensionContributors=Colaboradores:
+extensionContributors.tip=Pessoas a quem você deve agradecer por esta extensão
+extensionCreatorLabel=Autor:
+changelog=Histórico de mudanças
+changelog.tip=Mostrar histórico de mudanças
+license=Licença
+license.tip=Ler licença do usuário
+logo.tip=Visitar página da extensão
+sponsor.tip=Visitar página dos patrocinadores
+informaction.tip=Visitar página da InformAction
+extensionHomepage.tip=Visitar página da extensão
+extensionCreator.tip=Visitar página do autor
+version=Versão %S
diff --git a/extensions/noscript/chrome/locale/pt-BR/noscript/noscript.dtd b/extensions/noscript/chrome/locale/pt-BR/noscript/noscript.dtd
new file mode 100644
index 0000000..c2ceca4
--- /dev/null
+++ b/extensions/noscript/chrome/locale/pt-BR/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opções">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Opções do NoScript">
+<!ENTITY noscriptAbout "Sobre o NoScript 5.1.8.5…">
+<!ENTITY noscriptPermissionsText "Você pode especificar os sites que podem executar JavaScripts. Escreva o endereço ou o domínio (ex &quot;http://www.site.com&quot; ou &quot;site.com&quot;) do site que deseja permitir e depois clique em Permitir.">
+<!ENTITY noscriptWebAddress "Endereço:">
+<!ENTITY noscriptAllow "Permitir">
+<!ENTITY noscriptAllow.accesskey "P">
+<!ENTITY noscriptForbid "Proibir">
+<!ENTITY noscriptForbid.accesskey "P">
+<!ENTITY noscriptTrust "Marcar como Confiável">
+<!ENTITY noscriptTrust.accesskey "C">
+<!ENTITY noscriptUntrust "Marcar como Não Confiável">
+<!ENTITY noscriptUntrust.accesskey "N">
+<!ENTITY noscriptRemoveSelected "Remover Sites Selecionados">
+<!ENTITY noscriptGloballyEnabled "JavaScript Globalmente Permitido (perigoso)">
+<!ENTITY noscriptAutoReload "Atualizar automaticamente a página atual quando as permissões são alteradas.">
+<!ENTITY noscriptGeneral "Geral">
+<!ENTITY noscriptAppearance "Aparência">
+<!ENTITY noscriptShow "Mostrar…">
+<!ENTITY noscriptCtxMenu "Menu de Contexto">
+<!ENTITY noscriptStatusIcon "Ãcone da Barra de Status">
+<!ENTITY noscriptFullAddr "Endereços completos (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Domínios completos (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Base de domínios do 2º nível (noscript.net)">
+<!ENTITY noscriptTempCmd "Permitir temporariamente […]">
+<!ENTITY noscriptSound "Alerta de áudio quando os scripts são bloqueados">
+<!ENTITY noscriptImport "Importar">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exportar">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Mostrar mensagens sobre os scripts bloqueados">
+<!ENTITY noscriptNotify.bottom "Mostrar mensagens no botão">
+<!ENTITY noscriptSound.choose "Escolher">
+<!ENTITY noscriptSound.choose.accesskey "E">
+<!ENTITY noscriptSound.play "Tocar">
+<!ENTITY noscriptSound.play.accesskey "T">
+<!ENTITY noscriptSound.reset "Restaurar padrões">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Avançado">
+<!ENTITY noscriptAdditionalPermissions "Permissões adicionais para sites confiáveis">
+<!ENTITY noscriptAllowClipboard "Permitir copiar e colar texto a partir da área de transferência">
+<!ENTITY noscriptAdditionalRestrictions "Restrições adicionais para sites não confiáveis">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Aplicar restrições a sites confiáveis também.">
+<!ENTITY noscriptForbidJava "Proibir Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Proibir XSLT">
+<!ENTITY noscriptForbidSilverlight "Proibir Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Proibir &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Proibir &lt;FRAMES&gt;">
+<!ENTITY noscriptForbidFonts "Proibir @font-face">
+<!ENTITY noscriptForbidWebGL "Proibir WebGL">
+<!ENTITY noscriptForbidMedia "Proibir &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Proibir Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Proibir outros plugins">
+<!ENTITY noscriptReloadWarn "Estas opções terão efeito em páginas novas ou (manualmente) atualizadas.">
+<!ENTITY noscriptConfirmUnblock "Pedir confirmação antes de desbloquear temporariamente um objeto">
+<!ENTITY noscriptStatusLabel "Informações na barra de status">
+<!ENTITY noscriptForbidBookmarklets "Proibir livretos de favoritos">
+<!ENTITY noscriptShowPlaceholder "Mostrar ícone de substituição">
+<!ENTITY noscriptTruncateTitle "Quebrar títulos dos documentos">
+<!ENTITY noscriptFixLinks "Tentar corrigir links JavaScript">
+<!ENTITY noscriptAllowBookmarks "Permitir sites abertos pelos favoritos">
+<!ENTITY noscriptAllowViaBookmarks "Permitir sites abertos pelos favoritos">
+<!ENTITY noscriptAllowPing "Permitir &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Permitir links locais">
+<!ENTITY noscriptForbidPing "Proibir &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Proibir redirecionamentos META dentro de elementos &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "A">
+<!ENTITY noscriptNotifyMeta "Exibir mensagem sobre META redirecionamentos bloqueados">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "Lista Branca">
+<!ENTITY noscriptPermissions "Permissões">
+<!ENTITY noscriptRefresh "Atualizar">
+<!ENTITY noscriptNotifications "Notificações">
+<!ENTITY noscriptToolbarToggle "Um clique esquerdo no botão do NoScript na barra de ferramentas altera as permissões para o site atual">
+<!ENTITY noscriptTrusted "Confiável">
+<!ENTITY noscriptUntrusted "Não confiável">
+<!ENTITY noscriptUnknown "Desconhecido">
+<!ENTITY noscriptAdd "Adicionar">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Fechar">
+<!ENTITY noscriptSiteManager "Gerenciador de Sites">
+<!ENTITY noscriptSecurityManager "Gerenciador de segurança">
+<!ENTITY noscriptPolicies "Políticas">
+<!ENTITY noscriptDefaultPolicies "Políticas Padrão">
+<!ENTITY noscriptSitePolicies "Políticas Específicas do Site">
+<!ENTITY noscriptNselNever "Ocultar elementos &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Mostrar o elemento &lt;NOSCRIPT&gt; que perseguiu um script bloqueado &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Permitir temporariamente todos os sites de alto nível por padrão">
+<!ENTITY noscriptDescription "Proteção extra para o seu Firefox: O NoScript permite o uso de JavaScripts, Java (e outros plugins) somente para os domínios confiáveis que você selecionar (como por exemplo no site do seu internet banking). Esse bloqueio baseado em uma lista branca previne a exploração de vulnerabilidades de segurança (conhecidas e até mesmo as desconhecidas!) sem perda de desempenho… Usuários e especialistas concordam: o Firefox é realmente mais seguro com o NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Bloquear varredores baseados em CSS">
+<!ENTITY noscriptOptFilterXGet "Desinfectar requerimentos suspeitos via site">
+<!ENTITY noscriptOptFilterXPost "Alterar requerimentos perigosos via site em requerimentos sem dados">
+<!ENTITY noscriptShowConsole "Mostrar Console…">
+<!ENTITY noscriptShowConsole.accesskey "M">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "Perguntas e respostas do XSS …">
+<!ENTITY noscriptXssFaq.accesskey "P">
+<!ENTITY noscriptUnsafeReload "Recarregamento Inseguro">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Proteção Anti-XSS através das exceções">
+<!ENTITY noscriptXssExceptions.description "Os destinos que combinarem essas expressões NÃO serão protegidos do XSS">
+<!ENTITY noscriptMatchSample "Exemplo ilustrativo de combinação:">
+<!ENTITY noscriptReset "Restaurar">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Restaurar para os padrões">
+<!ENTITY noscriptResetDef.accesskey "p">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Anular Permissões Temporárias">
+<!ENTITY noscriptRevokeTemp.accesskey "A">
+<!ENTITY noscriptNoUntrustedPlaceholder "Nenhum placeholder para objetos provenientes de sites marcados como não confiáveis">
+<!ENTITY noscriptCollapseBlockedObjects "Quebrar objetos bloqueados">
+<!ENTITY noscriptExceptions "Exceções…">
+<!ENTITY noscriptBlockedObjects "Objetos bloqueados">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Bloquear todos os objetos provenientes de um site marcado como não confiável">
+<!ENTITY noscriptTempAllowPage "Autorizar tudo temporariamente nesta página">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Permitir todos nesta página">
+<!ENTITY noscriptAllowPage.accesskey "t">
+<!ENTITY noscriptTempToPerm "Tornar as permissões da página permanentes">
+<!ENTITY noscriptTempToPerm.accesskey "o">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "FAQ HTTPS">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Comportamento">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Proibir conteúdo web ativo a não ser que venha de uma conexão segura (HTTPS).">
+<!ENTITY noscriptHttps.never "Nunca">
+<!ENTITY noscriptHttps.proxy "Quando estiver usando um proxy (recomendado com Tor)">
+<!ENTITY noscriptHttps.always "Sempre">
+<!ENTITY noscriptHttpsForced "Forçar os sites seguintes a usarem conexões seguras (HTTPS):">
+<!ENTITY noscriptHttpsForcedExceptions "Nunca forçar conexão segura (HTTPS) para os sites seguintes:">
+<!ENTITY noscriptSecureCookies "Ativar Gerenciamento Automático e Seguro de Cookies">
+<!ENTITY noscriptSecureCookiesForced "Forçar encriptação para todos os cookies usados por HTTPS pelos sites seguintes:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignorara cookies inseguros usados por HTTPS pelos sites seguintes:">
+<!ENTITY noscriptClearClickTitle "Alerte de ClearClick">
+<!ENTITY noscriptClearClickHeader "Clickjacking em potencial / Tentativa de redirecionamento da interface do usuário!">
+<!ENTITY noscriptClearClickDescription "O NoScript interceptou uma interação por mouse ou teclado com um elemento parcialmente oculto. Clique na imagem para rodar entre a versão oculta e a versão clara.">
+<!ENTITY noscriptClearClickOpt "Proteção Clearclick nas páginas...">
+<!ENTITY noscriptClearClickReport "Relatório">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "ID do Relatório:">
+<!ENTITY noscriptTrustedPagesAdj "confiável">
+<!ENTITY noscriptUntrustedPagesAdj "não confiável">
+<!ENTITY noscriptKeepLocked "Manter esse elemento travado (recomendado)">
+<!ENTITY noscriptEmbeddings "Objetos Integrados">
+<!ENTITY noscriptPrev "Anterior">
+<!ENTITY noscriptNext "Próximo">
+<!ENTITY noscriptFrameOptErr.title "Esse conteúdo não pode ser mostrado num frame">
+<!ENTITY noscriptFrameOptErr.desc "Para aumentar sua segurança, o publicador desse conteúdo não permite que ele seja mostrado num frame.">
+<!ENTITY noscriptFrameOptErr.link "Clique aqui para abrir esse conteúdo em uma nova janela">
+<!ENTITY noscriptBookmarkSync "Fazer backup da configuração do NoScript em um favorito para fácil sincronização">
+<!ENTITY noscriptShowReleaseNotes "Mostra as notas de lançamento das atualizações">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Ajustes de regras">
+<!ENTITY ABE.enabled.label "Ativar ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Permitir que sites usem suas próprias regras">
+<!ENTITY ABE.edit.label "Editar...">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Ativar">
+<!ENTITY ABE.enable.accesskey "A">
+<!ENTITY ABE.disable.label "Desativar">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Atualizar">
+<!ENTITY ABE.refresh.accesskey "t">
+<!ENTITY noscriptUninstall "Desinstalar">
+<!ENTITY noscriptRecentBlocked "Sites bloqueados recentemente">
+<!ENTITY noscriptExternalFilters "Filtros externos">
+<!ENTITY noscriptEF.enable "Habilitar filtros externos">
+<!ENTITY noscriptEF.add "Novo filtro…">
+<!ENTITY noscriptEF.executable "Arquivo executável:">
+<!ENTITY noscriptEF.browse "Procurar…">
+<!ENTITY noscriptEF.contentType "Tipo de conteúdo (MIME) a ser filtrado (valor exato ou expressão regular):">
+<!ENTITY noscriptEF.exceptions "Não filtrar objetos provenientes desses sites:">
+<!ENTITY noscriptEF.remove "Remover">
+<!ENTITY noscriptPreset "Nível de segurança">
+<!ENTITY noscriptPreset.off "Nenhum (está falando sério?!)">
+<!ENTITY noscriptPreset.low "Tranquilo (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Clássico (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortaleza (bloqueio completo)">
+<!ENTITY noscript.hoverUI "Abrir o menu de permissões quando o mouse passar sobre o ícone do NoScript">
+<!ENTITY noscriptDonate "Doar">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/pt-BR/noscript/noscript.properties b/extensions/noscript/chrome/locale/pt-BR/noscript/noscript.properties
new file mode 100644
index 0000000..bd1b41e
--- /dev/null
+++ b/extensions/noscript/chrome/locale/pt-BR/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Permitir JavaScript Globalmente (perigoso)
+forbidGlobal=Proibir JavaScript Globalmente (recomendado)
+allowLocal=Permitir %S
+allowTemp=Temporariamente permitir %S
+forbidLocal=Proibir %S
+allowed.glb=Perigo! JavaScript Permitido Globalmente
+allowed.yes=JavaScripts Atualmente Permitidos
+allowed.prt=JavaScripts Parcialmente Permitidos
+allowed.no=JavaScripts Atualmente Proibidos
+global.warning.title=Alerta!
+global.warning.text=Os JavaScripts serão globalmente permitidos (em qualquer site).\n Esta é uma ação potencialmente perigosa.\nTem certeza que deseja prosseguir?
+audio.samples=Amostras de Ãudio
+confirm=Tem certeza?
+alwaysAsk=Sempre pedir confirmação
+notifyHide=Ocultar após %S segundos
+trust=Confiar %S
+distrust=Marcar %S como não confiável
+untrustedOrigin=uma origem não confiável
+xss.notify.generic=O NoScript filtrou uma tentativa de uso de script via site(XSS) vinda de %S. Detalhes técnicos foram gravados no Console.
+xss.notify.showConsole=Mostrar Console…
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Desinfectou um requerimento suspeito. URL original [%1$S] requerido por [%2$S]. URL desinfectada: [%3$S].
+xss.reason.filterXGetRef=Desinfectou um requerimento de referência suspeita. URL [%1$S] requerida por [%2$S]. Referência desinfectada: [%3$S].
+xss.reason.filterXPost=Desinfectou um envio de arquivo suspeito de [%1$S] para [%2$S]: transformado em um requerimento do tipo somente download.
+unsafeReload.warning=Recarregamento INSEGURO e suspeito\n\n%1$S [%2$S}\n\nDE [%3$S]\n\nO NoScript NÃO protegerá este requerimento!\n
+metaRefresh.notify=O NoScript bloqueou um redirecionamento <META> dentro de um elemento do <NOSCRIPT>: %S em %S segundos.
+metaRefresh.notify.follow=Perseguir redirecionamento
+metaRefresh.notify.follow.accessKey=F
+notify.options=Opções
+notify.options.accessKey=O
+reset.title=Restaurar configurações do NoScript
+reset.warning=TODAS as configurações do NoScript e permissões de sites serão restauradas aos seus valores padrão imediatamente.\nEsta ação não poderá ser revertida.\nQuer prosseguir?
+bookmarkSync.title=Configuração de Favoritos do NoScript
+bookmarkSync.message=Esse favorito NÃo foi feito para ser aberto, mas para ser sincronizado utilizando um serviço como o Weave ou a extensão XMarks.
+bookmarkSync.confirm=O NoScript descobriu uma configuração dos favoritos aparentemente salva em\n%S.\nVocê realmente quer sobrescrever suas configurações locais do NoScript com o conteúdo desse favorito?
+ABE.notify=Requisição %1$S filtrada por ABE:<%2$S> %3$S
+ABE.chooseEditor=Favor selecionar um editor de texto para ajuste de regras do ABE
+allowFrom=Permitir tudo de %S
+allowTempFrom=Temporariamente permitir tudo de %S
+ABE.syntaxError=Erro de sintaxe no conjunto de regras ABE!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+siteInfo.confirm=Você está prestes a pedir informações sobre o site "%1$S"\nao fazer uma consulta ao %2$S.\nDeseja continuar?
+siteInfo.tooltip=Click com o botão do meio, ou Shift click para informações do site…
+ef.activate=Filtrar %S
+ef.options=Opções do %S…
+ef.newName=Digite o nome do novo filtro:
+ef.locateExe=Selecione o arquivo executável para o filtro %S
+disable=Desativar %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/pt-PT/noscript/about.properties b/extensions/noscript/chrome/locale/pt-PT/noscript/about.properties
new file mode 100644
index 0000000..fff2536
--- /dev/null
+++ b/extensions/noscript/chrome/locale/pt-PT/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Protecção extra para o seu Firefox...
+aboutTitle=Sobre %S
+extensionContributors=Contribuintes:
+extensionContributors.tip=A quem deve agradecer por esta extensão
+extensionCreatorLabel=Criador:
+changelog=Histórico
+changelog.tip=Mostrar histórico
+license=Licença
+license.tip=Ler a licença final do utilizador
+logo.tip=Visitar a página da extensão
+sponsor.tip=Visitar a página do patrocinador
+informaction.tip=Visitar a página da InformAction
+extensionHomepage.tip=Visitar a página da extensão
+extensionCreator.tip=Visitar a página do autor
+version=Versão %S
diff --git a/extensions/noscript/chrome/locale/pt-PT/noscript/noscript.dtd b/extensions/noscript/chrome/locale/pt-PT/noscript/noscript.dtd
new file mode 100644
index 0000000..a03e0a1
--- /dev/null
+++ b/extensions/noscript/chrome/locale/pt-PT/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opções">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Opções do NoScript">
+<!ENTITY noscriptAbout "Sobre o NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Pode especificar os sítios que podem executar scripts. Escreva o endereço ou o domínio (ex: &quot;http://www.sitio.com&quot; ou &quot;sitio.com&quot;) do sítio que deseja permitir e depois pressione em Permitir.">
+<!ENTITY noscriptWebAddress "Endereço:">
+<!ENTITY noscriptAllow "Permitir">
+<!ENTITY noscriptAllow.accesskey "P">
+<!ENTITY noscriptForbid "Não permitir">
+<!ENTITY noscriptForbid.accesskey "N">
+<!ENTITY noscriptTrust "Marcar como de confiança">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Marcar como não sendo de confiança">
+<!ENTITY noscriptUntrust.accesskey "o">
+<!ENTITY noscriptRemoveSelected "Remover sítios seleccionados">
+<!ENTITY noscriptGloballyEnabled "Scripts permitidos na globalidade (perigoso)">
+<!ENTITY noscriptAutoReload "Actualizar automaticamente a página actual quando as permissões são alteradas.">
+<!ENTITY noscriptGeneral "Geral">
+<!ENTITY noscriptAppearance "Aparência">
+<!ENTITY noscriptShow "Mostrar...">
+<!ENTITY noscriptCtxMenu "Menu de contexto">
+<!ENTITY noscriptStatusIcon "Ãcone da Barra de Estado">
+<!ENTITY noscriptFullAddr "Endereço completo (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Domínios completos (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Base domínios de 2º nível (noscript.net)">
+<!ENTITY noscriptTempCmd "Permitir temporariamente [...]">
+<!ENTITY noscriptSound "Alerta de áudio quando os scripts são bloqueados">
+<!ENTITY noscriptImport "Importar">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exportar">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Mostrar mensagens sobre os scripts bloqueados">
+<!ENTITY noscriptNotify.bottom "Mostrar mensagens na zona inferior">
+<!ENTITY noscriptSound.choose "Procurar">
+<!ENTITY noscriptSound.choose.accesskey "P">
+<!ENTITY noscriptSound.play "Tocar">
+<!ENTITY noscriptSound.play.accesskey "T">
+<!ENTITY noscriptSound.reset "Predefinição">
+<!ENTITY noscriptSound.reset.accesskey "r">
+<!ENTITY noscriptAdvanced "Avançado">
+<!ENTITY noscriptAdditionalPermissions "Permissões adicionais para sítios de confiança">
+<!ENTITY noscriptAllowClipboard "Permitir copiar e colar texto com formatações de texto a partir da área de transferência">
+<!ENTITY noscriptAdditionalRestrictions "Restrições adicionais para sítios sem confiança">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Aplicar estas restrições também nos sítios de confiança">
+<!ENTITY noscriptForbidJava "Proibir Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Proibir XSLT">
+<!ENTITY noscriptForbidSilverlight "Proibir Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Proibir &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Proibir &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Proibir @font-face">
+<!ENTITY noscriptForbidWebGL "Proibir WebGL">
+<!ENTITY noscriptForbidMedia "Proibir &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Proibir Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Proibir outros plugins">
+<!ENTITY noscriptReloadWarn "Estas opções terão efeito em páginas novas ou (manualmente) actualizadas.">
+<!ENTITY noscriptConfirmUnblock "Pedir confirmação antes de desbloquear temporariamente um objecto">
+<!ENTITY noscriptStatusLabel "Informações na barra de estado">
+<!ENTITY noscriptForbidBookmarklets "Proibir bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Mostrar ícone de substituição">
+<!ENTITY noscriptTruncateTitle "Quebrar títulos dos documentos">
+<!ENTITY noscriptFixLinks "Tentar corrigir ligações de JavaScript">
+<!ENTITY noscriptAllowBookmarks "Permitir todos os sítios que se encontrem nos Marcadores">
+<!ENTITY noscriptAllowViaBookmarks "Permitir páginas abertas através dos Marcadores">
+<!ENTITY noscriptAllowPing "Permitir &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Permitir ligações locais">
+<!ENTITY noscriptForbidPing "Proibir &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Proibir redireccionamentos META dentro de elementos &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "Mostrar mensagem sobre redireccionamentos META bloqueados">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "Lista Branca">
+<!ENTITY noscriptPermissions "Permissões">
+<!ENTITY noscriptRefresh "Actualizar">
+<!ENTITY noscriptNotifications "Notificações">
+<!ENTITY noscriptToolbarToggle "Clique esquerdo na barra de ferramentas do NoScript altera as permissões para o sítio principal actual">
+<!ENTITY noscriptTrusted "De confiança">
+<!ENTITY noscriptUntrusted "Não é de confiança">
+<!ENTITY noscriptUnknown "Desconhecido">
+<!ENTITY noscriptAdd "Adicionar">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Fechar">
+<!ENTITY noscriptSiteManager "Gestor de Sítios">
+<!ENTITY noscriptSecurityManager "Gestor de Segurança">
+<!ENTITY noscriptPolicies "Políticas">
+<!ENTITY noscriptDefaultPolicies "Políticas Pré-definidas">
+<!ENTITY noscriptSitePolicies "Políticas Especificas do Sítio">
+<!ENTITY noscriptNselNever "Ocultar elementos &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Mostrar o elemento &lt;NOSCRIPT&gt; que seguiu um script bloqueado &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Permitir temporariamente todos os sites de alto nível por pré-definição">
+<!ENTITY noscriptDescription "Protecção extra para o seu Firefox: O NoScript permite o uso de JavaScripts, Java (e outros plugins) somente para os domínios de confiança que você seleccionar (como por exemplo no sítio do seu internet banking). Esse bloqueio é baseado numa lista branca que previne a exploração de vulnerabilidades de segurança (conhecidas e até mesmo as desconhecidas!) sem perda de desempenho... Os especialistas concordam: o Firefox é realmente mais seguro com o NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Bloquear scanners baseados em CSS">
+<!ENTITY noscriptOptFilterXGet "Desinfectar requerimentos suspeitos via sítio">
+<!ENTITY noscriptOptFilterXPost "Alterar requerimentos perigosos via sítio em requerimentos GET sem dados">
+<!ENTITY noscriptShowConsole "Mostrar Consola...">
+<!ENTITY noscriptShowConsole.accesskey "M">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "Perguntas e respostas do XSS ...">
+<!ENTITY noscriptXssFaq.accesskey "P">
+<!ENTITY noscriptUnsafeReload "Recarregamento Inseguro">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Protecção Anti-XSS através das excepções">
+<!ENTITY noscriptXssExceptions.description "Os destinos que combinarem essas expressões NÃO serão protegidos contra XSS">
+<!ENTITY noscriptMatchSample "Exemplo ilustrativo da combinação:">
+<!ENTITY noscriptReset "Restaurar">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Restaurar pré-definições">
+<!ENTITY noscriptResetDef.accesskey "p">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Anular Permissões Temporárias">
+<!ENTITY noscriptRevokeTemp.accesskey "A">
+<!ENTITY noscriptNoUntrustedPlaceholder "Nenhum placeholder para objectos provenientes de sítios marcados como de confiança">
+<!ENTITY noscriptCollapseBlockedObjects "Colapsar objectos bloqueados">
+<!ENTITY noscriptExceptions "Excepções...">
+<!ENTITY noscriptBlockedObjects "Objectos bloqueados">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Bloquear todos os objectos provenientes de um site marcado como não confiável">
+<!ENTITY noscriptTempAllowPage "Autorizar tudo temporariamente nesta página">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Permitir tudo nesta página">
+<!ENTITY noscriptAllowPage.accesskey "e">
+<!ENTITY noscriptTempToPerm "Tornar as permissões da página permanentes">
+<!ENTITY noscriptTempToPerm.accesskey "n">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Comportamento">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Proibir conteúdo web activo a não ser que venha de uma ligação segura (HTTPS):">
+<!ENTITY noscriptHttps.never "Nunca">
+<!ENTITY noscriptHttps.proxy "Ao usar um proxy (recomendado com Tor)">
+<!ENTITY noscriptHttps.always "Sempre">
+<!ENTITY noscriptHttpsForced "Forçar o uso de ligações seguras (HTTPS)dos seguintes sítios:">
+<!ENTITY noscriptHttpsForcedExceptions "Nunca forçar o uso de ligações seguras (HTTPS)dos seguintes sítios:">
+<!ENTITY noscriptSecureCookies "Activar a gestão automática segura de cookies">
+<!ENTITY noscriptSecureCookiesForced "Forçar cifra para todos os cookies aplicada sobre HTTPS pelos seguintes sítios:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignorar cookies não seguros aplicada sobre HTTPS pelos seguintes sítios:">
+<!ENTITY noscriptClearClickTitle "Limpar aviso com clique">
+<!ENTITY noscriptClearClickHeader "Potencial Clickjacking / Tentativa de mudar UI">
+<!ENTITY noscriptClearClickDescription "O NoScript interceptou uma interacção do rato ou do teclado com um elemento parcialmene oculto. Clique na imagem acima para mudar entre a versão limpa e a obstruída">
+<!ENTITY noscriptClearClickOpt "Limpar aviso com clique nas páginas...">
+<!ENTITY noscriptClearClickReport "Relatório">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "ID do relatório:">
+<!ENTITY noscriptTrustedPagesAdj "de confiança">
+<!ENTITY noscriptUntrustedPagesAdj "não é de confiança">
+<!ENTITY noscriptKeepLocked "Manter este elemento fechado (recomendado)">
+<!ENTITY noscriptEmbeddings "Objectos embebidos">
+<!ENTITY noscriptPrev "Anterior">
+<!ENTITY noscriptNext "Seguinte">
+<!ENTITY noscriptFrameOptErr.title "Este conteúdo não pode ser apresentado numa frame">
+<!ENTITY noscriptFrameOptErr.desc "Para o proteger, o editor deste conteúdo não permite que seja apresentado numa frame.">
+<!ENTITY noscriptFrameOptErr.link "Clique aqui para abrir este conteúdo numa nova janela">
+<!ENTITY noscriptBookmarkSync "Configuração de backup do NoScript num marcador para fácil sincronização">
+<!ENTITY noscriptShowReleaseNotes "Mostrar as notas de lançamento nas actualizações">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Conjunto de regras:">
+<!ENTITY ABE.enabled.label "Activar ABE(Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Permitir que os sítios puxem os seus próprios conjuntos de regras">
+<!ENTITY ABE.edit.label "Editar...">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Activar">
+<!ENTITY ABE.enable.accesskey "c">
+<!ENTITY ABE.disable.label "Desactivar">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Actualizar">
+<!ENTITY ABE.refresh.accesskey "z">
+<!ENTITY noscriptUninstall "Desinstalar">
+<!ENTITY noscriptRecentBlocked "Sítios bloqueados recentemente">
+<!ENTITY noscriptExternalFilters "Filtros Externos">
+<!ENTITY noscriptEF.enable "Activar filtros externos">
+<!ENTITY noscriptEF.add "Novo filtro ...">
+<!ENTITY noscriptEF.executable "Ficheiro executável:">
+<!ENTITY noscriptEF.browse "Navegar ...">
+<!ENTITY noscriptEF.contentType "Tipo de conteúdo (MIME) a ser filtrado (correspondência exacta ou expressão regular):">
+<!ENTITY noscriptEF.exceptions "Não filtrar objectos provenientes destes sítios:">
+<!ENTITY noscriptEF.remove "Remover">
+<!ENTITY noscriptPreset "Nível de Segurança">
+<!ENTITY noscriptPreset.off "Desligado (tem a certeza?)">
+<!ENTITY noscriptPreset.low "Sensível (Lista negra + Segurança Web)">
+<!ENTITY noscriptPreset.medium "Classic (Lista branca + Segurança Web)">
+<!ENTITY noscriptPreset.high "Fortaleza (bloqueio completo)">
+<!ENTITY noscript.hoverUI "Abra o menu de permissões quando o rato passa sobre o ícone do NoScript">
+<!ENTITY noscriptDonate "Doar">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/pt-PT/noscript/noscript.properties b/extensions/noscript/chrome/locale/pt-PT/noscript/noscript.properties
new file mode 100644
index 0000000..07a920b
--- /dev/null
+++ b/extensions/noscript/chrome/locale/pt-PT/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Permitir JavaScript Globalmente (perigoso)
+forbidGlobal=Proibir JavaScript Globalmente (recomendado)
+allowLocal=Permitir %S
+allowTemp=Permitir temporariamente %S
+forbidLocal=Proibir %S
+allowed.glb=Perigo! Scripts permitidos globalmente
+allowed.yes=Scripts permitidos de momento
+allowed.prt=Scripts permitidos parcialmente
+allowed.no=Scripts proibidos de momento
+global.warning.title=Aviso!
+global.warning.text=Os Scripts serão globalmente permitidos (em qualquer sítio).\nEsta é uma acção potencialmente perigosa.\nDeseja mesmo continuar?
+audio.samples=Ficheiros Ãudio [wav]
+confirm=Tem a certeza?
+alwaysAsk=Pedir sempre confirmação
+notifyHide=Ocultar após %S segundos
+trust=Confiar %S
+distrust=Marcar %S como Não Confiável
+untrustedOrigin=uma origem não confiável
+xss.notify.generic=O NoScript filtrou uma tentativa de uso de script via sítio (XSS) vinda de %S. Detalhes técnicos foram gravados na consola.
+xss.notify.showConsole=Mostrar consola...
+xss.notify.showConsole.accessKey=s
+xss.reason.filterXGet=Desinfectou um requerimento suspeito. O URL original [%1$S] requerido por [%2$S]. URL desinfectada: [%3$S].)
+xss.reason.filterXGetRef=Desinfectou um requerimento de referência suspeita. A URL [%1$S] requerida por [%2$S]. Referência desinfectada: [%3$S].)
+xss.reason.filterXPost=Carregamento suspeito desinfectado de [%1$S] para [%2$S]: transformado em um requerimento do tipo apenas transferência.
+unsafeReload.warning=Recarregamento INSEGURO e suspeito\n\n%1$S [%2$S}\n\nDE [%3$S]\n\nO NoScript NÃO irá proteger este pedido!\n
+metaRefresh.notify=O NoScript bloqueou um redireccionamento <META> dentro de um elemento do <NOSCRIPT>: %S em %S segundos.
+metaRefresh.notify.follow=Seguir redireccionamento
+metaRefresh.notify.follow.accessKey=S
+notify.options=Opções
+notify.options.accessKey=O
+reset.title=Reiniciar configurações do NoScript
+reset.warning=TODAS as configurações do NoScript e as permissões de sítios serão restauradas imediatamente para os seus valores pré-definidos.\n Esta acção não poderá ser revertida. \nDeseja continuar?
+bookmarkSync.title=Marcador de configuração do NoScript
+bookmarkSync.message=Este marcador Não é para ser aberto, mas sim ser sincronizado usando um serviço tipo Weave ou a extensão XMarks.
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark\'s content?
+ABE.notify=Pedido %1$S filtrado por ABE: <%2$S> %3$S
+ABE.chooseEditor=Escolha um editor de texto para os conjuntos de regras ABE
+ABE.syntaxError=Erro de sintaxe no conjunto de regras ABE!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Permitir tudo de %S
+allowTempFrom=Permitir tudo de %S temporariamente
+siteInfo.confirm=Está prestes a pedir informações sobre o sítio \"%1$S\"\nao enviar um pedido para %2$S.\nDeseja continuar?
+siteInfo.tooltip=Clique-central ou Shift+clique para obter informações do sítio...
+ef.activate=Filtro %S
+ef.options=%S opções...
+ef.newName=Escreva o nome do novo filtro:
+ef.locateExe=Seleccione o ficheiro executável para o filtro %S
+disable=Desactivar %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/ro/noscript/about.properties b/extensions/noscript/chrome/locale/ro/noscript/about.properties
new file mode 100644
index 0000000..bcbe68b
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ro/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Ca protecție suplimentară pentru Firefox, NoScript nu permite executarea scripturilor JavaScript, Java, sau ale altor plugin-uri decât pentru domeniile de încredere alese de Dvs. Acest sistem de blocare preventivă a scripturilor împiedică exploatarea vulnerabilităților de securitate (cunoscute sau chiar necunoscute) fără pierdere de performanță... Experții vor fi de acord: Firefox este mult mai sigur cu NoScript :)
+aboutTitle=Despre %S
+extensionContributors=Colaboratori:
+extensionContributors.tip=Cei cărora ar trebui să le mulțumiți pentru această extensie
+extensionCreatorLabel=Autor:
+changelog=Jurnal modificări
+changelog.tip=Afișează jurnalul de modificări
+license=Licență
+license.tip=Afișează Licența pentru utilizatorul final
+logo.tip=Deschide pagina gazdă a suplimentului
+sponsor.tip=Deschide pagina gazdă a sponsorului
+informaction.tip=Deschide pagina gazdă InformAction
+extensionHomepage.tip=Deschide pagina gazdă a suplimentului
+extensionCreator.tip=Deschide pagina gazdă a autorului
+version=Versiunea %S
diff --git a/extensions/noscript/chrome/locale/ro/noscript/noscript.dtd b/extensions/noscript/chrome/locale/ro/noscript/noscript.dtd
new file mode 100644
index 0000000..fda381a
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ro/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Opțiuni...">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "Opțiuni NoScript">
+<!ENTITY noscriptAbout "Despre NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Puteți specifica saiturile cărora li se permite să execute scripturi. Scrieți adresa sau domeniul paginii (exemplu: „http://www.sait.ro“ sau „sait.ro“), apoi apăsați pe butonul „Permite“.">
+<!ENTITY noscriptWebAddress "Adresă sait:">
+<!ENTITY noscriptAllow "Permite">
+<!ENTITY noscriptAllow.accesskey "P">
+<!ENTITY noscriptForbid "Interzice">
+<!ENTITY noscriptForbid.accesskey "I">
+<!ENTITY noscriptTrust "Marchează ca „De încredere“">
+<!ENTITY noscriptTrust.accesskey "d">
+<!ENTITY noscriptUntrust "Marchează ca „De neîncredere“">
+<!ENTITY noscriptUntrust.accesskey "n">
+<!ENTITY noscriptRemoveSelected "Elimină saiturile selectare">
+<!ENTITY noscriptGloballyEnabled "Scripturi permise global (riscant)">
+<!ENTITY noscriptAutoReload "Reîncarcă automat paginile atunci când se schimbă permisiunile">
+<!ENTITY noscriptGeneral "General">
+<!ENTITY noscriptAppearance "Aspect">
+<!ENTITY noscriptShow "Elemente afișate">
+<!ENTITY noscriptCtxMenu "Opțiune în meniul contextual">
+<!ENTITY noscriptStatusIcon "Pictogramă pe bara de stare">
+<!ENTITY noscriptFullAddr "Adrese complete (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Domenii complete (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Domenii de nivel 2 (noscript.net)">
+<!ENTITY noscriptTempCmd "Permite temporar [...]">
+<!ENTITY noscriptSound "Avertizează sonor când scripturile sunt blocate">
+<!ENTITY noscriptImport "Importă">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exportă">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Afișează un mesaj privind scripturile blocate">
+<!ENTITY noscriptNotify.bottom "Afișează mesajul în partea de jos a ferestrei">
+<!ENTITY noscriptSound.choose "Alege sunetul...">
+<!ENTITY noscriptSound.choose.accesskey "A">
+<!ENTITY noscriptSound.play "Redă">
+<!ENTITY noscriptSound.play.accesskey "R">
+<!ENTITY noscriptSound.reset "Inițializează">
+<!ENTITY noscriptSound.reset.accesskey "I">
+<!ENTITY noscriptAdvanced "Complex">
+<!ENTITY noscriptAdditionalPermissions "Permisiuni suplimentare pentru saiturile de încredere">
+<!ENTITY noscriptAllowClipboard "Permite copierea și lipirea textului îmbogățit din memoria tampon a sistemului">
+<!ENTITY noscriptAdditionalRestrictions "Restricții suplimentare pentru saiturile de neîncredere">
+<!ENTITY noscriptPlugins "Plugin-uri">
+<!ENTITY noscriptContentBlocker "Aplică aceste restricții și pentru saiturile de încredere">
+<!ENTITY noscriptForbidJava "Interzice Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "Interzice XSLT (Extensible Stylesheet Language Transformations)">
+<!ENTITY noscriptForbidSilverlight "Interzice Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Interzice &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Interzice &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Interzice @font-face">
+<!ENTITY noscriptForbidWebGL "Interzice WebGL">
+<!ENTITY noscriptForbidMedia "Interzice &lt;AUDIO&gt;/&lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Interzice Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Interzice alte plugin-uri">
+<!ENTITY noscriptReloadWarn "Aceste opțiuni vor fi efective în paginile nou deschise sau în cele reîncărcate (manual)">
+<!ENTITY noscriptConfirmUnblock "Cere confirmare înainte de a debloca un obiect">
+<!ENTITY noscriptStatusLabel "Etichetă pe bara de stare">
+<!ENTITY noscriptForbidBookmarklets "Interzice scripturile din semnele de carte">
+<!ENTITY noscriptShowPlaceholder "Afișează amplasamentul obiectului blocat">
+<!ENTITY noscriptTruncateTitle "Trunchiază titlurile documentelor">
+<!ENTITY noscriptFixLinks "Încearcă repararea legăturilor JavaScript">
+<!ENTITY noscriptAllowBookmarks "Permite saiturile din semnele de carte">
+<!ENTITY noscriptAllowViaBookmarks "Permite toate saiturile deschise prin semnele de carte">
+<!ENTITY noscriptAllowPing "Permite &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Permite legăturile locale">
+<!ENTITY noscriptForbidPing "Interzice &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Interzice redirectările META din interiorul elementelor &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "r">
+<!ENTITY noscriptNotifyMeta "Afișează un mesaj despre redirectările META interzise">
+<!ENTITY noscriptNotifyMeta.accesskey "M">
+<!ENTITY noscriptWhitelist "Listă de adrese sigure">
+<!ENTITY noscriptPermissions "Permisiuni">
+<!ENTITY noscriptRefresh "Actualizează">
+<!ENTITY noscriptNotifications "Notificări">
+<!ENTITY noscriptToolbarToggle "Comută permisiunile pentru domeniul primar curent cu clic-stânga pe butonul din bara de unelte">
+<!ENTITY noscriptTrusted "Saituri „de încredere“">
+<!ENTITY noscriptUntrusted "Saituri „de neîncredere“">
+<!ENTITY noscriptUnknown "Saituri „necunoscute“">
+<!ENTITY noscriptAdd "Adaugă">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "ÃŽnchide">
+<!ENTITY noscriptSiteManager "Gestionar de saituri">
+<!ENTITY noscriptSecurityManager "Gestionar de securitate">
+<!ENTITY noscriptPolicies "Reguli">
+<!ENTITY noscriptDefaultPolicies "Reguli implicite">
+<!ENTITY noscriptSitePolicies "Reguli dependente de sait">
+<!ENTITY noscriptNselNever "Ascunde elementele &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Afișează elementele &lt;NOSCRIPT&gt; care urmează unui element &lt;SCRIPT&gt; blocat">
+<!ENTITY noscriptAutoAllowTopLevel "Permite temporar domeniile primare în mod implicit">
+<!ENTITY noscriptDescription "Ca protecție suplimentară pentru Firefox, NoScript nu permite executarea scripturilor JavaScript, Java, sau ale altor plugin-uri decât pentru domeniile de încredere alese de Dvs. Acest sistem de blocare preventivă a scripturilor împiedică exploatarea vulnerabilităților de securitate (cunoscute sau chiar necunoscute) fără pierdere de performanță... Experții vor fi de acord: Firefox este mult mai sigur cu NoScript :)">
+<!ENTITY noscriptOptBlockCssScanners "Blochează scanerele bazate pe CSS">
+<!ENTITY noscriptOptFilterXGet "Elimină solicitările suspecte între saituri">
+<!ENTITY noscriptOptFilterXPost "Transformă solicitările POST între saituri în solicitări GET fără date">
+<!ENTITY noscriptShowConsole "Afișează consola...">
+<!ENTITY noscriptShowConsole.accesskey "c">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "Informații XSS...">
+<!ENTITY noscriptXssFaq.accesskey "f">
+<!ENTITY noscriptUnsafeReload "Reîncărcare nesigură">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Excepții la protecția anti-XSS">
+<!ENTITY noscriptXssExceptions.description "Destinațiile care se potrivesc cu expresiile regulate din listă nu vor fi protejate împotriva atacurilor XSS.">
+<!ENTITY noscriptMatchSample "Exemplu de expresie regulată:">
+<!ENTITY noscriptReset "Inițializează">
+<!ENTITY noscriptReset.accesskey "I">
+<!ENTITY noscriptResetDef "Inițializează la valorile implicite">
+<!ENTITY noscriptResetDef.accesskey "v">
+<!ENTITY noscriptOptionsWidth "50em">
+<!ENTITY noscriptRevokeTemp "Revocă permisiunile temporare">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "Nu afișa amplasamentul obiectelor care provin din saituri marcate ca „De neîncredere“">
+<!ENTITY noscriptCollapseBlockedObjects "Restrânge spațiul obiectelor blocate">
+<!ENTITY noscriptExceptions "Excepții...">
+<!ENTITY noscriptBlockedObjects "Obiecte blocate">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Blochează orice obiect care provine dintr-un sait marcat ca „De neîncredere“">
+<!ENTITY noscriptTempAllowPage "Permite temporar tot din această pagină">
+<!ENTITY noscriptTempAllowPage.accesskey "t">
+<!ENTITY noscriptAllowPage "Permite tot din această pagină">
+<!ENTITY noscriptAllowPage.accesskey "P">
+<!ENTITY noscriptTempToPerm "Permanentizează permisiunile paginii">
+<!ENTITY noscriptTempToPerm.accesskey "e">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "Informații HTTPS...">
+<!ENTITY noscriptHttpsFaq.accesskey "I">
+<!ENTITY noscriptHttps.behavior "Comportament">
+<!ENTITY noscriptHttps.cookies "Module cookie">
+<!ENTITY noscriptHttps.description "Interzice conținutul web activ dacă nu provine dintr-o conexiune securizată (HTTPS):">
+<!ENTITY noscriptHttps.never "Niciodată">
+<!ENTITY noscriptHttps.proxy "Când se folosește un proxy (recomandat cu Tor)">
+<!ENTITY noscriptHttps.always "ÃŽntotdeauna">
+<!ENTITY noscriptHttpsForced "Forțează următoarele saituri să folosească conexiuni securizate (HTTPS):">
+<!ENTITY noscriptHttpsForcedExceptions "Nu forța niciodată conexiuni securizate (HTTPS) pentru următoarele saituri:">
+<!ENTITY noscriptSecureCookies "Activează gestionarea securizată automată a modulelor cookie">
+<!ENTITY noscriptSecureCookiesForced "Forțază criptarea tuturor modulelor cookie stabilite prin HTTPS pentru următoarele saituri:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignoră modulele cookie nesigure stabilite prin HTTPS pentru următoarele saituri:">
+<!ENTITY noscriptClearClickTitle "Avertisment ClearClick">
+<!ENTITY noscriptClearClickHeader "Clickjacking potențial / Încercare de recuperare UI!">
+<!ENTITY noscriptClearClickDescription "NoScript a interceptat o interacțiune a mausului sau tastaturii cu un element parțial ascuns. Faceți clic pe imaginea de mai jos pentru a comuta între versiunea ascunsă și cea vizibilă.">
+<!ENTITY noscriptClearClickOpt "Protecție ClearClick pentru paginile...">
+<!ENTITY noscriptClearClickReport "Raport">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "ID raport:">
+<!ENTITY noscriptTrustedPagesAdj "de încredere">
+<!ENTITY noscriptUntrustedPagesAdj "de neîncredere">
+<!ENTITY noscriptKeepLocked "Păstrează blocat acest element (recomandat)">
+<!ENTITY noscriptEmbeddings "Obiecte înglobate">
+<!ENTITY noscriptPrev "ÃŽnapoi">
+<!ENTITY noscriptNext "ÃŽnainte">
+<!ENTITY noscriptFrameOptErr.title "Conținut nepermis a fi afișat într-un cadru">
+<!ENTITY noscriptFrameOptErr.desc "Pentru a vă proteja securitatea, editorul acestui conținut nu permite ca acesta să fie afișat într-un cadru.">
+<!ENTITY noscriptFrameOptErr.link "Apăsați aici pentru a deschide acest conținut într-o fereastră nouă">
+<!ENTITY noscriptBookmarkSync "Arhivează configurația NoScript într-un semn de carte pentru o sincronizare facilă">
+<!ENTITY noscriptShowReleaseNotes "Afișează note privind versiunea la actualizări">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Serii de reguli:">
+<!ENTITY ABE.enabled.label "Activează ABE (Application Boundaries Enforcer - Gardian al limitelor aplicației)">
+<!ENTITY ABE.siteEnabled.label "Permite saiturilor să execute propriile serii de reguli">
+<!ENTITY ABE.edit.label "Editează...">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Activează">
+<!ENTITY ABE.enable.accesskey "A">
+<!ENTITY ABE.disable.label "Dezactivează">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Actualizează">
+<!ENTITY ABE.refresh.accesskey "t">
+<!ENTITY noscriptUninstall "Dezinstalează">
+<!ENTITY noscriptRecentBlocked "Saituri blocate recent">
+<!ENTITY noscriptExternalFilters "Filtre externe">
+<!ENTITY noscriptEF.enable "Activează filtrele externe">
+<!ENTITY noscriptEF.add "Filtru nou...">
+<!ENTITY noscriptEF.executable "Fișier executabil:">
+<!ENTITY noscriptEF.browse "Răsfoiește...">
+<!ENTITY noscriptEF.contentType "Tip de conținut (MIME) de filtrat (potrivire exactă sau expresie regulată):">
+<!ENTITY noscriptEF.exceptions "Nu filtra obiectele provenite de la următoarele saituri:">
+<!ENTITY noscriptEF.remove "Elimină">
+<!ENTITY noscriptPreset "Nivel de securitate">
+<!ENTITY noscriptPreset.off "Libertate (e o glumă??!)">
+<!ENTITY noscriptPreset.low "Fără grijă (listă neagră + securitate web)">
+<!ENTITY noscriptPreset.medium "Clasic (listă albă + securitate web)">
+<!ENTITY noscriptPreset.high "Fortăreață (protecție totală)">
+<!ENTITY noscript.hoverUI "Afișează meniul permisiunilor când mausul survolează pictograma NoScript">
+<!ENTITY noscriptDonate "Donați">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/ro/noscript/noscript.properties b/extensions/noscript/chrome/locale/ro/noscript/noscript.properties
new file mode 100644
index 0000000..ecf1a6c
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ro/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Permite scripturile global (riscant)
+forbidGlobal=Interzice scripturile global (recomandat)
+allowLocal=Permite scripturile de la %S
+allowTemp=Permite temporar scripturile de la %S
+forbidLocal=Interzice scripturile de la %S
+allowed.glb=Pericol! Scripturile sunt permise global
+allowed.yes=Scripturi permise în mod curent
+allowed.prt=Scripturi permise parțial
+allowed.no=Scripturi interzise
+global.warning.title=Atenție!
+global.warning.text=Scripturile vor fi permise global (pentru toate saiturile).\nAceastă operațiune poate fi periculoasă.\nSigur doriți să continuați?
+audio.samples=Fișiere audio
+confirm=Confirmați?
+alwaysAsk=Cere întotdeauna confirmare
+notifyHide=Ascunde mesajul după %S secunde
+trust=Marchează %S ca „De încredere“
+distrust=Marchează %S ca „De neîncredere“
+untrustedOrigin=o origine dubioasă
+xss.notify.generic=NoScript a filtrat o tentativă de solicitare de scripturi între saituri (XSS - Cross-site scripting) provenind de la %S. Detaliile tehnice au fost înregistrate în consolă.
+xss.notify.showConsole=Afișează consola...
+xss.notify.showConsole.accessKey=A
+xss.reason.filterXGet=Cererea suspectă a fost curățată. Adresa originală [%1$S] a fost solicitată de [%2$S]. Adresa curățată este [%3$S].
+xss.reason.filterXGetRef=Cererea de referință suspectă a fost curățată. Adresa [%1$S] a fost solicitată de [%2$S]. Referința curățată este [%3$S].
+xss.reason.filterXPost=Încărcarea suspectă către [%1$S] solicitată de [%2$S] a fost curățată. Comanda a fost transformată într-o simplă solicitare de descărcare GET.
+unsafeReload.warning=Reîncărcarea NESIGURĂ a cererii\n\n%1$S [%2$S]\n\nde la [%3$S]\n\nnu va fi protejată de către NoScript!\n
+metaRefresh.notify=NoScript a blocat o redirecționare <META> dintr-un element <NOSCRIPT>: %S în %S secunde.
+metaRefresh.notify.follow=Urmează redirecționarea
+metaRefresh.notify.follow.accessKey=U
+notify.options=Opțiuni
+notify.options.accessKey=O
+reset.title=Inițializează NoScript
+reset.warning=TOATE opțiunile NoScript și permisiunile saiturilor vor fi inițializate imediat la valorile lor implicite.\nAceastă acțiune nu poate fi anulată.\nDoriți să continuați?
+bookmarkSync.title=Semn de carte de configurare NoScript
+bookmarkSync.message=Acest semn de carte nu este menit să fie deschis ci să fie sincronizat cu servicii cum ar fi suplimentele Firefox Sync sau Xmarks.
+bookmarkSync.confirm=NoScript a gasit un semn de carte de configurare salvat evident pe\n%S.\nSigur doriți să înlocuiți configurația Dvs. locală NoScript cu cea conținută la acest semn de carte?
+ABE.notify=Cererea %1$S filtrată de ABE: <%2$S> %3$S
+ABE.chooseEditor=Alegeți un editor de text pentru regulile ABE
+ABE.syntaxError=Eroare de sintaxă în setul de reguri ABE!
+ABE.wanIpAsLocal=IP WAN (%S) ∈ LOCAL
+allowFrom=Permite tot de la %S
+allowTempFrom=Permite temporar tot de la %S
+siteInfo.confirm=Sunteți pe cale de a solicita informații despre saitul „%1$S“\nprin lansarea unei cereri la %2$S.\nDoriți să continuați?
+siteInfo.tooltip=Clic-mijloc sau Shift+clic pentru informații despre sait...
+ef.activate=Filtrează %S
+ef.options=Opțiuni %S...
+ef.newName=Denumire filtru:
+ef.locateExe=Selectare fișier executabil pentru filtrul %S
+disable=Dezactivează %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/ru-RU/noscript/about.properties b/extensions/noscript/chrome/locale/ru-RU/noscript/about.properties
new file mode 100644
index 0000000..07debd4
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ru-RU/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð·Ð°Ñ‰Ð¸Ñ‚Ð° Ð´Ð»Ñ Firefox: NoScript позволÑет разрешать JavaScript, Java (и другие плагины) только Ð´Ð»Ñ Ð´Ð¾Ð²ÐµÑ€ÐµÐ½Ð½Ñ‹Ñ… доменов, выбранных вами (например: Ñайт банковÑкого обÑлуживаниÑ). Белый ÑпиÑок, оÑнованный на принципе упреждающего блокированиÑ, позволÑет предотвратить иÑпользование уÑзвимоÑтей (извеÑтных и ещё не извеÑтных!) без потери функциональноÑти… ЭкÑперты ÑоглашаютÑÑ: Firefox дейÑтвительно безопаÑнее Ñ NoScript :-)
+aboutTitle=О раÑширении %S
+extensionContributors=УчаÑтники:
+extensionContributors.tip=Люди, которых можно поблагодарить за помощь
+extensionCreatorLabel=Ðвтор:
+changelog=ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ð²ÐµÑ€Ñий
+changelog.tip=ПроÑмотреть иÑторию верÑий NoScript
+license=Лицензионное Ñоглашение
+license.tip=Лицензионное Ñоглашение конечного пользователÑ
+logo.tip=Открыть домашнюю Ñтраницу раÑширениÑ
+sponsor.tip=Открыть домашнюю Ñтраницу ÑпонÑора
+informaction.tip=Открыть домашнюю Ñтраницу InformAction
+extensionHomepage.tip=Открыть домашнюю Ñтраницу раÑширениÑ
+extensionCreator.tip=Открыть домашнюю Ñтраницу автора
+version=ВерÑÐ¸Ñ %S
diff --git a/extensions/noscript/chrome/locale/ru-RU/noscript/noscript.dtd b/extensions/noscript/chrome/locale/ru-RU/noscript/noscript.dtd
new file mode 100644
index 0000000..8cb39c4
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ru-RU/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "ÐаÑтройки…">
+<!ENTITY noscriptOptions.accesskey "а">
+<!ENTITY noscriptOptionsLong "ÐаÑтройки NoScript">
+<!ENTITY noscriptAbout "О раÑширении">
+<!ENTITY noscriptPermissionsText "Ð’Ñ‹ можете указать, каким веб-Ñайтам разрешено выполнение Ñкриптов. Введите Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ домен (например: «http://www.site.com» или «site.com») Ñайта, который хотите разрешить, затем нажмите кнопку «Разрешить».">
+<!ENTITY noscriptWebAddress "ÐÐ´Ñ€ÐµÑ Ð²ÐµÐ±-Ñайта:">
+<!ENTITY noscriptAllow "Разрешить">
+<!ENTITY noscriptAllow.accesskey "е">
+<!ENTITY noscriptForbid "Запретить">
+<!ENTITY noscriptForbid.accesskey "ь">
+<!ENTITY noscriptTrust "Отметить как Доверенный">
+<!ENTITY noscriptTrust.accesskey "о">
+<!ENTITY noscriptUntrust "Отметить как Ðедоверенный">
+<!ENTITY noscriptUntrust.accesskey "в">
+<!ENTITY noscriptRemoveSelected "Удалить выбранные Ñайты">
+<!ENTITY noscriptGloballyEnabled "Глобальное разрешение Ñкриптов (опаÑно)">
+<!ENTITY noscriptAutoReload "ÐвтоматичеÑки перезагружать завиÑимые Ñтраницы при изменении разрешений">
+<!ENTITY noscriptGeneral "ОÑновные">
+<!ENTITY noscriptAppearance "Внешний вид">
+<!ENTITY noscriptShow "Отображать Ñледующие Ñлементы NoScript…">
+<!ENTITY noscriptCtxMenu "Пункт в контекÑтном меню">
+<!ENTITY noscriptStatusIcon "Значок в Ñтроке ÑоÑтоÑниÑ">
+<!ENTITY noscriptFullAddr "Полные адреÑа (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Полные домены (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Базовые домены 2-го ÑƒÑ€Ð¾Ð²Ð½Ñ (noscript.net)">
+<!ENTITY noscriptTempCmd "Временно разрешить […]">
+<!ENTITY noscriptSound "Звуковое оповещение при блокировке Ñкриптов">
+<!ENTITY noscriptImport "Импорт">
+<!ENTITY noscriptImport.accesskey "м">
+<!ENTITY noscriptExport "ЭкÑпорт">
+<!ENTITY noscriptExport.accesskey "к">
+<!ENTITY noscriptNotify "Отображать ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾ заблокированных Ñкриптах">
+<!ENTITY noscriptNotify.bottom "РаÑполагать ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð²Ð½Ð¸Ð·Ñƒ окна">
+<!ENTITY noscriptSound.choose "Обзор">
+<!ENTITY noscriptSound.choose.accesskey "о">
+<!ENTITY noscriptSound.play "ПроÑлушать">
+<!ENTITY noscriptSound.play.accesskey "а">
+<!ENTITY noscriptSound.reset "СброÑ">
+<!ENTITY noscriptSound.reset.accesskey "б">
+<!ENTITY noscriptAdvanced "Дополнительно">
+<!ENTITY noscriptAdditionalPermissions "Дополнительные Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð´Ð¾Ð²ÐµÑ€ÐµÐ½Ð½Ñ‹Ñ… Ñайтов">
+<!ENTITY noscriptAllowClipboard "РаÑширенные копирование и вÑтавка из внешнего буфера обмена">
+<!ENTITY noscriptAdditionalRestrictions "Дополнительные Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð½ÐµÐ´Ð¾Ð²ÐµÑ€ÐµÐ½Ð½Ñ‹Ñ… Ñайтов">
+<!ENTITY noscriptPlugins "Плагины">
+<!ENTITY noscriptContentBlocker "ПрименÑÑ‚ÑŒ Ñти Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¸ Ð´Ð»Ñ Ð´Ð¾Ð²ÐµÑ€ÐµÐ½Ð½Ñ‹Ñ… Ñайтов">
+<!ENTITY noscriptForbidJava "Запретить Java™">
+<!ENTITY noscriptForbidXSLT "Запретить XSLT">
+<!ENTITY noscriptForbidSilverlight "Запретить Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Запретить &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Запретить &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Запретить @font-face">
+<!ENTITY noscriptForbidWebGL "Запретить WebGL">
+<!ENTITY noscriptForbidMedia "Запретить &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Запретить Macromedia® Flash®">
+<!ENTITY noscriptForbidPlugins "Запретить другие плагины">
+<!ENTITY noscriptReloadWarn "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñтих параметров вÑтупают в Ñилу на новых или перезагруженных (вручную) Ñтраницах">
+<!ENTITY noscriptConfirmUnblock "Подтверждать временную разблокировку объекта">
+<!ENTITY noscriptStatusLabel "Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð² Ñтроке ÑоÑтоÑниÑ">
+<!ENTITY noscriptForbidBookmarklets "Запретить иÑпользование Bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Заполнитель вмеÑто заблокированных объектов">
+<!ENTITY noscriptTruncateTitle "ОтÑекать Ñлишком длинные заголовки веб-Ñайтов">
+<!ENTITY noscriptFixLinks "ПытатьÑÑ Ð¸Ñправить JavaScript-ÑÑылки">
+<!ENTITY noscriptAllowBookmarks "Разрешать Ñайты, открываемые через закладки">
+<!ENTITY noscriptAllowViaBookmarks "Разрешать Ñайты, открываемые через закладки">
+<!ENTITY noscriptAllowPing "Разрешить иÑпользование &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Разрешить локальные ÑÑылки">
+<!ENTITY noscriptForbidPing "Запретить иÑпользование &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Запретить META Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ Ñлементов &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "а">
+<!ENTITY noscriptNotifyMeta "Показывать ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾ заблокированных META перенаправлениÑÑ…">
+<!ENTITY noscriptNotifyMeta.accesskey "Ñ‹">
+<!ENTITY noscriptWhitelist "Белый ÑпиÑок">
+<!ENTITY noscriptPermissions "РазрешениÑ">
+<!ENTITY noscriptRefresh "Обновить">
+<!ENTITY noscriptNotifications "УведомлениÑ">
+<!ENTITY noscriptToolbarToggle "Ðажатием на значок переключать разрешение документа верхнего ÑƒÑ€Ð¾Ð²Ð½Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾Ð¹ вкладки">
+<!ENTITY noscriptTrusted "Доверенные">
+<!ENTITY noscriptUntrusted "Ðедоверенные">
+<!ENTITY noscriptUnknown "ÐеизвеÑтный">
+<!ENTITY noscriptAdd "Добавить">
+<!ENTITY noscriptAdd.accesskey "о">
+<!ENTITY noscriptClose "Закрыть">
+<!ENTITY noscriptSiteManager "Менеджер Ñайтов">
+<!ENTITY noscriptSecurityManager "Управление безопаÑноÑтью">
+<!ENTITY noscriptPolicies "Политики">
+<!ENTITY noscriptDefaultPolicies "Политики по умолчанию">
+<!ENTITY noscriptSitePolicies "Специальные политики Ð´Ð»Ñ Ñайтов">
+<!ENTITY noscriptNselNever "Скрывать Ñлементы &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Показывать Ñлемент &lt;NOSCRIPT&gt;, который Ñледует за заблокированным &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Временно разрешать документы верхнего ÑƒÑ€Ð¾Ð²Ð½Ñ Ð¿Ð¾ умолчанию">
+<!ENTITY noscriptDescription "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð·Ð°Ñ‰Ð¸Ñ‚Ð° Ð´Ð»Ñ Firefox: NoScript позволÑет разрешать JavaScript, Java (и другие плагины) только Ð´Ð»Ñ Ð´Ð¾Ð²ÐµÑ€ÐµÐ½Ð½Ñ‹Ñ… доменов, выбранных вами (например: Ñайт банковÑкого обÑлуживаниÑ). Белый ÑпиÑок, оÑнованный на принципе упреждающего блокированиÑ, позволÑет предотвратить иÑпользование уÑзвимоÑтей (извеÑтных и ещё не извеÑтных!) без потери функциональноÑти… ЭкÑперты ÑоглашаютÑÑ: Firefox дейÑтвительно безопаÑнее Ñ NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Блокировать CSS-Ñканеры">
+<!ENTITY noscriptOptFilterXGet "Фильтровать подозрительные межÑайтовые запроÑÑ‹">
+<!ENTITY noscriptOptFilterXPost "ЗаменÑÑ‚ÑŒ межÑайтовые POST-запроÑÑ‹ на GET-запроÑÑ‹ без данных">
+<!ENTITY noscriptShowConsole "Открыть конÑоль…">
+<!ENTITY noscriptShowConsole.accesskey "о">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "Справка по XSS (межÑайтовому Ñкриптингу)">
+<!ENTITY noscriptXssFaq.accesskey "а">
+<!ENTITY noscriptUnsafeReload "ÐебезопаÑÐ½Ð°Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°">
+<!ENTITY noscriptUnsafeReload.accesskey "е">
+<!ENTITY noscriptXssExceptions "ИÑÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð°Ð½Ñ‚Ð¸-XSS защиты">
+<!ENTITY noscriptXssExceptions.description "Целевые Ñтраницы, ÑоответÑтвующие Ñтим регулÑрным выражениÑм, ÐЕ будут защищатьÑÑ Ð¿Ñ€Ð¾Ñ‚Ð¸Ð²Â XSS.">
+<!ENTITY noscriptMatchSample "Пример шаблона:">
+<!ENTITY noscriptReset "СброÑ">
+<!ENTITY noscriptReset.accesskey "о">
+<!ENTITY noscriptResetDef "СброÑить наÑтройки">
+<!ENTITY noscriptResetDef.accesskey "и">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Отменить временные разрешениÑ">
+<!ENTITY noscriptRevokeTemp.accesskey "е">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ðе показывать заполнитель вмеÑто объектов Ñ Ñайтов, отмеченных как недоверенные">
+<!ENTITY noscriptCollapseBlockedObjects "Сворачивать заблокированные объекты">
+<!ENTITY noscriptExceptions "ИÑключениÑ…">
+<!ENTITY noscriptBlockedObjects "Заблокированные объекты">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Блокировать любой объект Ñ Ñайта, отмеченного как недоверенный">
+<!ENTITY noscriptTempAllowPage "Временно разрешить вÑе Ñкрипты на Ñтой Ñтранице">
+<!ENTITY noscriptTempAllowPage.accesskey "о">
+<!ENTITY noscriptAllowPage "Разрешить вÑе Ñкрипты на Ñтой Ñтранице">
+<!ENTITY noscriptAllowPage.accesskey "а">
+<!ENTITY noscriptTempToPerm "Сохранить уÑтановленные разрешениÑ">
+<!ENTITY noscriptTempToPerm.accesskey "о">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "ЧаВо по HTTPS">
+<!ENTITY noscriptHttpsFaq.accesskey "а">
+<!ENTITY noscriptHttps.behavior "Поведение">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Запрещать активное веб-Ñодержимое, за иÑключением защищённых (HTTPS) Ñоединений:">
+<!ENTITY noscriptHttps.never "Ðикогда">
+<!ENTITY noscriptHttps.proxy "При иÑпользовании прокÑи (рекомендуетÑÑ Tor)">
+<!ENTITY noscriptHttps.always "Ð’Ñегда">
+<!ENTITY noscriptHttpsForced "ЗаÑтавлÑÑ‚ÑŒ указанные Ñайты иÑпользовать защищённое (HTTPS) Ñоединение:">
+<!ENTITY noscriptHttpsForcedExceptions "Ðе принуждать иÑпользовать защищённое (HTTPS) Ñоединение Ð´Ð»Ñ Ñайтов:">
+<!ENTITY noscriptSecureCookies "ÐвтоматичеÑÐºÐ°Ñ ÑиÑтема ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑтью cookies">
+<!ENTITY noscriptSecureCookiesForced "ИÑпользовать шифрование Ð´Ð»Ñ Ð²Ñех cookies, уÑтанавливаемых через HTTPS Ñо Ñледующих Ñайтов:">
+<!ENTITY noscriptSecureCookiesExceptions "Игнорировать небезопаÑные cookies, уÑтанавливаемые через HTTPS Ñо Ñледующих Ñайтов:">
+<!ENTITY noscriptClearClickTitle "ÐŸÑ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ ClearClick">
+<!ENTITY noscriptClearClickHeader "Возможно Clickjacking / Попытка Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ UI">
+<!ENTITY noscriptClearClickDescription "NoScript перехватил взаимодейÑтвие мыши или клавиатуры Ñ Ñ‡Ð°Ñтично Ñкрытым Ñлементом. Ðажмите на изображение, чтобы увидеть разницу.">
+<!ENTITY noscriptClearClickOpt "ClearClick-защита на Ñтраницах...">
+<!ENTITY noscriptClearClickReport "Сообщение об ошибке">
+<!ENTITY noscriptClearClickReport.accesskey "о">
+<!ENTITY noscriptClearClickReportId "ID ÑообщениÑ:">
+<!ENTITY noscriptTrustedPagesAdj "доверенных">
+<!ENTITY noscriptUntrustedPagesAdj "недоверенных">
+<!ENTITY noscriptKeepLocked "ОÑтавить Ñтот Ñлемент заблокированным (рекомендуетÑÑ)">
+<!ENTITY noscriptEmbeddings "Ð’Ñтроенные объекты">
+<!ENTITY noscriptPrev "Предыдущий">
+<!ENTITY noscriptNext "Следующий">
+<!ENTITY noscriptFrameOptErr.title "Это Ñодержимое не может быть отображено во фрейме">
+<!ENTITY noscriptFrameOptErr.desc "Ð”Ð»Ñ Ð²Ð°ÑˆÐµÐ¹ безопаÑноÑти издатель Ñтого Ñодержимого не разрешил его отображение во фрейме">
+<!ENTITY noscriptFrameOptErr.link "Щёлкните Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñодержимого в новом окне">
+<!ENTITY noscriptBookmarkSync "Создать резервную копию наÑтроек в закладках Ð´Ð»Ñ Ð»Ñ‘Ð³ÐºÐ¾Ð¹ Ñинхронизации">
+<!ENTITY noscriptShowReleaseNotes "Показывать Ð¿Ñ€Ð¸Ð¼ÐµÑ‡Ð°Ð½Ð¸Ñ Ðº релизу при обновлениÑÑ…">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Ðаборы правил:">
+<!ENTITY ABE.enabled.label "ИÑпользовать ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Разрешить Ñайтам уÑтанавливать Ñвои наборы правил">
+<!ENTITY ABE.edit.label "Изменить...">
+<!ENTITY ABE.edit.accesskey "з">
+<!ENTITY ABE.enable.label "ИÑпользовать">
+<!ENTITY ABE.enable.accesskey "Ñ">
+<!ENTITY ABE.disable.label "Отключить">
+<!ENTITY ABE.disable.accesskey "Ñ‚">
+<!ENTITY ABE.refresh.label "Обновить">
+<!ENTITY ABE.refresh.accesskey "б">
+<!ENTITY noscriptUninstall "Удалить">
+<!ENTITY noscriptRecentBlocked "Ðедавно заблокированные Ñайты">
+<!ENTITY noscriptExternalFilters "Внешние фильтры">
+<!ENTITY noscriptEF.enable "ИÑпользовать внешние фильтры">
+<!ENTITY noscriptEF.add "Ðовый фильтр…">
+<!ENTITY noscriptEF.executable "ИÑполнÑемый файл:">
+<!ENTITY noscriptEF.browse "Обзор…">
+<!ENTITY noscriptEF.contentType "Content type (MIME), подлежащий фильтрации (точное Ñовпадение или регулÑрное выражение):">
+<!ENTITY noscriptEF.exceptions "Ðе фильтровать объекты Ñ Ñтих Ñайтов:">
+<!ENTITY noscriptEF.remove "Удалить">
+<!ENTITY noscriptPreset "Уровень защиты">
+<!ENTITY noscriptPreset.off "Ðикакой (вы Ñерьёзно?)">
+<!ENTITY noscriptPreset.low "Легкое начало (чёрный ÑпиÑок + веб-защита)">
+<!ENTITY noscriptPreset.medium "Стандартный (белый ÑпиÑок + веб-защита)">
+<!ENTITY noscriptPreset.high "ОÑадный (на полную катушку)">
+<!ENTITY noscript.hoverUI "Открывать меню разрешений при наведении мыши на значок NoScript">
+<!ENTITY noscriptDonate "Сделать пожертвование">
+<!ENTITY noscriptDonate.accesskey "в">
+<!ENTITY noscriptAutoReload.currentTab "Перезагружать только активную вкладку">
+<!ENTITY noscriptCascadePermissions "КаÑкадное разрешение Ñкриптов третьей Ñтороны">
+<!ENTITY noscriptRestrictSubdocScripting "Блокировать Ñкрипты из белого ÑпиÑка в Ñубдокументах не из белого ÑпиÑка">
+<!ENTITY noscriptGlobalHttpsWhitelist "Разрешить вÑе HTTPS Ñкрипты в HTTPS документах">
+<!ENTITY noscriptPermanentInPrivate "Пункты поÑтоÑнных разрешений в приватном режиме">
+<!ENTITY noscriptCustom "Custom">
diff --git a/extensions/noscript/chrome/locale/ru-RU/noscript/noscript.properties b/extensions/noscript/chrome/locale/ru-RU/noscript/noscript.properties
new file mode 100644
index 0000000..72b6fd6
--- /dev/null
+++ b/extensions/noscript/chrome/locale/ru-RU/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Разрешить Ñкрипты глобально (опаÑно)
+forbidGlobal=Отменить глобальное разрешение Ñкриптов (рекомендуетÑÑ)
+allowLocal=Разрешить %S
+allowTemp=Временно разрешить %S
+forbidLocal=Запретить %S
+allowed.glb=Скрипты разрешены глобально. Это опаÑно!
+allowed.yes=Скрипты на Ñтой Ñтранице разрешены.
+allowed.prt=Скрипты чаÑтично разрешены.
+allowed.no=Скрипты на Ñтой Ñтранице запрещены.
+global.warning.title=Внимание!
+global.warning.text=Скрипты будут разрешены глобально (Ð´Ð»Ñ Ð²Ñех Ñайтов).\n Это потенциально опаÑное дейÑтвие.\nÐ’Ñ‹ дейÑтвительно хотите продолжить?
+audio.samples=Ðудиопример
+confirm=Вы уверены?
+alwaysAsk=Ð’Ñегда Ñпрашивать подтверждение
+notifyHide=Скрывать ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñле %S Ñекунд
+trust=ДоверÑÑ‚ÑŒ %S
+distrust=Отметить %S как Ðедоверенный
+untrustedOrigin=как недоверенный иÑточник
+xss.notify.generic=NoScript отфильтровал потенциальную XSS-атаку (попытку межÑайтового Ñкриптинга) Ñ Ð°Ð´Ñ€ÐµÑа %S. ТехничеÑкие подробноÑти занеÑены в конÑоль.
+xss.notify.showConsole=Открыть конÑоль…
+xss.notify.showConsole.accessKey=о
+xss.reason.filterXGet=Отфильтрован подозрительный запроÑ. URL: [%1$S]. Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¿Ð¾Ñледовал Ñо Ñтраницы: [%2$S]. Отфильтрованный адреÑ: [%3$S]
+xss.reason.filterXGetRef=Отфильтрован подозрительный иÑточник запроÑа («referer»): URL: [%1$S] Ñо Ñтраницы [%2$S]. Отфильтрованный адреÑ: [%3$S]
+xss.reason.filterXPost=Отфильтрована Ð¿Ð¾Ð´Ð¾Ð·Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° Ñ [%2$S] к [%1$S]: Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½ в GET-Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð»Ñ ÑкачиваниÑ.
+unsafeReload.warning=ÐебезопаÑнаÑ, Ð¿Ð¾Ð´Ð¾Ð·Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°\n\n%1$S [%2$S]\n\nОт [%3$S]\n\nNoScript ÐЕ Ñможет защитить данный запроÑ!\n
+metaRefresh.notify=NoScript заблокировал <META> перенаправление внутри Ñлемента <NOSCRIPT>: %S за %S Ñек.
+metaRefresh.notify.follow=Выполнить перенаправление
+metaRefresh.notify.follow.accessKey=о
+notify.options=ÐаÑтройки
+notify.options.accessKey=а
+reset.title=Ð¡Ð±Ñ€Ð¾Ñ Ð½Ð°Ñтроек NoScript
+reset.warning=ВСЕ наÑтройки NoScript и Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ñайтов будут Ñброшены к значениÑм, уÑтановленным по умолчанию.\nДанную операцию невозможно отменить.\nПродолжить?
+bookmarkSync.title=Закладка конфигурации NoScript
+bookmarkSync.message=Эта закладка предназначена не Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ, а Ð´Ð»Ñ Ñинхронизации Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑервиÑа Weave или раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ XMarks.
+bookmarkSync.confirm=NoScript обнаружил Ñохранённую закладку-конфигурацию раÑширениÑ\n%S.\nЖелаете ли обновить наÑтройки раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ NoScript на указанные в ней?
+ABE.notify=Ð—Ð°Ð¿Ñ€Ð¾Ñ %1$S отфильтрован ABE: <%2$S> %3$S
+ABE.chooseEditor=Выберите текÑтовый редактор Ð´Ð»Ñ Ð½Ð°Ð±Ð¾Ñ€Ð¾Ð² правил ABE
+ABE.syntaxError=СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° в наборе правил ABE!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Разрешить вÑе Ñкрипты Ñ %S
+allowTempFrom=Временно разрешить вÑе Ñкрипты Ñ %S
+siteInfo.confirm=Ð’Ñ‹ ÑобираетеÑÑŒ узнать информацию о Ñайте «%1$S»,\nотправив Ð·Ð°Ð¿Ñ€Ð¾Ñ Ðº %2$S.\nПродолжить?
+siteInfo.tooltip=Middle-click или shift+click Ð´Ð»Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¸ о Ñайте...
+ef.activate=Фильтр %S
+ef.options=%S наÑтройки...
+ef.newName=Введите название нового фильтра:
+ef.locateExe=Выберите иÑполнÑемый файл Ð´Ð»Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð° %S
+disable=Отключить %S
+disable.accessKey=ь
+allowed.glb-emb=Скрипты разрешены глобально, но некоторые вÑтроенные объекты заблокированы
+removal.title=Предупреждение о понижении ÑƒÑ€Ð¾Ð²Ð½Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑти
+removal.message=ÐžÑ‚ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¸Ð»Ð¸ удалÑÑ NoScript, вы отказываетеÑÑŒ от вÑех мер защиты, предоÑтавлÑемых NoScript.\n\nЕÑли вы проÑто уÑтали от обработки разрешений Ñкриптов Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ Ñайта, то еÑÑ‚ÑŒ безопаÑный вариант.\n\nNoScript может прекратить блокировать Ñкрипты, за иÑключением отмеченных вами как недоверенные, в то же Ð²Ñ€ÐµÐ¼Ñ Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÑÑ Ñамые передовые контрмеры против XSS, Clickjacking, CSRF и других веб-угроз.\n\nÐ’Ñ‹ дейÑтвительно хотите удалить вÑÑŽ защиту NoScript?\n
+removal.no=Ðет, но не блокировать Ñкрипты
+removal.yes=Да, удалить ВСЮ защиту
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\bDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/sk-SK/noscript/about.properties b/extensions/noscript/chrome/locale/sk-SK/noscript/about.properties
new file mode 100644
index 0000000..af7e2fa
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sk-SK/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Extra ochrana pre váš Firefox. NoScript povolí JavaScript, Javu (a ÄalÅ¡ie zásuvné moduly) len pre dôveryhodné domény podľa vášho výberu (napríklad webovú stránku vášho e-bankingu). Tento zoznam povolených založený na preventívnom blokovaní prístupu chráni pred zneužívaním bezpeÄnostných dier (známych aj neznámych) bez straty funkÄnosti. Odborníci by súhlasili: Firefox je s rozšírením NoScript naozaj bezpeÄnejší :-)
+aboutTitle=O rozšírení %S
+extensionContributors=Prispievatelia:
+extensionContributors.tip=Ľudia, ktorým patrí vÄaka za toto rozšírenie
+extensionCreatorLabel=Autor:
+changelog=Denník zmien
+changelog.tip=Zobraziť denník zmien
+license=Licencia
+license.tip=Čítať licenciu koncového používateľa
+logo.tip=Navštíviť domovskú stránku rozšírenia
+sponsor.tip=Navštíviť domovskú stránku sponzora
+informaction.tip=Navštíviť stránku InformAction
+extensionHomepage.tip=Navštíviť domovskú stránku rozšírenia
+extensionCreator.tip=Navštíviť domovskú stránku autora
+version=Verzia %S
diff --git a/extensions/noscript/chrome/locale/sk-SK/noscript/noscript.dtd b/extensions/noscript/chrome/locale/sk-SK/noscript/noscript.dtd
new file mode 100644
index 0000000..e7290cd
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sk-SK/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Možnosti...">
+<!ENTITY noscriptOptions.accesskey "M">
+<!ENTITY noscriptOptionsLong "NoScript – Možnosti">
+<!ENTITY noscriptAbout "O rozšírení NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Môžete urÄiÅ¥, ktoré webové stránky majú povolené spúšťaÅ¥ JavaScript. Zadajte adresu alebo doménu (napríklad &quot;http://www.site.com&quot; alebo &quot;site.com&quot;) stránky, ktorú chcete povoliÅ¥, a potom kliknite na tlaÄidlo PovoliÅ¥.">
+<!ENTITY noscriptWebAddress "Adresa webovej stránky:">
+<!ENTITY noscriptAllow "Povoliť">
+<!ENTITY noscriptAllow.accesskey "P">
+<!ENTITY noscriptForbid "Zakázať">
+<!ENTITY noscriptForbid.accesskey "Z">
+<!ENTITY noscriptTrust "OznaÄiÅ¥ ako dôveryhodné">
+<!ENTITY noscriptTrust.accesskey "d">
+<!ENTITY noscriptUntrust "OznaÄiÅ¥ ako nedôveryhodné">
+<!ENTITY noscriptUntrust.accesskey "n">
+<!ENTITY noscriptRemoveSelected "Odstrániť vybrané stránky">
+<!ENTITY noscriptGloballyEnabled "Skripty vÅ¡eobecne povolené (nebezpeÄné)">
+<!ENTITY noscriptAutoReload "Automaticky znovu naÄítaÅ¥ stránky, keÄ sa zmení povolenie">
+<!ENTITY noscriptGeneral "Všeobecné">
+<!ENTITY noscriptAppearance "Vzhľad">
+<!ENTITY noscriptShow "Zobraziť...">
+<!ENTITY noscriptCtxMenu "Kontextová ponuka">
+<!ENTITY noscriptStatusIcon "Ikona v stavovom riadku">
+<!ENTITY noscriptFullAddr "Celé adresy (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Celé domény (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Základňa pre subdomény (noscript.net)">
+<!ENTITY noscriptTempCmd "DoÄasne povoliÅ¥ [...]">
+<!ENTITY noscriptSound "Zvukový signál pri zablokovaní skriptov">
+<!ENTITY noscriptImport "Importovať">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exportovať">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Zobraziť oznámenie o blokovaných skriptoch">
+<!ENTITY noscriptNotify.bottom "Umiestniť oznámenie naspodok">
+<!ENTITY noscriptSound.choose "Vybrať">
+<!ENTITY noscriptSound.choose.accesskey "V">
+<!ENTITY noscriptSound.play "Prehrať">
+<!ENTITY noscriptSound.play.accesskey "h">
+<!ENTITY noscriptSound.reset "Obnoviť predvolené">
+<!ENTITY noscriptSound.reset.accesskey "r">
+<!ENTITY noscriptAdvanced "Spresnenie">
+<!ENTITY noscriptAdditionalPermissions "Ďalšie povolenia pre dôveryhodné stránky">
+<!ENTITY noscriptAllowClipboard "Povoliť kopírovanie a prilepenie textu z externej schránky">
+<!ENTITY noscriptAdditionalRestrictions "Ďalšie obmedzenia pre nepovolené stránky">
+<!ENTITY noscriptPlugins "Zásuvné moduly">
+<!ENTITY noscriptContentBlocker "Použiť tieto obmedzenia aj na dôveryhodné stránky">
+<!ENTITY noscriptForbidJava "Zakázať Java™">
+<!ENTITY noscriptForbidXSLT "Zakázať XSLT">
+<!ENTITY noscriptForbidSilverlight "Zakázať Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Zakázať &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Zakázať &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Zakázať @font-face">
+<!ENTITY noscriptForbidWebGL "Zakázať WebGL">
+<!ENTITY noscriptForbidMedia "Zakázať &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Zakázať Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Zakázať ostatné zásuvné moduly">
+<!ENTITY noscriptReloadWarn "Tieto možnosti sa prejavia na nových (alebo na ruÄne znovu naÄítaných) stránkach">
+<!ENTITY noscriptConfirmUnblock "Pred doÄasným odblokovaním objektu sa opýtaÅ¥ na potvrdenie">
+<!ENTITY noscriptStatusLabel "Informácie v stavovom riadku">
+<!ENTITY noscriptForbidBookmarklets "Zakázať záložkové skripty">
+<!ENTITY noscriptShowPlaceholder "Zobraziť ikonu zástupcu">
+<!ENTITY noscriptTruncateTitle "Skrátiť titulky dokumentov">
+<!ENTITY noscriptFixLinks "Pokúsiť sa opraviť prepojenia JavaScriptu">
+<!ENTITY noscriptAllowBookmarks "Povoliť všetky stránky nájdené v Záložkách">
+<!ENTITY noscriptAllowViaBookmarks "Povoliť stránky otvorené zo Záložiek">
+<!ENTITY noscriptAllowPing "Povoliť &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Povoliť lokálne prepojenia">
+<!ENTITY noscriptForbidPing "Zakázať &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Zakázať presmerovanie META v rámci prvkov &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "Zobraziť správu o zablokovaných META presmerovaniach">
+<!ENTITY noscriptNotifyMeta.accesskey "a">
+<!ENTITY noscriptWhitelist "Zoznam povolených">
+<!ENTITY noscriptPermissions "Povolenia">
+<!ENTITY noscriptRefresh "Obnoviť">
+<!ENTITY noscriptNotifications "Oznámenia">
+<!ENTITY noscriptToolbarToggle "Kliknutím ľavým tlaÄidlom myÅ¡i na tlaÄidlo NoScript na paneli s nástrojmi sa prepínajú povolenia pre aktuálnu doménu najvyÅ¡Å¡ej úrovne">
+<!ENTITY noscriptTrusted "Dôveryhodné">
+<!ENTITY noscriptUntrusted "Nedôveryhodné">
+<!ENTITY noscriptUnknown "Neznáme">
+<!ENTITY noscriptAdd "Pridať">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Zavrieť">
+<!ENTITY noscriptSiteManager "Správca stránok">
+<!ENTITY noscriptSecurityManager "Správca zabezpeÄenia">
+<!ENTITY noscriptPolicies "Politiky">
+<!ENTITY noscriptDefaultPolicies "Predvolené politiky">
+<!ENTITY noscriptSitePolicies "Politiky konkrétnej stránky">
+<!ENTITY noscriptNselNever "Skryť prvky &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Zobraziť prvok &lt;NOSCRIPT&gt;, ktorý nasleduje za blokovaným &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "DoÄasne povoliÅ¥ stránky najvyÅ¡Å¡ej úrovne">
+<!ENTITY noscriptDescription "Extra ochrana pre Firefox: NoScript povolí JavaScript, Javu (a ÄalÅ¡ie doplnky) len pre dôveryhodné domény podľa vášho výberu (napríklad webovú stránku bankingu). Tento zoznam dôveryhodných serverov založený na preventívnom blokovaní chráni pred zneužitím bezpeÄnostných dier (známych aj neznámych!) bez straty funkÄnosti... Experti budú súhlasiÅ¥: Firefox s rozšírením NoScript je naozaj bezpeÄnejší :-)">
+<!ENTITY noscriptOptBlockCssScanners "Blokovať skenery CSS">
+<!ENTITY noscriptOptFilterXGet "Ošetriť podozrivé požiadavky cross-site">
+<!ENTITY noscriptOptFilterXPost "Prepnúť požiadavky POST cross-site na údajovo bezstratové požiadavky GET">
+<!ENTITY noscriptShowConsole "Zobraziť konzolu...">
+<!ENTITY noscriptShowConsole.accesskey "k">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "NebezpeÄné znovunaÄítanie">
+<!ENTITY noscriptUnsafeReload.accesskey "N">
+<!ENTITY noscriptXssExceptions "Výnimky ochrany Anti-XSS">
+<!ENTITY noscriptXssExceptions.description "Adresy zodpovedajúce týmto regulárnym výrazom NEBUDÚ chránené proti XSS">
+<!ENTITY noscriptMatchSample "Vzor šablóny:">
+<!ENTITY noscriptReset "Vynulovať">
+<!ENTITY noscriptReset.accesskey "V">
+<!ENTITY noscriptResetDef "Vynulovať na predvolené">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "ZruÅ¡iÅ¥ doÄasné povolenia">
+<!ENTITY noscriptRevokeTemp.accesskey "d">
+<!ENTITY noscriptNoUntrustedPlaceholder "Žiadny zástupca pre objekty zo stránok oznaÄených ako nedôveryhodné">
+<!ENTITY noscriptCollapseBlockedObjects "StlaÄiÅ¥ blokované objekty">
+<!ENTITY noscriptExceptions "Výnimky...">
+<!ENTITY noscriptBlockedObjects "Blokované objekty">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "BlokovaÅ¥ vÅ¡etky objekty prichádzajúce zo stránky oznaÄenej ako nedôveryhodná">
+<!ENTITY noscriptTempAllowPage "DoÄasne povoliÅ¥ celú túto stránku">
+<!ENTITY noscriptTempAllowPage.accesskey "D">
+<!ENTITY noscriptAllowPage "Povoliť všetky tieto stránky">
+<!ENTITY noscriptAllowPage.accesskey "v">
+<!ENTITY noscriptTempToPerm "Nastaviť toto povolenie ako trvalé">
+<!ENTITY noscriptTempToPerm.accesskey "N">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Správanie">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "ZakázaÅ¥ aktívny obsah webu, ak nepochádza zo zabezpeÄeného pripojenia (HTTPS):">
+<!ENTITY noscriptHttps.never "Nikdy">
+<!ENTITY noscriptHttps.proxy "KeÄ sa používa server proxy (odporúÄané s Tor)">
+<!ENTITY noscriptHttps.always "Vždy">
+<!ENTITY noscriptHttpsForced "VynútiÅ¥ používanie zabezpeÄeného pripojenia (HTTPS) pre nasledujúce stránky:">
+<!ENTITY noscriptHttpsForcedExceptions "Nikdy nenútiÅ¥ zabezpeÄené pripojenie (HTTPS) pre nasledujúce stránky:">
+<!ENTITY noscriptSecureCookies "PovoliÅ¥ Automatickú správu zabezpeÄených cookies">
+<!ENTITY noscriptSecureCookiesForced "VynútiÅ¥ zabezpeÄenie pre vÅ¡etky cookies nastavené cez HTTPS pre nasledujúce stránky&quot;">
+<!ENTITY noscriptSecureCookiesExceptions "IgnorovaÅ¥ nebezpeÄné cookies nastavené nastavené nasledujúcimi stránkami cez HTTPS">
+<!ENTITY noscriptClearClickTitle "Upozornenia ClearClick">
+<!ENTITY noscriptClearClickHeader "Potenciálny pokus o podvodné správanie po kliknutí!">
+<!ENTITY noscriptClearClickDescription "NoScript zachytil interakciu klávesnice alebo myÅ¡i s ÄiastoÄne skrytým objektom. Kliknutím na obrázok môžete prepínaÅ¥ medzi podozrivou a preÄistenou verziou.">
+<!ENTITY noscriptClearClickOpt "Ochrana ClearClick na">
+<!ENTITY noscriptClearClickReport "Nahlásiť">
+<!ENTITY noscriptClearClickReport.accesskey "h">
+<!ENTITY noscriptClearClickReportId "ID správy:">
+<!ENTITY noscriptTrustedPagesAdj "dôveryhodných stránkach">
+<!ENTITY noscriptUntrustedPagesAdj "nedôveryhodných stránkach">
+<!ENTITY noscriptKeepLocked "PonechaÅ¥ tento prvok blokovaný (odporúÄa sa)">
+<!ENTITY noscriptEmbeddings "Vložené objekty">
+<!ENTITY noscriptPrev "Predchádzajúci">
+<!ENTITY noscriptNext "Ďalší">
+<!ENTITY noscriptFrameOptErr.title "Tento obsah nie je možné zobraziť v rámci">
+<!ENTITY noscriptFrameOptErr.desc "Na vašu ochranu autor tohto obsahu nepovolil jeho zobrazenie v rámci">
+<!ENTITY noscriptFrameOptErr.link "Kliknutím sem otvoríte tento obsah v novom okne">
+<!ENTITY noscriptBookmarkSync "Zálohujte si konfiguráciu rozšírenia NoScript ako záložku pre jednoduchú synchronizáciu">
+<!ENTITY noscriptShowReleaseNotes "Pri aktualizácii zobraziť poznámky k vydaniu">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Sady pravidiel:">
+<!ENTITY ABE.enabled.label "Povoliť ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Povoliť stránkam pridávať ich vlastné sady pravidiel">
+<!ENTITY ABE.edit.label "Upraviť...">
+<!ENTITY ABE.edit.accesskey "U">
+<!ENTITY ABE.enable.label "Povoliť">
+<!ENTITY ABE.enable.accesskey "P">
+<!ENTITY ABE.disable.label "Zakázať">
+<!ENTITY ABE.disable.accesskey "Z">
+<!ENTITY ABE.refresh.label "Obnoviť">
+<!ENTITY ABE.refresh.accesskey "O">
+<!ENTITY noscriptUninstall "Odinštalovať">
+<!ENTITY noscriptRecentBlocked "Naposledy zablokované stránky">
+<!ENTITY noscriptExternalFilters "Externé filtre">
+<!ENTITY noscriptEF.enable "Povoliť externé filtre">
+<!ENTITY noscriptEF.add "Nový filter…">
+<!ENTITY noscriptEF.executable "Spustiteľný súbor:">
+<!ENTITY noscriptEF.browse "Prehľadávať…">
+<!ENTITY noscriptEF.contentType "Typ obsahu (MIME), ktorý má byť filtrovaný (presná zhoda alebo regulárny výraz):">
+<!ENTITY noscriptEF.exceptions "Nefiltrovať objekty z týchto stránok:">
+<!ENTITY noscriptEF.remove "Odstrániť">
+<!ENTITY noscriptPreset "Úroveň zabezpeÄenia">
+<!ENTITY noscriptPreset.off "Vypnuté (vážne to chcete?)">
+<!ENTITY noscriptPreset.low "Jednoduché (Äierna listina + webová bezpeÄnosÅ¥)">
+<!ENTITY noscriptPreset.medium "Klasické (biela listina + webová bezpeÄnosÅ¥)">
+<!ENTITY noscriptPreset.high "Pevnosť (úplné uzamknutie)">
+<!ENTITY noscript.hoverUI "Otvoriť ponuku povolení po presunutí myši nad ikonu rozšírenia NoScript">
+<!ENTITY noscriptDonate "Prispieť">
+<!ENTITY noscriptDonate.accesskey "P">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/sk-SK/noscript/noscript.properties b/extensions/noscript/chrome/locale/sk-SK/noscript/noscript.properties
new file mode 100644
index 0000000..e555511
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sk-SK/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=PovoliÅ¥ JavaScript vÅ¡eobecne (nebezpeÄné)
+forbidGlobal=ZakázaÅ¥ JavaScript vÅ¡eobecne (odporúÄané)
+allowLocal=Povoliť %S
+allowTemp=DoÄasne povoliÅ¥ %S
+forbidLocal=Zakázať %S
+allowed.glb=Pozor! JavaScript všeobecne povolený
+allowed.yes=JavaScript aktuálne povolený
+allowed.prt=JavaScript ÄiastoÄne povolený
+allowed.no=JavaScript aktuálne zakázaný
+global.warning.title=Upozornenie!
+global.warning.text=JavaScript bude vÅ¡eobecne povolený (pre vÅ¡etky stránky).\nToto je možno nebezpeÄná akcia.\nNaozaj chcete pokraÄovaÅ¥?
+audio.samples=Zvuky
+confirm=Naozaj to chcete?
+alwaysAsk=Vždy sa opýtať na potvrdenie
+notifyHide=Skryť po %S s.
+trust=Dôveryhodné: %S
+distrust=OznaÄiÅ¥ %S ako nedôveryhodné
+untrustedOrigin=Nedôveryhodný pôvod
+xss.notify.generic=NoScript filtroval potencionálny pokus o skriptovanie cross-site (XSS). Technické podrobnosti boli zaznamenané do konzoly.
+xss.notify.showConsole=Zobraziť konzolu...
+xss.notify.showConsole.accessKey=k
+xss.reason.filterXGet=Ošetrená podozrivá požiadavka. Pôvodná adresa [%1$S] požadovaná z %2$S]. Ošetrená adresa: [%3$S].
+xss.reason.filterXGetRef=OÅ¡etrená podozrivá požiadavka odkazovaÄa. Adresa [%1$S] požadovaná z [%2$S]. OÅ¡etrený odkazovaÄ: [%3$S].
+xss.reason.filterXPost=Ošetrené podozrivé odovzdávanie na [%1$S] z [%2$S]: transformované na požiadavku GET (Len prevziať).
+unsafeReload.warning=NEBEZPEÄŒNÉ znovunaÄítanie podozrivého\n\n%1$S [%2$S]\n\nZ [%3$S]\n\nNoScript NEBUDE chrániÅ¥ túto požiadavku!\n
+metaRefresh.notify=NoScript zablokoval presmerovanie <META> v rámci prvku <NOSCRIPT>: %S o %S s.
+metaRefresh.notify.follow=Nasledovať presmerovanie
+metaRefresh.notify.follow.accessKey=N
+notify.options=Možnosti
+notify.options.accessKey=M
+reset.title=NoScript – Vynulovanie
+reset.warning=VÅ ETKY predvoľby a povolenia stránok budú priamo vynulované na predvolené hodnoty.\nTento úkon nemožno vrátiÅ¥.\nChcete pokraÄovaÅ¥?
+bookmarkSync.title=Záložka konfigurácie rozšírenia NoScript
+bookmarkSync.message=Táto záložka nie je urÄená na otváranie, ale na synchronizáciu využitím služieb rozšírení ako Weave Äi XMarks.
+bookmarkSync.confirm=NoScript naÅ¡iel konfiguraÄnú záložku zdanlivo uloženú v\n%S.\nNaozaj chcete prepísaÅ¥ lokálnu konfiguráciu rozšírenia NoScript obsahom tejto záložky?
+ABE.notify=Žiadosť %1$S odfiltrovaná pomocou ABE: <%2$S> %3$S
+ABE.chooseEditor=Zvoľte textový editor pre sady pravidiel ABE
+allowFrom=Povoliť všetky z %S
+allowTempFrom=DoÄasne povoliÅ¥ vÅ¡etky z %S
+ABE.syntaxError=Chyba syntaxe v sade pravidiel ABE!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+siteInfo.confirm=Chystáte sa požiadaÅ¥ o informácie o stránke "%1$S"\nodoslaním požiadavky na %2$S.\nChcete pokraÄovaÅ¥?
+siteInfo.tooltip=Informácie o stránke po kliknutí stredným tlaÄidlom alebo kombinácii Shift+kliknutie…
+ef.activate=Filter %S
+ef.options=Možnosti %S…
+ef.newName=Zadajte názov filtra:
+ef.locateExe=Zvoľte spustiteľný súbor pre filter %S
+disable=Vypnúť %S
+disable.accessKey=V
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/sl-SI/noscript/about.properties b/extensions/noscript/chrome/locale/sl-SI/noscript/about.properties
new file mode 100644
index 0000000..5e2d34c
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sl-SI/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Dodatna zaÅ¡Äita za vaÅ¡ Firefox: NoScript omogoÄi izvajanje JavaScript, Java (in drugih vtiÄnikov) samo na zaupanja vrednih domenah po vaÅ¡i izbiri (pr. domaÄa stran vaÅ¡e spletne banke). S pristopom varnih seznamov onemogoÄimo izkoriÅ¡Äanje varnostnih lukenj (znanih in neznanih!) brez izgub funkcionalnosti... Strokovnjaki se bodo strinjali: Firefox je bolj varen z uporabo NoScript-a :-)
+aboutTitle=O programu %S
+extensionContributors=Prispevali so:
+extensionContributors.tip=Ljudje, katerim se morate zahvaliti za to razširitev
+extensionCreatorLabel=Avtor:
+changelog=Dnevnik sprememb
+changelog.tip=Prikaži dnevnik sprememb
+license=Licenca
+license.tip=Preberi licenco za konÄnega uporabnika
+logo.tip=Pojdi na domaÄo stran razÅ¡iritve
+sponsor.tip=ObiÅ¡Äi domaÄo stran sponzorja
+informaction.tip=ObiÅ¡Äi domaÄo stran InformAction
+extensionHomepage.tip=ObiÅ¡Äi domaÄo stran razÅ¡iritve
+extensionCreator.tip=ObiÅ¡Äi domaÄo stran avtorja
+version=RazliÄica %S
diff --git a/extensions/noscript/chrome/locale/sl-SI/noscript/noscript.dtd b/extensions/noscript/chrome/locale/sl-SI/noscript/noscript.dtd
new file mode 100644
index 0000000..1de57d5
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sl-SI/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Možnosti...">
+<!ENTITY noscriptOptions.accesskey "M">
+<!ENTITY noscriptOptionsLong "NoScript Možnosti">
+<!ENTITY noscriptAbout "O NoScript 5.1.8.5 programu...">
+<!ENTITY noscriptPermissionsText "DoloÄite lahko na katerih straneh bo izvajanje skript dovoljeno. Vnesite naslov ali domeno (pr. &quot;http://www.domena.com&quot; or &quot;domena.com&quot;) strani, na kateri želite omogoÄiti izvajanje skript in kliknite Dovoli.">
+<!ENTITY noscriptWebAddress "Naslov strani:">
+<!ENTITY noscriptAllow "Dovoli">
+<!ENTITY noscriptAllow.accesskey "D">
+<!ENTITY noscriptForbid "PrepreÄi">
+<!ENTITY noscriptForbid.accesskey "P">
+<!ENTITY noscriptTrust "OznaÄi kot varno">
+<!ENTITY noscriptTrust.accesskey "V">
+<!ENTITY noscriptUntrust "OznaÄi kot nevarno">
+<!ENTITY noscriptUntrust.accesskey "N">
+<!ENTITY noscriptRemoveSelected "Odstrani oznaÄene strani">
+<!ENTITY noscriptGloballyEnabled "OmogoÄeno vsesploÅ¡no izvajanje skript (nevarno)">
+<!ENTITY noscriptAutoReload "Avtomatsko osveži strani ob spremembi pravic">
+<!ENTITY noscriptGeneral "Splošno">
+<!ENTITY noscriptAppearance "Izgled">
+<!ENTITY noscriptShow "Prikaži...">
+<!ENTITY noscriptCtxMenu "Kontekstualni meni">
+<!ENTITY noscriptStatusIcon "Ikono v statusni vrstici">
+<!ENTITY noscriptFullAddr "Polen naslov (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Polne domene (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Osnovne domene drugega reda (noscript.net)">
+<!ENTITY noscriptTempCmd "ZaÄasno omogoÄi [...]">
+<!ENTITY noscriptSound "ZvoÄni signal ob onemogoÄenih skriptah">
+<!ENTITY noscriptImport "Uvozi">
+<!ENTITY noscriptImport.accesskey "U">
+<!ENTITY noscriptExport "Izvozi">
+<!ENTITY noscriptExport.accesskey "I">
+<!ENTITY noscriptNotify "Prikaži sporoÄilo o blokiranih skriptah">
+<!ENTITY noscriptNotify.bottom "Prikaži sporoÄilo na dnu">
+<!ENTITY noscriptSound.choose "Prebrskaj">
+<!ENTITY noscriptSound.choose.accesskey "r">
+<!ENTITY noscriptSound.play "Predvajaj">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Ponastavi">
+<!ENTITY noscriptSound.reset.accesskey "o">
+<!ENTITY noscriptAdvanced "Napredno">
+<!ENTITY noscriptAdditionalPermissions "Dodatna dovoljenja za zaupanja vredne strani">
+<!ENTITY noscriptAllowClipboard "OmogoÄi kopiranje in lepljenje obogatenega besedila s sistemskega odložiÅ¡Äa">
+<!ENTITY noscriptAdditionalRestrictions "Dodatne omejitve za zaupanja nevredne strani">
+<!ENTITY noscriptPlugins "VtiÄniki">
+<!ENTITY noscriptContentBlocker "Uporabi te omejitve tudi na zaupanja vrednih straneh">
+<!ENTITY noscriptForbidJava "OnemogoÄi Javoâ„¢">
+<!ENTITY noscriptForbidXSLT "OnemogoÄi XSLT">
+<!ENTITY noscriptForbidSilverlight "OnemogoÄi Microsoft® Silverlightâ„¢">
+<!ENTITY noscriptForbidIFrames "OnemogoÄi &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "OnemogoÄi &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "OnemogoÄi @font-face">
+<!ENTITY noscriptForbidWebGL "OnemogoÄi WebGL">
+<!ENTITY noscriptForbidMedia "OnemogoÄi &lt;ZVOK&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "OnemogoÄi Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "OnemogoÄi druge vtiÄnike">
+<!ENTITY noscriptReloadWarn "Te nastavitve bodo stopile v veljavo na novih oz. (roÄno) osveženih straneh">
+<!ENTITY noscriptConfirmUnblock "Zahtevaj potrditev preden zaÄasno omogoÄiÅ¡ doloÄen predmet">
+<!ENTITY noscriptStatusLabel "Opis v statusni vrstici">
+<!ENTITY noscriptForbidBookmarklets "OnemogoÄi bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Prikaži ikono pri blokiranih predmetih">
+<!ENTITY noscriptTruncateTitle "Odreži naslove dokumentov">
+<!ENTITY noscriptFixLinks "Poskušaj popraviti JavaScript povezave">
+<!ENTITY noscriptAllowBookmarks "Dovoli odpiranje strani preko bookmarkov">
+<!ENTITY noscriptAllowViaBookmarks "Dovoli odpiranje strani preko bookmarkov">
+<!ENTITY noscriptAllowPing "Dovoli &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Dovoli lokalne povezave">
+<!ENTITY noscriptForbidPing "OnemogoÄi &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "OnemogoÄi META preusmeritve znotraj &lt;NOSCRIPT&gt; elementov">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "P">
+<!ENTITY noscriptNotifyMeta "Prikaži obvestilo o blokiranih META preusmeritvah">
+<!ENTITY noscriptNotifyMeta.accesskey "P">
+<!ENTITY noscriptWhitelist "Seznam dovoljenih strani">
+<!ENTITY noscriptPermissions "Dovoljenja">
+<!ENTITY noscriptRefresh "Osveži">
+<!ENTITY noscriptNotifications "Obvestila">
+<!ENTITY noscriptToolbarToggle "Z levim klikom na NoScript gumbu v orodni vrstici se spremenijo dovoljenja za trenutno vrhnjo domeno">
+<!ENTITY noscriptTrusted "Varno">
+<!ENTITY noscriptUntrusted "Nevarno">
+<!ENTITY noscriptUnknown "Neznano">
+<!ENTITY noscriptAdd "Dodaj">
+<!ENTITY noscriptAdd.accesskey "D">
+<!ENTITY noscriptClose "Zapri">
+<!ENTITY noscriptSiteManager "Upravitelj strani">
+<!ENTITY noscriptSecurityManager "Upravitelj varnosti">
+<!ENTITY noscriptPolicies "Politike">
+<!ENTITY noscriptDefaultPolicies "Privzete politike">
+<!ENTITY noscriptSitePolicies "SpecifiÄne politike strani">
+<!ENTITY noscriptNselNever "Skrij &lt;NOSCRIPT&gt; elemente">
+<!ENTITY noscriptNselForce "Prikaži &lt;NOSCRIPT&gt; elemente, ki sledijo blokiranemu &lt;SCRIPT&gt; elementu">
+<!ENTITY noscriptAutoAllowTopLevel "Privzeto zaÄasno dovoli vrhnje domene">
+<!ENTITY noscriptDescription "Dodatna zaÅ¡Äita za vaÅ¡ Firefox: NoScript omogoÄi izvajanje JavaScript, Java (in drugih vtiÄnikov) samo na zaupanja vrednih domenah po vaÅ¡i izbiri (pr. domaÄa stran vaÅ¡e spletne banke). S pristopom varnih seznamov onemogoÄimo izkoriÅ¡Äanje varnostnih lukenj (znanih in neznanih!) brez izgub funkcionalnosti... Strokovnjaki se bodo strinjali: Firefox je bolj varen z uporabo NoScript-a :-)">
+<!ENTITY noscriptOptBlockCssScanners "PrepreÄi CSS-osnovane skenerje">
+<!ENTITY noscriptOptFilterXGet "Saniraj sumljive zahtevke drugih strani">
+<!ENTITY noscriptOptFilterXPost "Preoblikuj cross-site POST zahtevke v data-less GET zahtevke">
+<!ENTITY noscriptShowConsole "Prikaži konzolo...">
+<!ENTITY noscriptShowConsole.accesskey "P">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Nevarna osvežitev">
+<!ENTITY noscriptUnsafeReload.accesskey "o">
+<!ENTITY noscriptXssExceptions "Izjeme pri XSS zaÅ¡Äiti">
+<!ENTITY noscriptXssExceptions.description "Naslovi, ki ustrezajo spodaj predpisanim vzorcem NE BODO zaÅ¡Äiteni pred XSS ranljivostmi">
+<!ENTITY noscriptMatchSample "Primer ujemanja vzorca:">
+<!ENTITY noscriptReset "Ponastavi">
+<!ENTITY noscriptReset.accesskey "P">
+<!ENTITY noscriptResetDef "Ponastavi na privzete vrednosti">
+<!ENTITY noscriptResetDef.accesskey "n">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "PrekliÄi zaÄasne pravice">
+<!ENTITY noscriptRevokeTemp.accesskey "Z">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ne prikaži okvirja predmetov, ki izvirajo iz zaupanja nevrednih strani">
+<!ENTITY noscriptCollapseBlockedObjects "Skrij blokirane predmete">
+<!ENTITY noscriptExceptions "Izjeme...">
+<!ENTITY noscriptBlockedObjects "Blokirani predmeti">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Blokiraj vsak predmet, ki prihaja z zaupanja nevrednih strani">
+<!ENTITY noscriptTempAllowPage "ZaÄasno omogoÄi vse na tej strani">
+<!ENTITY noscriptTempAllowPage.accesskey "S">
+<!ENTITY noscriptAllowPage "Dovoli vse na tej strani">
+<!ENTITY noscriptAllowPage.accesskey "D">
+<!ENTITY noscriptTempToPerm "Spremeni dovoljenja za stran v trajna">
+<!ENTITY noscriptTempToPerm.accesskey "t">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ...">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Delovanje">
+<!ENTITY noscriptHttps.cookies "Piškotki">
+<!ENTITY noscriptHttps.description "OnemogoÄi aktivno vsebino v kolikor ne prihaja iz varne (HTTPS) povezave:">
+<!ENTITY noscriptHttps.never "Nikoli">
+<!ENTITY noscriptHttps.proxy "Ko uporabljam proxy strežnik (priporoÄeno pri Tor)">
+<!ENTITY noscriptHttps.always "Vedno">
+<!ENTITY noscriptHttpsForced "Vsili slednjim stranem uporabo varne (HTTPS) povezave:">
+<!ENTITY noscriptHttpsForcedExceptions "Nikoli ne vsili varne (HTTPS) povezave sledeÄim stranem:">
+<!ENTITY noscriptSecureCookies "OmogoÄi avtomatsko varno upravljanje piÅ¡kotkov">
+<!ENTITY noscriptSecureCookiesForced "Vsili Å¡ifriranje za vse piÅ¡kotke ustvarjene preko HTTPS za sledeÄe strani:">
+<!ENTITY noscriptSecureCookiesExceptions "Prezri nevarne piÅ¡kotke ustvarjene preko HTTPS za sledeÄe strani:">
+<!ENTITY noscriptClearClickTitle "ClearClick Opozorilo">
+<!ENTITY noscriptClearClickHeader "Morebiten poskus ugrabitve klika oz. uporabniškega vmesnika.">
+<!ENTITY noscriptClearClickDescription "NoScript je zaznal interakcijo miÅ¡ke oz. tipkovnice z delno prikritim elementom. Kliknite na zgornjo sliko za prikaz prikrite in prave razliÄice.">
+<!ENTITY noscriptClearClickOpt "ClearClick zaÅ¡Äita na straneh...">
+<!ENTITY noscriptClearClickReport "PoroÄilo">
+<!ENTITY noscriptClearClickReport.accesskey "P">
+<!ENTITY noscriptClearClickReportId "ID poroÄila:">
+<!ENTITY noscriptTrustedPagesAdj "zaupljiv">
+<!ENTITY noscriptUntrustedPagesAdj "nezaupljiv">
+<!ENTITY noscriptKeepLocked "Naj bo ta element zaklenjen (priporoÄeno)">
+<!ENTITY noscriptEmbeddings "Vstavljeni predmeti">
+<!ENTITY noscriptPrev "Prejšnji">
+<!ENTITY noscriptNext "Naslednji">
+<!ENTITY noscriptFrameOptErr.title "Vsebine ni mogoÄe prikazati v okviru">
+<!ENTITY noscriptFrameOptErr.desc "Zaradi vaše varnosti, založnik ne dovoljuje objavo vsebine v okvirju">
+<!ENTITY noscriptFrameOptErr.link "Kliknite sem da se vsebina odpre v novem oknu">
+<!ENTITY noscriptBookmarkSync "Naredite varnostno kopijo NoScript med zaznamke za lažjo sinhronizacijo">
+<!ENTITY noscriptShowReleaseNotes "Prikaži opombe k izdaji ob posodobitvah">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Pravila:">
+<!ENTITY ABE.enabled.label "OmogoÄi ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Dovoli stranem vsiljevanje lastnih pravil">
+<!ENTITY ABE.edit.label "Uredi…">
+<!ENTITY ABE.edit.accesskey "U">
+<!ENTITY ABE.enable.label "OmogoÄi">
+<!ENTITY ABE.enable.accesskey "O">
+<!ENTITY ABE.disable.label "OnemogoÄi">
+<!ENTITY ABE.disable.accesskey "n">
+<!ENTITY ABE.refresh.label "Osveži">
+<!ENTITY ABE.refresh.accesskey "v">
+<!ENTITY noscriptUninstall "Odstrani">
+<!ENTITY noscriptRecentBlocked "Nedavno blokirane strani">
+<!ENTITY noscriptExternalFilters "Zunanji Filtri">
+<!ENTITY noscriptEF.enable "OmogoÄi zunanje filtre">
+<!ENTITY noscriptEF.add "Nov filter...">
+<!ENTITY noscriptEF.executable "Izvršilna datoteka:">
+<!ENTITY noscriptEF.browse "Prebrskaj...">
+<!ENTITY noscriptEF.contentType "Vrsta vsebine (MIME), ki jo je treba filtrirati (natanÄno ujemanje ali regularni izraz):">
+<!ENTITY noscriptEF.exceptions "Ne filtriraj predmetov, ki prihajajo iz teh strani:">
+<!ENTITY noscriptEF.remove "Odstrani">
+<!ENTITY noscriptPreset "Varnostni nivo">
+<!ENTITY noscriptPreset.off "OnemogoÄen (ali mislite resno?!)">
+<!ENTITY noscriptPreset.low "Lahkotno brskanje (ÄŒrni seznam + Spletna varnost)">
+<!ENTITY noscriptPreset.medium "Klasika (Beli seznam + Spletna varnost)">
+<!ENTITY noscriptPreset.high "Trdnjava (Popolna blokada)">
+<!ENTITY noscript.hoverUI "Odpri menu z dovoljenji, ko kurzor preleti NoScript ikono">
+<!ENTITY noscriptDonate "Doniraj">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/sl-SI/noscript/noscript.properties b/extensions/noscript/chrome/locale/sl-SI/noscript/noscript.properties
new file mode 100644
index 0000000..1757c8f
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sl-SI/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=OmogoÄi vsesploÅ¡no izvajanje skript (nevarno)
+forbidGlobal=OnemogoÄi vsesploÅ¡no izvajanje skript (priporoÄeno)
+allowLocal=Dovoli %S
+allowTemp=ZaÄasno dovoli %S
+forbidLocal=OnemogoÄi %S
+allowed.glb=Pozor! OmogoÄeno vsesploÅ¡no izvajanje skript
+allowed.yes=Trenutno omogoÄene skripte
+allowed.prt=Trenutno delno omogoÄene skripte
+allowed.no=Trenutno onemogoÄene skripte
+global.warning.title=Pozor!
+global.warning.text=Izvajanje skript bo vsesploÅ¡no omogoÄeno (na vsaki strani).\n To je lahko potencialno nevarno poÄetje.\nAli resniÄno želite nadaljevati?
+audio.samples=ZvoÄni posnetki
+confirm=Ste prepriÄani?
+alwaysAsk=Vedno zahtevaj potrditev
+notifyHide=Skrij po %S sekundah
+trust=Zaupaj %S
+distrust=OznaÄi %S kot nevarno
+untrustedOrigin=zaupanja nevreden izvor
+xss.notify.generic=NoScript je prestrezel potencialno cross-site scripting (XSS) namero na strani %S. TehniÄni detajli so zabeleženi v Konzoli.
+xss.notify.showConsole=Prikaži Konzolo...
+xss.notify.showConsole.accessKey=K
+xss.reason.filterXGet=Saniran sumljiv zahtevek. Izvoren URL [%1$S] zahtevan s strani [%2$S]. Saniran URL: [%3$S].)
+xss.reason.filterXGetRef=Saniran sumljiv naslov zahtevka. URL [%1$S] zahtevan s strani [%2$S]. Saniran naslov: [%3$S].)
+xss.reason.filterXPost=Sanirano sumljivo nalaganje na [%1$S] s strani [%2$S]: preoblikovano v download-only GET zahtevek
+unsafeReload.warning=NEVARNO ponovno nalagam sumljivo\n\n%1$S [%2$S]\n\nS STRANI [%3$S]\n\nNoScript NE BO zaÅ¡Äitil tega zahtevka!\n
+metaRefresh.notify=NoScript je onemogoÄil <META> preusmeritev znotraj <NOSCRIPT> elementa: %S v %S sekundah.
+metaRefresh.notify.follow=Sledi preusmeritvi
+metaRefresh.notify.follow.accessKey=S
+notify.options=Možnosti
+notify.options.accessKey=M
+reset.title=NoScript ponastavitev
+reset.warning=VSE nastavitve NoScript-a in dovoljenja strani bodo ponastavljena na privzete vrednosti.\nDejanja ni mogoÄe preklicati.\nAli želite nadaljevati?
+bookmarkSync.title=NoScript nastavitveni Zaznamek
+bookmarkSync.message=Ta zaznamek, NI miÅ¡ljen za branje, ampak za sinhronizacijo z uporabo storitev kot sta Weave ali XMarks vtiÄnika.
+bookmarkSync.confirm=NoScript je naÅ¡el nastavitveni zaznamek dozdevno shranjen na\n%S.\nAli resniÄno želite prepisati lokalne nastavitve NoScript z nastavitvami iz zaznamka?
+ABE.notify=Zahtevaj %1$S filtrira ABE: <%2$S> %3$S
+ABE.chooseEditor=Izberite tekstovni urejevalnik za urejanje ABE pravil
+ABE.syntaxError=Napaka v sintaksi ABE pravil!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=OmogoÄi vse z %S
+allowTempFrom=ZaÄasno omogoÄi vse z %S
+siteInfo.confirm=Ste na tem, da zaprosite za informacije o "%1$S" strani\Ns poizvedbo na %2$S.\nAli želite nadaljevati?
+siteInfo.tooltip=Srednji klik ali shift + klik za info stran...
+ef.activate=Filtriraj %S
+ef.options=%S možnosti...
+ef.newName=Vnesite ime novega filtra:
+ef.locateExe=Izberite izvršilno datoteko za %S filter
+disable=OnemogoÄi %S
+disable.accessKey=O
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/sr-RS/noscript/about.properties b/extensions/noscript/chrome/locale/sr-RS/noscript/about.properties
new file mode 100644
index 0000000..d5ea346
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sr-RS/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Додатна заштита за Ваш Firefox: NoScript дозвољава JavaScript, Java (и оÑтале додатке) Ñамо доменима којима Ñе верује по Вашем избору (нпр. Ваша е-banking веб Ñтрана). Овај превентивни приÑтуп блокирања базиран на белој лиÑти Ñпречава иÑкоришћавање безбедноÑних пропуÑта (познатих и чак и непознатих!) без икаквог губитка функционалноÑти... ЕкÑперти ће Ñе Ñложити: Firefox је заиÑта безбеднији Ñа NoScript-ом :-)
+aboutTitle=О %S
+extensionContributors=Радили на пројекту:
+extensionContributors.tip=Људи којима би требало да захвалите за ово проширење
+extensionCreatorLabel=Ðутор:
+changelog=Дневник промена
+changelog.tip=Прикажи дневник промена
+license=Лиценца
+license.tip=Прочитајте лиценцу за крајњег кориÑника
+logo.tip=ПоÑетите веб Ñтрану проширења
+sponsor.tip=ПоÑетите веб Ñтрану Ñпонзора
+informaction.tip=ПоÑетите InformAction веб Ñтрану
+extensionHomepage.tip=ПоÑетите веб Ñтрану проширења
+extensionCreator.tip=ПоÑетите веб Ñтрану аутора
+version=Верзија %S
diff --git a/extensions/noscript/chrome/locale/sr-RS/noscript/noscript.dtd b/extensions/noscript/chrome/locale/sr-RS/noscript/noscript.dtd
new file mode 100644
index 0000000..8083ced
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sr-RS/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Подешавања...">
+<!ENTITY noscriptOptions.accesskey "П">
+<!ENTITY noscriptOptionsLong "NoScript подешавања">
+<!ENTITY noscriptAbout "О NoScript 5.1.8.5-у">
+<!ENTITY noscriptPermissionsText "Можете да наведете којим веб Ñтранама је дозвољено да извршавају Ñкриптове. УнеÑите адреÑу или домен (нпр. &quot;http://www.site.com&quot; или &quot;site.com&quot;) Ñтране којој желите да дате дозволу и онда кликните Дозволи.">
+<!ENTITY noscriptWebAddress "ÐдреÑа веб Ñтране:">
+<!ENTITY noscriptAllow "Дозволи">
+<!ENTITY noscriptAllow.accesskey "Д">
+<!ENTITY noscriptForbid "Забрани">
+<!ENTITY noscriptForbid.accesskey "З">
+<!ENTITY noscriptTrust "Означи као проверено">
+<!ENTITY noscriptTrust.accesskey "в">
+<!ENTITY noscriptUntrust "Означи као непроверено">
+<!ENTITY noscriptUntrust.accesskey "н">
+<!ENTITY noscriptRemoveSelected "Уклони изабране Ñтране">
+<!ENTITY noscriptGloballyEnabled "Скриптови Ñу глобално дозвољени (опаÑно)">
+<!ENTITY noscriptAutoReload "ÐутоматÑки поново учитај Ñтране које Ñу обухваћене променом дозвола">
+<!ENTITY noscriptGeneral "Опште">
+<!ENTITY noscriptAppearance "Изглед">
+<!ENTITY noscriptShow "Прикажи...">
+<!ENTITY noscriptCtxMenu "КонтекÑтни мени">
+<!ENTITY noscriptStatusIcon "Икона на ÑтатуÑној линији">
+<!ENTITY noscriptFullAddr "Пуне адреÑе (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Пуни домени (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Базни домени другог нивоа (noscript.net)">
+<!ENTITY noscriptTempCmd "Привремено дозволи [...]">
+<!ENTITY noscriptSound "Звучно обавештење када Ñу Ñкриптови блокирани">
+<!ENTITY noscriptImport "Увоз">
+<!ENTITY noscriptImport.accesskey "У">
+<!ENTITY noscriptExport "Извоз">
+<!ENTITY noscriptExport.accesskey "И">
+<!ENTITY noscriptNotify "Прикажи поруку о блокираним Ñкриптовима">
+<!ENTITY noscriptNotify.bottom "ПоÑтави поруку на дно">
+<!ENTITY noscriptSound.choose "Изаберите">
+<!ENTITY noscriptSound.choose.accesskey "з">
+<!ENTITY noscriptSound.play "Свирај">
+<!ENTITY noscriptSound.play.accesskey "С">
+<!ENTITY noscriptSound.reset "Врати на подразумевано">
+<!ENTITY noscriptSound.reset.accesskey "Ð’">
+<!ENTITY noscriptAdvanced "Ðапредно">
+<!ENTITY noscriptAdditionalPermissions "Додатне дозволе за Ñтранице којима Ñе верује">
+<!ENTITY noscriptAllowClipboard "Дозволи rich text копирање и налепљивање из ектерног клипборда">
+<!ENTITY noscriptAdditionalRestrictions "Додатне забране за Ñтранице којима Ñе не верује">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Apply these restrictions to trusted sites too">
+<!ENTITY noscriptForbidJava "Забрани Java™">
+<!ENTITY noscriptForbidXSLT "Забрани XSLT">
+<!ENTITY noscriptForbidSilverlight "Забрани Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Забрани &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Забрани &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Забрани @font-face">
+<!ENTITY noscriptForbidWebGL "Забрани WebGL">
+<!ENTITY noscriptForbidMedia "Забрани &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Забрани Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Забрани оÑтале додатке">
+<!ENTITY noscriptReloadWarn "Ова подешавања ће бити примењена на нове или (ручно) поново учитане Ñтране">
+<!ENTITY noscriptConfirmUnblock "Тражи потврду пре привременог Ñкидања блокаде Ñа објекта">
+<!ENTITY noscriptStatusLabel "Лабела на ÑтатуÑној линији">
+<!ENTITY noscriptForbidBookmarklets "Забрани bookmarklet-е">
+<!ENTITY noscriptShowPlaceholder "Прикажи икону меÑта где Ñтоји објекат">
+<!ENTITY noscriptTruncateTitle "ОдÑеци наÑлове докумената">
+<!ENTITY noscriptFixLinks "Покушај да поправиш JavaScript везе">
+<!ENTITY noscriptAllowBookmarks "Дозволи Ñтранице отворене преко Омиљено">
+<!ENTITY noscriptAllowViaBookmarks "Дозволи Ñтранице отворене преко Омиљено">
+<!ENTITY noscriptAllowPing "Дозволи &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Дозволи локалне везе">
+<!ENTITY noscriptForbidPing "Забрани &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Забрани META редирекције унутар &lt;NOSCRIPT&gt; елемената">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "М">
+<!ENTITY noscriptWhitelist "Бела лиÑта">
+<!ENTITY noscriptPermissions "Дозволе">
+<!ENTITY noscriptRefresh "ОÑвежи">
+<!ENTITY noscriptNotifications "Обавештења">
+<!ENTITY noscriptToolbarToggle "Леви клик на NoScript дугме у линији алата укључује/иÑкључује дозволе top-level Ñтране">
+<!ENTITY noscriptTrusted "Којима Ñе верује">
+<!ENTITY noscriptUntrusted "Којима Ñе не верује">
+<!ENTITY noscriptUnknown "Ðепознато">
+<!ENTITY noscriptAdd "Додај">
+<!ENTITY noscriptAdd.accesskey "ј">
+<!ENTITY noscriptClose "Затвори">
+<!ENTITY noscriptSiteManager "Менаџер Ñтрана">
+<!ENTITY noscriptSecurityManager "Менаџер ÑигурноÑти">
+<!ENTITY noscriptPolicies "ПолиÑе">
+<!ENTITY noscriptDefaultPolicies "Подразумеване полиÑе">
+<!ENTITY noscriptSitePolicies "ПолиÑе Ñпецифичне за Ñтране">
+<!ENTITY noscriptNselNever "Сакриј &lt;NOSCRIPT&gt; елементе">
+<!ENTITY noscriptNselForce "Прикажи &lt;NOSCRIPT&gt; који Ñе налази иза блокираног &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Привремено дозволи top-level Ñтране као подразумевано">
+<!ENTITY noscriptDescription "Додатна заштита за ваш Firefox: NoScript дозвољава JavaScript, Java (и оÑтале додатке) Ñамо доменима којима Ñе верује по вашем избору (нпр. Ваша е-banking веб Ñтрана). Овај превентивни приÑтуп блокирања базиран на белој лиÑти Ñпречава иÑкоришћавање безбедноÑних пропуÑта (познатих и чак и непознатих!) без икаквог губитка функционалноÑти... ЕкÑперти ће Ñе Ñложити: Firefox је заиÑта безбеднији Ñа NoScript-ом :-)">
+<!ENTITY noscriptOptBlockCssScanners "Блокирај CSS-базиране Ñкенере">
+<!ENTITY noscriptOptFilterXGet "ОчиÑти Ñумњиве cross-site захтеве">
+<!ENTITY noscriptOptFilterXPost "Претвори cross-site POST захтеве у GET захтеве без података">
+<!ENTITY noscriptShowConsole "Прикажи конзолу...">
+<!ENTITY noscriptShowConsole.accesskey "Ñ€">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS ЧПП...">
+<!ENTITY noscriptXssFaq.accesskey "Ч">
+<!ENTITY noscriptUnsafeReload "Ðебезбедно поновно учитавање">
+<!ENTITY noscriptUnsafeReload.accesskey "б">
+<!ENTITY noscriptXssExceptions "Изузеци Anti-XSS заштите">
+<!ENTITY noscriptXssExceptions.description "Одредишта која задовољавају ове регуларне изразе ÐЕЋЕ бити заштићена од XSS">
+<!ENTITY noscriptMatchSample "Узорак шаблона за поклапање:">
+<!ENTITY noscriptReset "Врати подразумевано">
+<!ENTITY noscriptReset.accesskey "Р">
+<!ENTITY noscriptResetDef "РеÑетуј на подразумевано">
+<!ENTITY noscriptResetDef.accesskey "Ñ‚">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revoke Temporary Permissions">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "No placeholder for objects coming from sites marked as untrusted">
+<!ENTITY noscriptCollapseBlockedObjects "Collapse blocked objects">
+<!ENTITY noscriptExceptions "Exceptions...">
+<!ENTITY noscriptBlockedObjects "Blocked Objects">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Block every object coming from a site marked as untrusted">
+<!ENTITY noscriptTempAllowPage "Temporarily allow all this page">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Allow all this page">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Make page permissions permanent">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behavior">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image above to cycle beetween the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptClearClickReport "Пријави">
+<!ENTITY noscriptClearClickReport.accesskey "П">
+<!ENTITY noscriptClearClickReportId "ИД пријаве:">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Уграђени објекти">
+<!ENTITY noscriptPrev "Претходно">
+<!ENTITY noscriptNext "Даље">
+<!ENTITY noscriptFrameOptErr.title "Овај Ñадржај не може да буде приказан у оквиру">
+<!ENTITY noscriptFrameOptErr.desc "Ради заштите ваше ÑигурноÑти, објављивач ове Ñтранице не дозвољава приказивање у оквиру.">
+<!ENTITY noscriptFrameOptErr.link "Кликните овде да биÑте отворили овај Ñадржај у новом прозору">
+<!ENTITY noscriptBookmarkSync "Ðаправите резервну копију подешавања БезСкрити у забелешку ради лаког уÑклађивања">
+<!ENTITY noscriptShowReleaseNotes "Ðакон дограђивања прикажи белешку о издању">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "Ð">
+<!ENTITY ABE.rulesets.label "Правила:">
+<!ENTITY ABE.enabled.label "Укључи ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Дозволи Ñтраницама да објаве Ñвоја правила">
+<!ENTITY ABE.edit.label "Уреди...">
+<!ENTITY ABE.edit.accesskey "У">
+<!ENTITY ABE.enable.label "Укључи">
+<!ENTITY ABE.enable.accesskey "у">
+<!ENTITY ABE.disable.label "ИÑључи">
+<!ENTITY ABE.disable.accesskey "И">
+<!ENTITY ABE.refresh.label "ОÑвежи">
+<!ENTITY ABE.refresh.accesskey "О">
+<!ENTITY noscriptUninstall "ДеинÑталирај">
+<!ENTITY noscriptRecentBlocked "Ðедавно блокиране Ñтранице">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/sr-RS/noscript/noscript.properties b/extensions/noscript/chrome/locale/sr-RS/noscript/noscript.properties
new file mode 100644
index 0000000..9b73525
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sr-RS/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Дозволи Ñкрипте глобално (опаÑно)
+forbidGlobal=Забрани Ñкрипте глобално (препоручљиво)
+allowLocal=Дозволи %S
+allowTemp=Привремено дозволи %S
+forbidLocal=Забрани %S
+allowed.glb=ОпаÑноÑÑ‚! Скрипте Ñу глобално дозвољени
+allowed.yes=Скрипте Ñу тренутно дозвољени
+allowed.prt=Скрипте Ñу делимично дозвољени
+allowed.no=Скрипте Ñу тренутно забрањени
+global.warning.title=Упозорење!
+global.warning.text=Скрипте ће глобално бити дозвољене (за Ñве Ñтране).\n Ово је потенцијално опаÑна радња.\nДа ли заиÑта желите да наÑтавите?
+audio.samples=Звучни узорци
+confirm=Да ли Ñте Ñигурни?
+alwaysAsk=Увек тражи потврду
+notifyHide=Склони након %s Ñекунди
+trust=Веруј %S
+distrust=Означи %S као непроверено
+untrustedOrigin=Порекло непроверено
+xss.notify.generic=БезСкрипти је филтритао потенцијални покушај cross-site Ñкриптинга (XSS) од Ñтране %S. Технички детаљи Ñу забележени у конзолу.
+xss.notify.showConsole=Прикажи конзолу...
+xss.notify.showConsole.accessKey=к
+xss.reason.filterXGet=Очишћен Ñумњив захтев. Оригинални URL [%1$S] затражен од Ñтране [%2$S]. Очишћен URL: [%3$S].)
+xss.reason.filterXGetRef=Очишћен пошиљалац Ñумњивог захтева. URL [%1$S] је захтеван од Ñтране [%2$S]. Очишћен пошиљалац: [%3$S].)
+xss.reason.filterXPost=Очишћен Ñумњиви upload ка [%1$S] од [%2$S]: транÑформиÑано у download-only GET захтев.
+unsafeReload.warning=ÐЕБЕЗБЕДÐО поновно учитавање Ñумњивог \n\n%1$S [%2$S]\n\nОД [%3$S]\n\nNoScript ÐЕЋЕ заштитити овај захтев!\n
+metaRefresh.notify=БезСкрипти је блокирао <META> преуÑмеравање унутар <NOSCRIPT> елемента: %S за %S Ñекунди.
+metaRefresh.notify.follow=Следи преуÑмеравање
+metaRefresh.notify.follow.accessKey=л
+notify.options=Опције
+notify.options.accessKey=O
+reset.title=Врати почетна подешавања БезСкрипти
+reset.warning=СВРNoScript подешавања и дозволе за веб Ñтране ће тренутно бити враћени на подразумеване вредноÑти.\nОву акцију не можете да поништите.\nЖелите ли да наÑтавите?
+bookmarkSync.title=Забелешка за подешавање БезСкрипте
+bookmarkSync.message=Ова забелешка ÐИЈЕ предвиђена за отварање, већ за уÑклађивање коришћењем уÑлуга као што Ñу Weave или XMarks додатак.
+bookmarkSync.confirm=NoScript је пронашао забелешку Ñа подешавањима наочиглед Ñачувану у\n%S.\nДа ли желите да препишете меÑна NoScript подешавања Ñа Ñадржајем ове забелешке?
+ABE.notify=Захтев %1$S је филтрирао ABE: <%2$S> %3$S
+ABE.chooseEditor=Изаберите уређивач текÑта за обраду ABE правила
+allowFrom=Дозволи Ñве Ñа %S
+allowTempFrom=Привремено дозволи Ñве Ñа %S
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/sr/noscript/about.properties b/extensions/noscript/chrome/locale/sr/noscript/about.properties
new file mode 100644
index 0000000..cc7fa58
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sr/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Додатна заштита за фајерфокÑ. ÐоÑкрипт омогућава јаваÑкрипт, јаву и друге прикључке Ñамо за поверљиве Ñајтове. Ова бела лиÑта заÑнована је на превентивном забрањивању приÑтупа ради Ñпречавања иÑкоришћавања ÑигурноÑних рањивоÑти без губљења функционалноÑти. Стручњаци ће Ñе Ñложити – Ñ„Ð°Ñ˜ÐµÑ€Ñ„Ð¾ÐºÑ Ñ˜Ðµ безбеднији уз ноÑкрипт.
+aboutTitle=О додатку %S
+extensionContributors=ДоприноÑиоци:
+extensionContributors.tip=Људи заÑлужни за овај додатак
+extensionCreatorLabel=Ðутор:
+changelog=ÐŸÐ¾Ð¿Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½Ð°
+changelog.tip=Прикажи Ð¿Ð¾Ð¿Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½Ð°
+license=Лиценца
+license.tip=Прочитајте лиценцу крајњег кориÑника
+logo.tip=ПоÑетите Ñтраницу додатка
+sponsor.tip=ПоÑетите Ñтраницу Ñпонзора
+informaction.tip=ПоÑетите Ñтраницу Информекшен
+extensionHomepage.tip=ПоÑетите Ñтраницу додатка
+extensionCreator.tip=ПоÑетите Ñтраницу аутора
+version=Издање %S
diff --git a/extensions/noscript/chrome/locale/sr/noscript/noscript.dtd b/extensions/noscript/chrome/locale/sr/noscript/noscript.dtd
new file mode 100644
index 0000000..9fd5109
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sr/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "ПоÑтавке…">
+<!ENTITY noscriptOptions.accesskey "П">
+<!ENTITY noscriptOptionsLong "ПоÑтавке">
+<!ENTITY noscriptAbout "О додатку…">
+<!ENTITY noscriptPermissionsText "Можете изабрати којим Ñајтовима је дозвољено извршавање Ñкриптова. УнеÑите адреÑу или домен Ñајта и кликните на „Дозволи“.">
+<!ENTITY noscriptWebAddress "ÐдреÑа Ñајта:">
+<!ENTITY noscriptAllow "Дозволи">
+<!ENTITY noscriptAllow.accesskey "Д">
+<!ENTITY noscriptForbid "Забрани">
+<!ENTITY noscriptForbid.accesskey "З">
+<!ENTITY noscriptTrust "Означи као поверљиво">
+<!ENTITY noscriptTrust.accesskey "п">
+<!ENTITY noscriptUntrust "Означи као неповерљиво">
+<!ENTITY noscriptUntrust.accesskey "з">
+<!ENTITY noscriptRemoveSelected "Уклони изабране Ñајтове">
+<!ENTITY noscriptGloballyEnabled "Скриптови Ñу глобално дозвољени">
+<!ENTITY noscriptAutoReload "СамоÑтално учитај Ñтранице при измени дозвола">
+<!ENTITY noscriptGeneral "Опште">
+<!ENTITY noscriptAppearance "Изглед">
+<!ENTITY noscriptShow "Прикажи…">
+<!ENTITY noscriptCtxMenu "Приручни мени">
+<!ENTITY noscriptStatusIcon "Иконица на линији Ñтања">
+<!ENTITY noscriptFullAddr "Целе адреÑе (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Цели домени (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Домени другог нивоа (noscript.net)">
+<!ENTITY noscriptTempCmd "Привремено дозволи […]">
+<!ENTITY noscriptSound "ОбавеÑти ме звуком када Ñе Ñкриптови забране">
+<!ENTITY noscriptImport "Увези">
+<!ENTITY noscriptImport.accesskey "У">
+<!ENTITY noscriptExport "Извези">
+<!ENTITY noscriptExport.accesskey "И">
+<!ENTITY noscriptNotify "Прикажи поруку о забрањеним Ñкриптовима">
+<!ENTITY noscriptNotify.bottom "ПоÑтави поруку на дно">
+<!ENTITY noscriptSound.choose "Изабери">
+<!ENTITY noscriptSound.choose.accesskey "з">
+<!ENTITY noscriptSound.play "Репродукуј">
+<!ENTITY noscriptSound.play.accesskey "Р">
+<!ENTITY noscriptSound.reset "ПоÑтави на подразумевано">
+<!ENTITY noscriptSound.reset.accesskey "п">
+<!ENTITY noscriptAdvanced "Ðапредно">
+<!ENTITY noscriptAdditionalPermissions "Додатне дозволе за поверљиве Ñајтове">
+<!ENTITY noscriptAllowClipboard "Дозволи умножавање и убацивање текÑта из Ñпољне оÑтаве">
+<!ENTITY noscriptAdditionalRestrictions "Додатна ограничења за неповерљиве Ñајтове">
+<!ENTITY noscriptPlugins "Прикључци">
+<!ENTITY noscriptContentBlocker "Примени ова ограничења и на Ñајтове у белој лиÑти">
+<!ENTITY noscriptForbidJava "Забрани јаву">
+<!ENTITY noscriptForbidXSLT "Забрани XSLT">
+<!ENTITY noscriptForbidSilverlight "Забрани МајкроÑофт Ñилверлајт">
+<!ENTITY noscriptForbidIFrames "Забрани &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Забрани &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Забрани @font-face">
+<!ENTITY noscriptForbidWebGL "Забрани WebGL">
+<!ENTITY noscriptForbidMedia "Забрани &lt;AUDIO&gt;/&lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Забрани адоуб флеш">
+<!ENTITY noscriptForbidPlugins "Забрани оÑтале прикључке">
+<!ENTITY noscriptReloadWarn "Ове поÑтавке утицаће на нове или поновно отворене Ñтранице">
+<!ENTITY noscriptConfirmUnblock "Питај ме за потврду пре привременог деблокирања објекта">
+<!ENTITY noscriptStatusLabel "Ознака линије Ñтања">
+<!ENTITY noscriptForbidBookmarklets "Забрани маркерчиће">
+<!ENTITY noscriptShowPlaceholder "Прикажи иконицу меÑтодржача">
+<!ENTITY noscriptTruncateTitle "ОдÑеци наÑлове докумената">
+<!ENTITY noscriptFixLinks "Поправи везе јаваÑкрипте">
+<!ENTITY noscriptAllowBookmarks "Дозволи Ñајтове отворене преко забелешки">
+<!ENTITY noscriptAllowViaBookmarks "Дозволи Ñајтове отворене преко забелешки">
+<!ENTITY noscriptAllowPing "Дозволи &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Дозволи локалне везе">
+<!ENTITY noscriptForbidPing "Забрани &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Забрани мета преуÑмерења унутар елемента &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "м">
+<!ENTITY noscriptNotifyMeta "Прикажи поруку о забрањеним мета преуÑмерењима">
+<!ENTITY noscriptNotifyMeta.accesskey "Ñ€">
+<!ENTITY noscriptWhitelist "Бела лиÑта">
+<!ENTITY noscriptPermissions "Дозволе">
+<!ENTITY noscriptRefresh "ОÑвежи">
+<!ENTITY noscriptNotifications "Обавештења">
+<!ENTITY noscriptToolbarToggle "Левим кликом на алатницу ноÑкрипт мења дозволе за текући домен првог нивоа">
+<!ENTITY noscriptTrusted "Поверљиво">
+<!ENTITY noscriptUntrusted "Ðеповерљиво">
+<!ENTITY noscriptUnknown "Ðепознато">
+<!ENTITY noscriptAdd "Додај">
+<!ENTITY noscriptAdd.accesskey "Д">
+<!ENTITY noscriptClose "Затвори">
+<!ENTITY noscriptSiteManager "Управљач Ñајтовима">
+<!ENTITY noscriptSecurityManager "Управљач ÑигурноÑти">
+<!ENTITY noscriptPolicies "ПолиÑе">
+<!ENTITY noscriptDefaultPolicies "Подразумеване полиÑе">
+<!ENTITY noscriptSitePolicies "ПолиÑе одређених Ñајтова">
+<!ENTITY noscriptNselNever "Сакриј елементе &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Прикажи елемент &lt;NOSCRIPT&gt; који прати забрањен &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Привремено дозволи домене првог нивоа">
+<!ENTITY noscriptDescription "Додатна заштита за фајерфокÑ. ÐоÑкрипт омогућава јаваÑкрипт, јаву и друге прикључке Ñамо за поверљиве Ñајтове. Ова бела лиÑта заÑнована је на превентивном забрањивању приÑтупа ради Ñпречавања иÑкоришћавања ÑигурноÑних рањивоÑти без губљења функционалноÑти. Стручњаци ће Ñе Ñложити — Ñ„Ð°Ñ˜ÐµÑ€Ñ„Ð¾ÐºÑ Ñ˜Ðµ безбеднији уз ноÑкрипт.">
+<!ENTITY noscriptOptBlockCssScanners "Забрани Ñкенере заÑноване на CSS-у">
+<!ENTITY noscriptOptFilterXGet "Уклони Ñумњиве захтеве међуÑајтовне Ñкрипте">
+<!ENTITY noscriptOptFilterXPost "Пребаци међуÑајтовне POST захтеве у безподатковне GET захтеве">
+<!ENTITY noscriptShowConsole "Прикажи конзолу…">
+<!ENTITY noscriptShowConsole.accesskey "к">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS ЧПП…">
+<!ENTITY noscriptXssFaq.accesskey "Ч">
+<!ENTITY noscriptUnsafeReload "Ðебезбедно поновно учитавање">
+<!ENTITY noscriptUnsafeReload.accesskey "б">
+<!ENTITY noscriptXssExceptions "Ðнти-XSS изузеци заштите">
+<!ENTITY noscriptXssExceptions.description "Одредишта која Ñе поклапају Ñ Ñ€ÐµÐ³ÑƒÐ»Ð°Ñ€Ð½Ð¸Ð¼ изразима неће бити заштићена против XSS-а.">
+<!ENTITY noscriptMatchSample "ОбраÑци:">
+<!ENTITY noscriptReset "Поништи">
+<!ENTITY noscriptReset.accesskey "П">
+<!ENTITY noscriptResetDef "ПоÑтави на подразумевано">
+<!ENTITY noscriptResetDef.accesskey "Ñ">
+<!ENTITY noscriptOptionsWidth "40 em">
+<!ENTITY noscriptRevokeTemp "Опозови привремене дозволе">
+<!ENTITY noscriptRevokeTemp.accesskey "з">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ðиједан меÑтодржач за објекте не долази из неповерљивих Ñајтова">
+<!ENTITY noscriptCollapseBlockedObjects "Скупи забрањене објекте">
+<!ENTITY noscriptExceptions "Изузеци…">
+<!ENTITY noscriptBlockedObjects "Забрањени објекти">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Забрани Ñваки објекат који долази из неповерљивог Ñајта">
+<!ENTITY noscriptTempAllowPage "Привремено дозволи Ñве на овој Ñтраници">
+<!ENTITY noscriptTempAllowPage.accesskey "Ñ€">
+<!ENTITY noscriptAllowPage "Дозволи Ñве на овој Ñтраници">
+<!ENTITY noscriptAllowPage.accesskey "Д">
+<!ENTITY noscriptTempToPerm "Ðачини дозволе на Ñтраници као трајне">
+<!ENTITY noscriptTempToPerm.accesskey "Ð">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS ЧПП…">
+<!ENTITY noscriptHttpsFaq.accesskey "Ч">
+<!ENTITY noscriptHttps.behavior "Понашање">
+<!ENTITY noscriptHttps.cookies "Колачићи">
+<!ENTITY noscriptHttps.description "Забрани активни Ñадржај оÑим ако долази из безбедне (HTTPS) везе:">
+<!ENTITY noscriptHttps.never "Ðикада">
+<!ENTITY noscriptHttps.proxy "При коришћењу поÑредника (препоручује Ñе тор)">
+<!ENTITY noscriptHttps.always "Увек">
+<!ENTITY noscriptHttpsForced "Приморај Ñледеће Ñајтове да кориÑте безбедну (HTTPS) везу:">
+<!ENTITY noscriptHttpsForcedExceptions "Ðе приморавај коришћење безбедне (HTTPS) везе за Ñледеће Ñајтове:">
+<!ENTITY noscriptSecureCookies "Омогући Безбедно управљање колачићима">
+<!ENTITY noscriptSecureCookiesForced "Приморај шифровање за Ñве колачиће HTTPS-а за Ñледеће Ñајтове:">
+<!ENTITY noscriptSecureCookiesExceptions "Занемари небезбедне колачиће HTTPS-а за Ñледеће Ñајтове:">
+<!ENTITY noscriptClearClickTitle "Клирклик ворнинг">
+<!ENTITY noscriptClearClickHeader "Покушај кликџекинга / UI реадреÑирања!">
+<!ENTITY noscriptClearClickDescription "ÐоÑкрипт је преÑретнуо интеракцију миша или таÑтатуре Ñ Ð´ÐµÐ»Ð¸Ð¼Ð¸Ñ‡Ð½Ð¾ Ñакривеним елементом. Кликните на Ñлику иÑпод да промените између започетог и чиÑтог издања.">
+<!ENTITY noscriptClearClickOpt "Клирклик заштита на Ñтраницама…">
+<!ENTITY noscriptClearClickReport "Пријави">
+<!ENTITY noscriptClearClickReport.accesskey "П">
+<!ENTITY noscriptClearClickReportId "ID пријаве:">
+<!ENTITY noscriptTrustedPagesAdj "поверљиво">
+<!ENTITY noscriptUntrustedPagesAdj "неповерљиво">
+<!ENTITY noscriptKeepLocked "Задржи овај елемент закључаним (препоручено)">
+<!ENTITY noscriptEmbeddings "Уграђивања">
+<!ENTITY noscriptPrev "Претходно">
+<!ENTITY noscriptNext "Следеће">
+<!ENTITY noscriptFrameOptErr.title "Овај Ñадржај не може бити приказан у оквиру">
+<!ENTITY noscriptFrameOptErr.desc "Да би Ð²Ð°Ñ Ð·Ð°Ð´Ñ€Ð¶Ð°Ð¾/ла безбедним, издавач овог Ñадржаја не дозвољава његово приказивање у оквиру.">
+<!ENTITY noscriptFrameOptErr.link "Кликните овде да отворите Ñадржај у новом прозору">
+<!ENTITY noscriptBookmarkSync "Ðаправи резервни примерак подешавања у забелешци ради лакшег уÑклађивања">
+<!ENTITY noscriptShowReleaseNotes "Прикажи белешке издавача при доградњи">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Скупови правила:">
+<!ENTITY ABE.enabled.label "Омогући ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Дозволи Ñајтовима да поÑтаве Ñвој Ñкуп правила">
+<!ENTITY ABE.edit.label "Уреди…">
+<!ENTITY ABE.edit.accesskey "У">
+<!ENTITY ABE.enable.label "Омогући">
+<!ENTITY ABE.enable.accesskey "м">
+<!ENTITY ABE.disable.label "Онемогући">
+<!ENTITY ABE.disable.accesskey "н">
+<!ENTITY ABE.refresh.label "ОÑвежи">
+<!ENTITY ABE.refresh.accesskey "О">
+<!ENTITY noscriptUninstall "Уклони">
+<!ENTITY noscriptRecentBlocked "Забрањени Ñајтови">
+<!ENTITY noscriptExternalFilters "Спољни филтери">
+<!ENTITY noscriptEF.enable "Омогући Ñпољне филтере">
+<!ENTITY noscriptEF.add "Ðови филтер…">
+<!ENTITY noscriptEF.executable "Извршна датотека:">
+<!ENTITY noscriptEF.browse "Потражи…">
+<!ENTITY noscriptEF.contentType "Ð’Ñ€Ñта Ñадржаја (MIME) за филтрирање (подударање или регуларни израз):">
+<!ENTITY noscriptEF.exceptions "Ðе филтрирај објекте који долази Ñ Ð¾Ð²Ð¸Ñ… Ñајтова:">
+<!ENTITY noscriptEF.remove "Уклони">
+<!ENTITY noscriptPreset "Ðиво безбедноÑти">
+<!ENTITY noscriptPreset.off "ИÑкључено">
+<!ENTITY noscriptPreset.low "ЈедноÑтавно (црна лиÑта и веб безбедноÑÑ‚)">
+<!ENTITY noscriptPreset.medium "КлаÑично (бела лиÑта и веб безбедноÑÑ‚)">
+<!ENTITY noscriptPreset.high "Тврђава (пуно закључавање)">
+<!ENTITY noscript.hoverUI "Отвори мени за дозволе при прелаÑку мишем преко иконице ноÑкрипта">
+<!ENTITY noscriptDonate "Донирај">
+<!ENTITY noscriptDonate.accesskey "Д">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/sr/noscript/noscript.properties b/extensions/noscript/chrome/locale/sr/noscript/noscript.properties
new file mode 100644
index 0000000..7bf23ec
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sr/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Дозволи Ñкриптове глобално
+forbidGlobal=Забрани Ñкриптове глобално
+allowLocal=Дозволи %S
+allowTemp=Привремено дозволи %S
+forbidLocal=Забрани %S
+allowed.glb=Упозорење! Скриптови Ñу дозвољени глобално
+allowed.yes=Скриптови Ñу тренутно дозвољени
+allowed.prt=Скриптови Ñу делимично дозвољени
+allowed.no=Скриптови Ñу тренутно забрањени
+global.warning.title=Упозорење!
+global.warning.text=Скриптови ће бити дозвољени глобално (за Ñваки Ñајт).\nОва радња може бити опаÑна. Желите ли да наÑтавите?
+audio.samples=Звучни примерци
+confirm=ЈеÑте ли Ñигурни?
+alwaysAsk=Увек ме питај за потврду
+notifyHide=Сакриј поÑле %S Ñекунде/и
+trust=Означи %S као поверљиво
+distrust=Означи %S као неповерљиво
+untrustedOrigin=неповерљив извор
+xss.notify.generic=ÐоÑкрипт је филтрирао покушај међуÑајтовног Ñкриптовања (XSS) из %S. Технички детаљи Ñу забележени у конзоли.
+xss.notify.showConsole=Прикажи конзолу…
+xss.notify.showConsole.accessKey=к
+xss.reason.filterXGet=Саниран је Ñумњив захтев. Изворна адреÑа [%1$S] је затражена из [%2$S]. Санирана адреÑа: [%3$S].
+xss.reason.filterXGetRef=Саниран је Ñумњив упућивач захтева. ÐдреÑа [%1$S] је затражена из [%2$S]. Саниран упућивач: [%3$S].
+xss.reason.filterXPost=Санирано је Ñумњиво Ñлање на [%1$S] из [%2$S]: претворено у GET захтев доÑтупан Ñамо за преузимање.
+unsafeReload.warning=Ðебезбедно учитавање Ñумњивих\n\n%1$S [%2$S]\n\nFROM [%3$S]\n\nÐоÑкрипт неће заштитити овај захтев!\n
+metaRefresh.notify=ÐоÑкрипт је блокирао преуÑмерење <META> унутар елемента <NOSCRIPT>: %S у %S Ñекунде/и.
+metaRefresh.notify.follow=Прати преуÑмерење
+metaRefresh.notify.follow.accessKey=П
+notify.options=ПоÑтавке
+notify.options.accessKey=Ñ
+reset.title=Поништавање
+reset.warning=Сва подешавања додатка и дозволе Ñајтова биће поништени на подразумеване вредноÑти.\nОва радња Ñе не може вратити.\nЖелите ли да наÑтавите?
+bookmarkSync.title=Забелешка подешавања
+bookmarkSync.message=Ова забелешка није намењена за отварање, већ за уÑклађивање кориÑтећи додатке као што Ñу Weave или XMarks.
+bookmarkSync.confirm=ÐоÑкрипт је пронашао забелешку подешавања која је Ñачувана у\n%S.\nЖелите ли да замените текуће поÑтавке Ñа поÑтавкама из забелешке?
+ABE.notify=Затражи %1$S филтрирано од ABE: <%2$S> %3$S
+ABE.chooseEditor=Изаберите уређивач текÑта за Ñкуп правила ABE
+ABE.syntaxError=СинтакÑна грешка у Ñкупу правила ABE!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Дозволи Ñве Ñа %S
+allowTempFrom=Привремено дозволи Ñве Ñа %S
+siteInfo.confirm=Управо ћете питати за податке о Ñајту „%1$S“\nÑлањем упита на %2$S.\nЖелите ли да наÑтавите?
+siteInfo.tooltip=ПритиÑните Ñредњи клик или шифт и клик за податке о Ñтраници…
+ef.activate=Филтер %S
+ef.options=%S поÑтавке…
+ef.newName=УнеÑите назив новог филтера:
+ef.locateExe=Изаберите извршну датотеку за филтер %S
+disable=Онемогући %S
+disable.accessKey=О
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/sv-SE/noscript/about.properties b/extensions/noscript/chrome/locale/sv-SE/noscript/about.properties
new file mode 100644
index 0000000..c4d0cb1
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sv-SE/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Extra skydd för Firefox: NoScript tillåter JavaScript, Java (och andra tillägg) endast för betrodda domäner du valt (t ex din internetbank). Denna vitlistebaserade förebyggande blockering förhindrar uttnyttjande av säkerhetsproblem (både kända och okända) utan förlust av funktionalitet... Experter är överens: Firefox är verkligen säkrare med NoScript :-)
+aboutTitle=Om %S
+extensionContributors=Medverkande:
+extensionContributors.tip=Tack till:
+extensionCreatorLabel=Författare:
+changelog=Förändringslogg:
+changelog.tip=Visa förändringslogg:
+license=Licens
+license.tip=Läs slutanvändarlicens
+logo.tip=Besök tilläggets webbplats
+sponsor.tip=Besök sponsorns webbplats
+informaction.tip=Besök InformActions webbplats
+extensionHomepage.tip=Besök tilläggets webbplats
+extensionCreator.tip=Besök författarens webbplats
+version=Version %S
diff --git a/extensions/noscript/chrome/locale/sv-SE/noscript/noscript.dtd b/extensions/noscript/chrome/locale/sv-SE/noscript/noscript.dtd
new file mode 100644
index 0000000..94a0cde
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sv-SE/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Alternativ...">
+<!ENTITY noscriptOptions.accesskey "A">
+<!ENTITY noscriptOptionsLong "NoScript-alternativ">
+<!ENTITY noscriptAbout "Om NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Ange vilka webbplatser som får köra skript. Skriv webbadressen eller domänen (t ex. &quot;http://www.webbplats.se&quot; eller &quot;webbplats.se&quot;) för den webbplats där skript ska tillåtas. Klicka sedan på &quot;Tillåt&quot;.">
+<!ENTITY noscriptWebAddress "Sidans adress:">
+<!ENTITY noscriptAllow "Tillåt">
+<!ENTITY noscriptAllow.accesskey "T">
+<!ENTITY noscriptForbid "Förbjud">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Markera som betrodd">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Markera som ej betrodd">
+<!ENTITY noscriptUntrust.accesskey "F">
+<!ENTITY noscriptRemoveSelected "Ta bort markerade platser">
+<!ENTITY noscriptGloballyEnabled "Skript är tillåtna globalt (farligt)">
+<!ENTITY noscriptAutoReload "Uppdatera berörda webbsidor när skripttillstånd ändras">
+<!ENTITY noscriptGeneral "Allmänt">
+<!ENTITY noscriptAppearance "Utseende">
+<!ENTITY noscriptShow "Visa...">
+<!ENTITY noscriptCtxMenu "Snabbmeny">
+<!ENTITY noscriptStatusIcon "Statusfältsikon">
+<!ENTITY noscriptFullAddr "Hela adresser (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Hela domäner (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Andranivå-domäner (noscript.net)">
+<!ENTITY noscriptTempCmd "Tillåt tillfälligt [...]">
+<!ENTITY noscriptSound "Spela upp ljud när skript blockeras">
+<!ENTITY noscriptImport "Importera">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Exportera">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Visa meddelande om blockerade skript">
+<!ENTITY noscriptNotify.bottom "Placera nya meddelande längst ned">
+<!ENTITY noscriptSound.choose "Välj">
+<!ENTITY noscriptSound.choose.accesskey "V">
+<!ENTITY noscriptSound.play "Spela">
+<!ENTITY noscriptSound.play.accesskey "S">
+<!ENTITY noscriptSound.reset "Återställ standard">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Avancerat">
+<!ENTITY noscriptAdditionalPermissions "Ytterligare tillstånd för betrodda webbplatser">
+<!ENTITY noscriptAllowClipboard "Tillåt klipp ut och kopiera från externt urklipp">
+<!ENTITY noscriptAdditionalRestrictions "Ytterliga restriktioner för ej betrodda webbplatser">
+<!ENTITY noscriptPlugins "Tillägg">
+<!ENTITY noscriptContentBlocker "Använd begränsingarna på betrodda platser också">
+<!ENTITY noscriptForbidJava "Förbjud Java™">
+<!ENTITY noscriptForbidXSLT "Förbjud XSLT">
+<!ENTITY noscriptForbidSilverlight "Förbjud Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Förbjud &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Förbjud &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Förbjud @font-face">
+<!ENTITY noscriptForbidWebGL "Förbjud WebGL">
+<!ENTITY noscriptForbidMedia "Förbjud &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Förbjud Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Förbjud andra tillägg">
+<!ENTITY noscriptReloadWarn "Dessa alternativ kommer att börja gälla för nya eller (manuellt) uppdaterade webbsidor">
+<!ENTITY noscriptConfirmUnblock "Fråga innan temporär avblockering av ett objekt sker">
+<!ENTITY noscriptStatusLabel "Statusfältsetikett">
+<!ENTITY noscriptForbidBookmarklets "Förbjud bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Visa platshållarikon">
+<!ENTITY noscriptTruncateTitle "Korta av dokumenttitlar">
+<!ENTITY noscriptFixLinks "Försök reparera JavaSkript-länkar">
+<!ENTITY noscriptAllowBookmarks "Tillåt webbplatser som öppnas från bokmärken">
+<!ENTITY noscriptAllowViaBookmarks "Tillåt webbplatser som öppnas från bokmärken">
+<!ENTITY noscriptAllowPing "Tillåt &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Tillåt lokala länkar">
+<!ENTITY noscriptForbidPing "Förbjud &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Förbjud META omdirigering inuti &lt;NOSCRIPT&gt; element">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "F">
+<!ENTITY noscriptWhitelist "Vitlista">
+<!ENTITY noscriptPermissions "Behörigheter">
+<!ENTITY noscriptRefresh "Uppdatera">
+<!ENTITY noscriptNotifications "Notifieringar">
+<!ENTITY noscriptToolbarToggle "Vänsterklicka på NoScripts verktygsknapp för att ändra behörighet för aktuell webbsida">
+<!ENTITY noscriptTrusted "Betrodd">
+<!ENTITY noscriptUntrusted "Ej betrodd">
+<!ENTITY noscriptUnknown "Okänd">
+<!ENTITY noscriptAdd "Lägg till">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Stäng">
+<!ENTITY noscriptSiteManager "Platshanterare">
+<!ENTITY noscriptSecurityManager "Säkerhetshanterare">
+<!ENTITY noscriptPolicies "Riktlinjer">
+<!ENTITY noscriptDefaultPolicies "Standardriktlinjer">
+<!ENTITY noscriptSitePolicies "Platsspecifika riktlinjer">
+<!ENTITY noscriptNselNever "Dölj &lt;NOSCRIPT&gt; element">
+<!ENTITY noscriptNselForce "Visa &lt;NOSCRIPT&gt; element som följer ett blockerat &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Tillåt top-nivå platser tillfälligt">
+<!ENTITY noscriptDescription "Extra skydd för Firefox: NoScript tillåter JavaScript, Java (och andra tillägg) endast för betrodda domäner du valt (t ex din internetbank). Denna vitlistebaserade förebyggande blockering förhindrar uttnyttjande av säkerhetsproblem (både kända och okända) utan förlust av funktionalitet... Experter är överens: Firefox är verkligen säkrare med NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Blockera CSS-baserade scanners">
+<!ENTITY noscriptOptFilterXGet "Tvätta misstänkta XSS förfrågningar">
+<!ENTITY noscriptOptFilterXPost "Ändra XSS POST förfrågningar till datalösa GET förfrågningar">
+<!ENTITY noscriptShowConsole "Visa konsoll...">
+<!ENTITY noscriptShowConsole.accesskey "K">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Osäker omladdning">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Anti-XSS undantag">
+<!ENTITY noscriptXssExceptions.description "Destinationer som matchar dessa reguljära uttryck kommer INTE att skyddas mot XSS.">
+<!ENTITY noscriptMatchSample "Exempel på mönster:">
+<!ENTITY noscriptReset "Reset">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "Återställ till standard">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Återkalla temporära tillstånd">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "Visa inte platshållare för objekt från ej betrodda platser">
+<!ENTITY noscriptCollapseBlockedObjects "Minimera blockerade objekt">
+<!ENTITY noscriptExceptions "Undantag...">
+<!ENTITY noscriptBlockedObjects "Blockerade objekt">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Blockera alla objekt från ej betrodda platser">
+<!ENTITY noscriptTempAllowPage "Tillåt denna sida tillfälligt">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Tillåt allt på denna sida">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Spara sidtillstånd permanent">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ...">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Beteende">
+<!ENTITY noscriptHttps.cookies "Kakor">
+<!ENTITY noscriptHttps.description "Förbjud aktivt innehåll utom om det kommer från en säker (HTTPS) anslutning:">
+<!ENTITY noscriptHttps.never "Aldrig">
+<!ENTITY noscriptHttps.proxy "Vid användande av proxy (rekommenderas för Tor)">
+<!ENTITY noscriptHttps.always "Alltid">
+<!ENTITY noscriptHttpsForced "Tvinga dessa platser att använda säkra anslutningar (HTTPS):">
+<!ENTITY noscriptHttpsForcedExceptions "Tvinga aldrig dessa platser att använda säkra anslutningar (HTTPS):">
+<!ENTITY noscriptSecureCookies "Aktivera automatisk säker hantering av kakor">
+<!ENTITY noscriptSecureCookiesForced "Tvinga kryptering för alla kakor över HTTPS för dessa platser:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignorera osäkra kakor som skickas över HTTPS för dessa platser:">
+<!ENTITY noscriptClearClickTitle "ClearClick varning">
+<!ENTITY noscriptClearClickHeader "Potentiell Clickjacking /UI redressing försök!">
+<!ENTITY noscriptClearClickDescription "NoScript fångade upp musklick eller tangentbordsklick med ett delvis dolt element. Klicka på bilden ovan för att växla mellan dold och klartext version.">
+<!ENTITY noscriptClearClickOpt "ClearClick skydd på sidor...">
+<!ENTITY noscriptClearClickReport "Rapport">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Rapport ID:">
+<!ENTITY noscriptTrustedPagesAdj "betrodd">
+<!ENTITY noscriptUntrustedPagesAdj "ej betrodd">
+<!ENTITY noscriptKeepLocked "LÃ¥s detta element permanent (rekommenderas)">
+<!ENTITY noscriptEmbeddings "Inbäddade objekt">
+<!ENTITY noscriptPrev "Föregående">
+<!ENTITY noscriptNext "Nästa">
+<!ENTITY noscriptFrameOptErr.title "Innehållet kan inte visas i en ram">
+<!ENTITY noscriptFrameOptErr.desc "För att skydda dig, tillåter utgivaren att innehållet visas i en ram.">
+<!ENTITY noscriptFrameOptErr.link "Klicka här för att öppna innehållet i ett nytt fönster">
+<!ENTITY noscriptBookmarkSync "Spara NoScript konfigurationen i ett bokmärke för enkel synkronisering">
+<!ENTITY noscriptShowReleaseNotes "Visa nyheter vid uppdatering">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Regler:">
+<!ENTITY ABE.enabled.label "Aktivera ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Tillåt platser att använda sina egna regler">
+<!ENTITY ABE.edit.label "Redigera...">
+<!ENTITY ABE.edit.accesskey "W">
+<!ENTITY ABE.enable.label "Aktivera">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Inaktivera">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Uppdatera">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Avinstallera">
+<!ENTITY noscriptRecentBlocked "Nyligen blockerade platser">
+<!ENTITY noscriptNotifyMeta "Visa meddelande om blockerade META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptExternalFilters "Externa filter">
+<!ENTITY noscriptEF.enable "Aktivera externa filter">
+<!ENTITY noscriptEF.add "Nytt filter ...">
+<!ENTITY noscriptEF.executable "Körbar fil:">
+<!ENTITY noscriptEF.browse "Bläddra ...">
+<!ENTITY noscriptEF.contentType "Innehållstyp (MIME) som skall filtreras (exakt eller reguljärt uttryck):">
+<!ENTITY noscriptEF.exceptions "Filtrera inte objekt som kommer från dessa platser:">
+<!ENTITY noscriptEF.remove "Ta bort">
+<!ENTITY noscriptPreset "Skyddsnivå">
+<!ENTITY noscriptPreset.off "Av (är du seriös?!)">
+<!ENTITY noscriptPreset.low "Lättsam (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Klassisk (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Öppna behörighetsmenyn när muspekaren är över NoScript ikon">
+<!ENTITY noscriptDonate "Donera">
+<!ENTITY noscriptDonate.accesskey "O">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/sv-SE/noscript/noscript.properties b/extensions/noscript/chrome/locale/sv-SE/noscript/noscript.properties
new file mode 100644
index 0000000..25670d6
--- /dev/null
+++ b/extensions/noscript/chrome/locale/sv-SE/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Tillåt skript globalt (farligt)
+forbidGlobal=Förbjud skript globalt (rekommenderas)
+allowLocal=Tillåt %S
+allowTemp=Tillåt tillfälligt %S
+forbidLocal=Förbjud %S
+allowed.glb=Fara! Skript tillåtna globalt
+allowed.yes=För närvarande tillåtna skript
+allowed.prt=Delvis tillåtna skript
+allowed.no=För närvarande förbjudna skript
+global.warning.title=Varning!
+global.warning.text=Skript kommer att tillåtas globalt (för alla webbplatser)\n Detta kan vara farligt. \n Vill du fortsätta?
+audio.samples=Ljudprover
+confirm=Är du säker?
+alwaysAsk=Fråga alltid
+notifyHide=Dölj efter %S sekunder
+trust=Trust %S
+distrust=Markera %S som ej betrodd
+untrustedOrigin=ursprung ej betrodd
+xss.notify.generic=NoScript filtrerade bort ett potentiellt XSS försök från %S. Tekniska detaljer kan läsas i konsollen.
+xss.notify.showConsole=Visa konsoll...
+xss.notify.showConsole.accessKey=K
+xss.reason.filterXGet=Tvättade misstänkta förfrågningar. Original URL [%1$S] begärd från [%2$S]. Tvättad URL: [%3$S].)
+xss.reason.filterXGetRef=Tvättade misstänkt förfrågningsursprung. URL [%1$S] begärd från [%2$S]. Tvättat ursprung: [%3$S].)
+xss.reason.filterXPost=Rensade misstänkt uppladdning till [%1$S] från [%2$S]: transformerad till en GET förfrågan för nerladdning.
+unsafeReload.warning=OSÄKER omladdning av misstänkt\n\n%1$S [%2$S]\n\nFRÅN [%3$S]\n\nNoScript kommer INTE att skydda denna förfrågan!\n
+metaRefresh.notify=NoScript blockerade en <META> omdirigering inuti ett <NOSCRIPT> element: %S i %S sekunder.
+metaRefresh.notify.follow=Följ omdirigering
+metaRefresh.notify.follow.accessKey=F
+notify.options=Inställningar
+notify.options.accessKey=I
+reset.title=Återställ NoScript
+reset.warning=ALLA NoScript inställningar och tillstånd kommer att återställas till sina standardvärden omedelbart.\nDetta kan inte ångras.\nVill du fortsätta?
+bookmarkSync.title=NoScript konfigurationsbokmärke
+bookmarkSync.message=Bokmärket skall INTE öppnas i ett fönster utan skall användas för synkronisering via tjänster som Weave eller XMarks.
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark\'s content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+allowFrom=Tillåt allt från %S
+allowTempFrom=Tillåt allt från %S tillfälligt
+ABE.syntaxError=Syntaxfel i ABE regeluppsättning!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOKALA
+siteInfo.confirm=Du är på väg att be om information om platsen \"%1$S\"\n genom att skicka en förfrågan till %2$S.\nVill du fortsätta?
+siteInfo.tooltip=Mellanklicka eller shift + klicka för Site Info ...
+ef.activate=Filter %S
+ef.options=%S alternativ ...
+ef.newName=Skriv in namnet på det nya filtret:
+ef.locateExe=Välj den körbara filen för %S filtret
+disable=Inaktivera %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/te-IN/noscript/about.properties b/extensions/noscript/chrome/locale/te-IN/noscript/about.properties
new file mode 100644
index 0000000..9aa6835
--- /dev/null
+++ b/extensions/noscript/chrome/locale/te-IN/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality… Experts will agree: Firefox is really safer with NoScript :-)
+aboutTitle=About %S
+extensionContributors=Contributors:
+extensionContributors.tip=People you should thank for this extension
+extensionCreatorLabel=Author:
+changelog=Changelog
+changelog.tip=Show changelog
+license=License
+license.tip=Read end-user license
+logo.tip=Visit extension home page
+sponsor.tip=Visit sponsor home page
+informaction.tip=Visit InformAction home page
+extensionHomepage.tip=Visit extension home page
+extensionCreator.tip=Visit author home page
+version=Version %S
diff --git a/extensions/noscript/chrome/locale/te-IN/noscript/noscript.dtd b/extensions/noscript/chrome/locale/te-IN/noscript/noscript.dtd
new file mode 100644
index 0000000..c0ab05e
--- /dev/null
+++ b/extensions/noscript/chrome/locale/te-IN/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Options…">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript Options">
+<!ENTITY noscriptAbout "About NoScript 5.1.8.5…">
+<!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. &quot;http://www.site.com&quot; or &quot;site.com&quot;) of the site you want to allow and then click Allow.">
+<!ENTITY noscriptWebAddress "Address of web site:">
+<!ENTITY noscriptAllow "Allow">
+<!ENTITY noscriptAllow.accesskey "l">
+<!ENTITY noscriptForbid "Forbid">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "Mark as Trusted">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Mark as Untrusted">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "Remove Selected Sites">
+<!ENTITY noscriptGloballyEnabled "Scripts Globally Allowed (dangerous)">
+<!ENTITY noscriptAutoReload "Automatically reload affected pages when permissions change">
+<!ENTITY noscriptGeneral "General">
+<!ENTITY noscriptAppearance "Appearance">
+<!ENTITY noscriptShow "Show…">
+<!ENTITY noscriptCtxMenu "Contextual menu">
+<!ENTITY noscriptStatusIcon "Status bar icon">
+<!ENTITY noscriptFullAddr "Full Addresses (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Full Domains (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Base 2nd level Domains (noscript.net)">
+<!ENTITY noscriptTempCmd "Temporarily allow […]">
+<!ENTITY noscriptSound "Audio feedback when scripts are blocked">
+<!ENTITY noscriptImport "Import">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "Export">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "Show message about blocked scripts">
+<!ENTITY noscriptNotify.bottom "Place message at the bottom">
+<!ENTITY noscriptSound.choose "Choose">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Play">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Reset default">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "Advanced">
+<!ENTITY noscriptAdditionalPermissions "Additional permissions for trusted sites">
+<!ENTITY noscriptAllowClipboard "Allow rich text copy and paste from external clipboard">
+<!ENTITY noscriptAdditionalRestrictions "Additional restrictions for untrusted sites">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Apply these restrictions to trusted sites too">
+<!ENTITY noscriptForbidJava "Forbid Javaâ„¢">
+<!ENTITY noscriptForbidSilverlight "Forbid Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Forbid &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Forbid &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Forbid @font-face">
+<!ENTITY noscriptForbidWebGL "Forbid WebGL">
+<!ENTITY noscriptForbidMedia "Forbid &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Forbid Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "Forbid other plugins">
+<!ENTITY noscriptReloadWarn "These options will take effect on new or (manually) reloaded pages">
+<!ENTITY noscriptConfirmUnblock "Ask for confirmation before temporarily unblocking an object">
+<!ENTITY noscriptStatusLabel "Status bar label">
+<!ENTITY noscriptForbidBookmarklets "Forbid bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Show placeholder icon">
+<!ENTITY noscriptTruncateTitle "Truncate document titles">
+<!ENTITY noscriptFixLinks "Attempt to fix JavaScript links">
+<!ENTITY noscriptAllowBookmarks "Allow sites opened through bookmarks">
+<!ENTITY noscriptAllowViaBookmarks "Allow sites opened through bookmarks">
+<!ENTITY noscriptAllowPing "Allow &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Allow local links">
+<!ENTITY noscriptForbidPing "Forbid &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Forbid META redirections inside &lt;NOSCRIPT&gt; elements">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptWhitelist "Whitelist">
+<!ENTITY noscriptPermissions "Permissions">
+<!ENTITY noscriptRefresh "Refresh">
+<!ENTITY noscriptNotifications "Notifications">
+<!ENTITY noscriptToolbarToggle "Left clicking on NoScript toolbar button toggles permissions for current top-level site">
+<!ENTITY noscriptTrusted "Trusted">
+<!ENTITY noscriptUntrusted "Untrusted">
+<!ENTITY noscriptUnknown "Unknown">
+<!ENTITY noscriptAdd "Add">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "Close">
+<!ENTITY noscriptSiteManager "Site Manager">
+<!ENTITY noscriptSecurityManager "Security Manager">
+<!ENTITY noscriptPolicies "Policies">
+<!ENTITY noscriptDefaultPolicies "Default Policies">
+<!ENTITY noscriptSitePolicies "Site Specific Policies">
+<!ENTITY noscriptNselNever "Hide &lt;NOSCRIPT&gt; elements">
+<!ENTITY noscriptNselForce "Show the &lt;NOSCRIPT&gt; element which follows a blocked &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "Temporarily allow top-level sites by default">
+<!ENTITY noscriptDescription "Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality… Experts will agree: Firefox is really safer with NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Block CSS-based scanners">
+<!ENTITY noscriptOptFilterXGet "Sanitize cross-site suspicious requests">
+<!ENTITY noscriptOptFilterXPost "Turn cross-site POST requests into data-less GET requests">
+<!ENTITY noscriptShowConsole "Show Console…">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ…">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Unsafe Reload">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Anti-XSS Protection Exceptions">
+<!ENTITY noscriptXssExceptions.description "Destinations matching these regular expressions will NOT be protected against XSS.">
+<!ENTITY noscriptMatchSample "Pattern matching sample:">
+<!ENTITY noscriptReset "Reset">
+<!ENTITY noscriptReset.accesskey "s">
+<!ENTITY noscriptResetDef "Reset to defaults">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revoke Temporary Permissions">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "No placeholder for objects coming from sites marked as untrusted">
+<!ENTITY noscriptCollapseBlockedObjects "Collapse blocked objects">
+<!ENTITY noscriptExceptions "Exceptions…">
+<!ENTITY noscriptBlockedObjects "Blocked Objects">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Block every object coming from a site marked as untrusted">
+<!ENTITY noscriptTempAllowPage "Temporarily allow all this page">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "Allow all this page">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Make page permissions permanent">
+<!ENTITY noscriptTempToPerm.accesskey "M">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behavior">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image below to cycle between the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Embedded Objects">
+<!ENTITY noscriptPrev "Previuous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptForbidXSLT "Forbid XSLT">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/te-IN/noscript/noscript.properties b/extensions/noscript/chrome/locale/te-IN/noscript/noscript.properties
new file mode 100644
index 0000000..35e928f
--- /dev/null
+++ b/extensions/noscript/chrome/locale/te-IN/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Allow Scripts Globally (dangerous)
+forbidGlobal=Forbid Scripts Globally (advised)
+allowLocal=Allow %S
+allowTemp=Temporarily allow %S
+forbidLocal=Forbid %S
+allowed.glb=Danger! Scripts Globally Allowed
+allowed.yes=Scripts Currently Allowed
+allowed.prt=Scripts Partially Allowed
+allowed.no=Scripts Currently Forbidden
+global.warning.title=Warning!
+global.warning.text=Scripts are going to be allowed globally (for every site).\nThis is a potentially dangerous action.\nDo you really want to proceed?
+audio.samples=Audio samples
+confirm=Are you sure?
+alwaysAsk=Always ask for confirmation
+notifyHide=Hide after %S seconds
+trust=Trust %S
+distrust=Mark %S as Untrusted
+untrustedOrigin=an untrusted origin
+xss.notify.generic=NoScript filtered a potential cross-site scripting (XSS) attempt from %S. Technical details have been logged to the Console.
+xss.notify.showConsole=Show Console…
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=Sanitized suspicious request. Original URL [%1$S] requested from [%2$S]. Sanitized URL: [%3$S].
+xss.reason.filterXGetRef=Sanitized suspicious request referer. URL [%1$S] requested from [%2$S]. Sanitized Referrer: [%3$S].
+xss.reason.filterXPost=Sanitized suspicious upload to [%1$S] from [%2$S]: transformed into a download-only GET request.
+unsafeReload.warning=UNSAFELY reloading a suspicious\n\n%1$S [%2$S]\n\nFROM [%3$S]\n\nNoScript will NOT protect this request!\n
+metaRefresh.notify=NoScript blocked a <META> redirection inside a <NOSCRIPT> element: %S in %S seconds.
+metaRefresh.notify.follow=Follow Redirection
+metaRefresh.notify.follow.accessKey=F
+notify.options=Options
+notify.options.accessKey=O
+reset.title=NoScript Reset
+reset.warning=ALL the NoScript preferences and site permissions will be reset to their default values immediately.\nThis action cannot be reverted.\nDo you want to continue?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark\'s content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You\'re about to ask for information about the \"%1$S\" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/th/noscript/about.properties b/extensions/noscript/chrome/locale/th/noscript/about.properties
new file mode 100644
index 0000000..30aef49
--- /dev/null
+++ b/extensions/noscript/chrome/locale/th/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=à¸à¸²à¸£à¸›à¹‰à¸­à¸‡à¸à¸±à¸™à¸žà¸´à¹€à¸¨à¸©à¸ªà¸³à¸«à¸£à¸±à¸šà¹„ฟร์ฟอà¸à¸‹à¹Œà¸‚องคุณ: NoScript ยอมรับจาวาสคริปต์à¹à¸¥à¸°à¸ˆà¸²à¸§à¸²(à¹à¸¥à¸°à¸•à¸±à¸§à¹€à¸ªà¸£à¸´à¸¡à¸­à¸·à¹ˆà¸™à¹†)เฉพาะโดเมนที่คุณเลือà¸(เช่น เว็บไซต์ธุรà¸à¸´à¸ˆà¸ªà¹ˆà¸§à¸™à¸•à¸±à¸§à¸‚องคุณ) บัà¸à¸Šà¸µà¸‚าวนี้บล็อà¸à¸à¸²à¸£à¹à¸ªà¸§à¸‡à¸«à¸²à¸œà¸¥à¸›à¸£à¸°à¹‚ยชน์ที่คืบคลานเข้ามาà¸à¹ˆà¸­à¸™à¸‚องความปลอดภัยที่ไม่มั่นคง(ระบุà¹à¸¥à¸°à¹„ม่ระบุ)ด้วยคุณประโยชน์...ผู้ใช้ระดับสูงจะเข้าใจ: ไฟร์ฟอà¸à¸‹à¹Œà¸ˆà¸°à¸›à¸¥à¸­à¸”ภัยขึ้นด้วยโนสคริปต์ :-)
+aboutTitle=เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š %S
+extensionContributors=ผู้สนับสนุน:
+extensionContributors.tip=คนที่คุณควรขอบคุณสำหรับส่วนขยายนี้
+extensionCreatorLabel=ผู้จัดทำ:
+changelog=บันทึà¸à¸„วามเปลี่ยนà¹à¸›à¸¥à¸‡
+changelog.tip=à¹à¸ªà¸”งบันทึà¸à¸„วามเปลี่ยนà¹à¸›à¸¥à¸‡
+license=ลิขสิทธิ์
+license.tip=อ่านลิขสิทธิ์ผู้ใช้ขั้นปลาย
+logo.tip=เยี่ยมชมโฮมเพจส่วนขยาย
+sponsor.tip=เยี่ยมชมโฮมเพจผู้อุปถัมภ์
+informaction.tip=เยี่ยมชมโฮมเพจ InformAction
+extensionHomepage.tip=เยี่ยมชมโฮมเพจส่วนขยาย
+extensionCreator.tip=เยี่ยมชมโฮมเพจผู้จัดทำ
+version=รุ่น %S
diff --git a/extensions/noscript/chrome/locale/th/noscript/noscript.dtd b/extensions/noscript/chrome/locale/th/noscript/noscript.dtd
new file mode 100644
index 0000000..383ae0f
--- /dev/null
+++ b/extensions/noscript/chrome/locale/th/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "ตัวเลือà¸...">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "ตัวเลือภNoScript">
+<!ENTITY noscriptAbout "เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "คุณสามารถà¸à¸³à¸«à¸™à¸”เว็บไซต์ที่จะอนุà¸à¸²à¸•à¸”ำเนินà¸à¸²à¸£à¸ªà¸„ริปต์ พิมพ์ที่อยู่หรือโดเมน (เช่น &quot;http://www.site.com&quot; หรือ &quot;site.com&quot;) ของไซต์ที่คุณต้องà¸à¸²à¸£à¸­à¸™à¸¸à¸à¸²à¸•à¹à¸¥à¸°à¸„ลิà¸à¸­à¸™à¸¸à¸à¸²à¸•">
+<!ENTITY noscriptWebAddress "ที่อยู่เว็บไซต์:">
+<!ENTITY noscriptAllow "อนุà¸à¸²à¸•">
+<!ENTITY noscriptAllow.accesskey "A">
+<!ENTITY noscriptForbid "ห้าม">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "ทำเครื่องหมายเชื่อถือได้">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "ทำเครื่องหมายเชื่อถือไม่ได้">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "ลบไซต์ที่เลือà¸">
+<!ENTITY noscriptGloballyEnabled "อนุà¸à¸²à¸•à¸ªà¸„ริปต์ทั่วไป (อันตราย)">
+<!ENTITY noscriptAutoReload "เรียà¸à¹ƒà¸«à¸¡à¹ˆà¸«à¸™à¹‰à¸²à¸—ี่ส่งผลอัตโนมัติเมื่อเปลี่ยนà¸à¸²à¸£à¸­à¸™à¸¸à¸à¸²à¸•">
+<!ENTITY noscriptGeneral "ทั่วไป">
+<!ENTITY noscriptAppearance "à¸à¸²à¸£à¸›à¸£à¸²à¸à¸">
+<!ENTITY noscriptShow "à¹à¸ªà¸”ง...">
+<!ENTITY noscriptCtxMenu "เมนูบริบท">
+<!ENTITY noscriptStatusIcon "à¹à¸ªà¸”งสัà¸à¸£à¸¹à¸›à¹à¸–บสถานะ">
+<!ENTITY noscriptFullAddr "ที่อยู่เต็ม (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "โดเมนเต็ม (www.noscript.net)">
+<!ENTITY noscriptBaseDom "โดเมนบนà¸à¸²à¸™à¸—ี่สอง (noscript.net)">
+<!ENTITY noscriptTempCmd "อนุà¸à¸²à¸•à¸Šà¸±à¹ˆà¸§à¸„ราว [...]">
+<!ENTITY noscriptSound "เสียงผลป้อนà¸à¸¥à¸±à¸šà¹€à¸¡à¸·à¹ˆà¸­à¸ªà¸„ริปต์ถูà¸à¸šà¸¥à¹‡à¸­à¸">
+<!ENTITY noscriptImport "นำเข้า">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "ส่งออà¸">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "à¹à¸ªà¸”งข้อความเà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸šà¸ªà¸„ริปต์ที่บล็อà¸">
+<!ENTITY noscriptNotify.bottom "วางข้อความที่ล่างสุด">
+<!ENTITY noscriptSound.choose "เลือà¸">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "เล่น">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "à¸à¸¥à¸±à¸šà¹„ปยังค่าเริ่มต้น">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "ขั้นสูง">
+<!ENTITY noscriptAdditionalPermissions "à¸à¸²à¸£à¸­à¸™à¸¸à¸à¸²à¸•à¸—ี่เพิ่มขึ้นสำหรับไซต์ที่เขื่อถือ">
+<!ENTITY noscriptAllowClipboard "อนุà¸à¸²à¸•à¹ƒà¸«à¹‰à¸£à¸´à¸Šà¹€à¸—็à¸à¸‹à¹Œà¸„ัดลอà¸à¹à¸¥à¸°à¸§à¸²à¸‡à¸ˆà¸²à¸à¸„ลิปบอร์ดภายนอà¸">
+<!ENTITY noscriptAdditionalRestrictions "à¸à¸²à¸£à¸„วบคุมที่เพิ่มขึ้นสำหรับไซต์ที่ไม่เชื่อถือ">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Apply these restrictions to trusted sites too">
+<!ENTITY noscriptForbidJava "ไม่อนุà¸à¸²à¸•à¸ˆà¸²à¸§à¸²Ã¢â„¢">
+<!ENTITY noscriptForbidXSLT "Forbid XSLT">
+<!ENTITY noscriptForbidSilverlight "ไม่อนุà¸à¸²à¸• Microsoft® Silverlightâ„¢">
+<!ENTITY noscriptForbidIFrames "ไม่อนุà¸à¸²à¸• &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "ไม่อนุà¸à¸²à¸• &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "ไม่อนุà¸à¸²à¸• @font-face">
+<!ENTITY noscriptForbidWebGL "ไม่อนุà¸à¸²à¸• WebGL">
+<!ENTITY noscriptForbidMedia "ไม่อนุà¸à¸²à¸• &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "ไม่อนุà¸à¸²à¸• Macromedia® Flash®">
+<!ENTITY noscriptForbidPlugins "ไม่อนุà¸à¸²à¸•à¸•à¸±à¸§à¹€à¸ªà¸£à¸´à¸¡à¸­à¸·à¹ˆà¸™">
+<!ENTITY noscriptReloadWarn "ตัวเลือà¸à¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰à¸ˆà¸°à¸ªà¹ˆà¸‡à¸œà¸¥à¸à¸£à¸°à¸—บในหน้าใหม่หรือหน้าที่เรียà¸à¹ƒà¸«à¸¡à¹ˆ (ด้วยตัวเอง)">
+<!ENTITY noscriptConfirmUnblock "ถามเรื่องà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¸à¹ˆà¸­à¸™à¸–อนà¸à¸²à¸£à¸šà¸¥à¹‡à¸­à¸à¸§à¸±à¸•à¸–ุชั่วคราว">
+<!ENTITY noscriptStatusLabel "ป้ายà¹à¸–บสถานะ">
+<!ENTITY noscriptForbidBookmarklets "ไม่อนุà¸à¸²à¸• bookmarklet">
+<!ENTITY noscriptShowPlaceholder "à¹à¸ªà¸”งสัà¸à¸£à¸¹à¸›à¸•à¸±à¸§à¸¢à¸¶à¸”ตำà¹à¸«à¸™à¹ˆà¸‡">
+<!ENTITY noscriptTruncateTitle "ตัดปลายหัวเรื่องเอà¸à¸ªà¸²à¸£">
+<!ENTITY noscriptFixLinks "พยายามซ่อมà¹à¸‹à¸¡à¸¥à¸´à¸‡à¸à¹Œ JavaScript">
+<!ENTITY noscriptAllowBookmarks "อนุà¸à¸²à¸•à¹„ซต์ให้เปิดผ่านที่คั่นหน้า">
+<!ENTITY noscriptAllowViaBookmarks "อนุà¸à¸²à¸•à¹„ซต์ให้เปิดผ่านที่คั่นหน้า">
+<!ENTITY noscriptAllowPing "อนุà¸à¸²à¸• &lt;ปิง...&gt;">
+<!ENTITY noscriptAllowLocalLinks "อนุà¸à¸²à¸•à¸¥à¸´à¸‡à¸à¹Œà¸ à¸²à¸¢à¹ƒà¸™">
+<!ENTITY noscriptForbidPing "ไม่อนุà¸à¸²à¸• &lt;ปิง...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "ห้าม META เปลี่ยนทางภายในส่วนประà¸à¸­à¸š &lt;noscript&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptWhitelist "บัà¸à¸Šà¸µà¸‚าว">
+<!ENTITY noscriptPermissions "à¸à¸²à¸£à¸­à¸™à¸¸à¸à¸²à¸•">
+<!ENTITY noscriptRefresh "เรียà¸à¸«à¸™à¹‰à¸²à¹ƒà¸«à¸¡à¹ˆ">
+<!ENTITY noscriptNotifications "à¸à¸²à¸£à¹€à¸•à¸·à¸­à¸™">
+<!ENTITY noscriptToolbarToggle "คลิà¸à¸‹à¹‰à¸²à¸¢à¸šà¸™à¸›à¸¸à¹ˆà¸¡à¹à¸–มเครื่องมือ NoScript จะสลับà¸à¸²à¸£à¸­à¸™à¸¸à¸à¸²à¸•à¹ƒà¸«à¹‰à¹„ซต์ระดับสูงสุดปัจจุบัน">
+<!ENTITY noscriptTrusted "เชื่อถือได้">
+<!ENTITY noscriptUntrusted "เชื่อถือไม่ได้">
+<!ENTITY noscriptUnknown "ไม่ระบุ">
+<!ENTITY noscriptAdd "เพิ่ม">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "ปิด">
+<!ENTITY noscriptSiteManager "ตัวจัดà¸à¸²à¸£à¹„ซต์">
+<!ENTITY noscriptSecurityManager "ตัวจัดà¸à¸²à¸£à¸”้านความปลอดภัย">
+<!ENTITY noscriptPolicies "à¸à¸Ž">
+<!ENTITY noscriptDefaultPolicies "à¸à¸Žà¹€à¸”ิม">
+<!ENTITY noscriptSitePolicies "à¸à¸Žà¹„ซต์ที่ปราà¸à¸">
+<!ENTITY noscriptNselNever "ซ่อนส่วนประà¸à¸­à¸š &lt;noscript&gt;">
+<!ENTITY noscriptNselForce "à¹à¸ªà¸”งส่วนประà¸à¸­à¸š &lt;noscript&gt; ที่ตาม &lt;SCRIPT&gt; ที่บล็อà¸">
+<!ENTITY noscriptAutoAllowTopLevel "อนุà¸à¸²à¸•à¹„ซต์ระดับสูงสุดโดยชั่วคราวด้วยค่าเริ่มต้น">
+<!ENTITY noscriptDescription "à¸à¸²à¸£à¸›à¹‰à¸­à¸‡à¸à¸±à¸™à¸žà¸´à¹€à¸¨à¸©à¸ªà¸³à¸«à¸£à¸±à¸šà¹„ฟร์ฟอà¸à¸‹à¹Œà¸‚องคุณ: NoScript อนุà¸à¸²à¸•à¸ˆà¸²à¸§à¸²à¸ªà¸„ริปต์ จาวา(à¹à¸¥à¸°à¸•à¸±à¸§à¹€à¸ªà¸£à¸´à¸¡à¸­à¸·à¹ˆà¸™à¹†)เฉพาะสำหรับโดเมนที่เชื่อถือได้ของตัวเลือà¸à¸‚องคุณ(เช่นเว็บไซต์โฮมว่างของคุณ) บัà¸à¸Šà¸µà¸‚าวนี้มีพื้นà¸à¸²à¸™à¸­à¸¢à¸¹à¹ˆà¸šà¸™à¸à¸²à¸£à¸šà¸¥à¹‡à¸­à¸à¸žà¸£à¸µ-เอมป์ทีฟคล้ายà¸à¸²à¸£à¸›à¹‰à¸­à¸‡à¸à¸±à¸™à¸à¸²à¸£à¸«à¸²à¸›à¸£à¸°à¹‚ยชน์อย่างไม่ถูà¸à¸•à¹‰à¸­à¸‡à¸‚องความอ่อนà¹à¸­à¸‚องความปลอดภัย(รู้à¹à¸¥à¹‰à¸§à¹à¸¥à¸°à¹à¸¡à¹‰à¹à¸•à¹ˆà¹„ม่รู้!)ด้วยà¸à¸²à¸£à¹ƒà¸Šà¹‰à¹ƒà¸«à¹‰à¹€à¸›à¹‡à¸™à¸›à¸£à¸°à¹‚ยชน์อย่างไม่ผิดพลาด...ผู้เชี่ยวชาà¸à¸ˆà¸°à¸¢à¸­à¸¡à¸£à¸±à¸š: ไฟร์ฟอà¸à¸‹à¹Œà¸›à¸¥à¸­à¸”ภัยà¸à¸§à¹ˆà¸²à¸­à¸¢à¹ˆà¸²à¸‡à¹à¸—้จริงด้วย NoScript:-)">
+<!ENTITY noscriptOptBlockCssScanners "บล็อà¸à¹€à¸„รื่องà¸à¸£à¸²à¸”ตรวจที่มีซีเอสเอสเป็นราà¸à¸à¸²à¸™">
+<!ENTITY noscriptOptFilterXGet "ไซต์ผสมปราศจาà¸à¹€à¸Šà¸·à¹‰à¸­à¹‚รคมีความต้องà¸à¸²à¸£à¸™à¹ˆà¸²à¸ªà¸‡à¸ªà¸±à¸¢">
+<!ENTITY noscriptOptFilterXPost "เปลี่ยนความต้องà¸à¸²à¸£à¹„ซต์ผสม POST ไปยังความต้องà¸à¸²à¸£à¹„ม่มีข้อมูล GET">
+<!ENTITY noscriptShowConsole "à¹à¸ªà¸”งส่วนเà¸à¹‰à¸²à¸„ุม...">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "เอà¸à¸‹à¹Œà¹€à¸­à¸ªà¹€à¸­à¸ª">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "คำถามพบบ่อยเอà¸à¸‹à¹Œà¹€à¸­à¸ªà¹€à¸­à¸ª...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "โหลดใหม่ไม่ปลอดภัย">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "ข้อยà¸à¹€à¸§à¹‰à¸™à¸à¸²à¸£à¸›à¸à¸›à¹‰à¸­à¸‡à¹à¸­à¸™à¸—ิ-เอà¸à¸‹à¹Œà¹€à¸­à¸ªà¹€à¸­à¸ª">
+<!ENTITY noscriptXssExceptions.description "เป้าหมายà¸à¸²à¸£à¸ˆà¸±à¸šà¸„ู่à¸à¸²à¸£à¹à¸ªà¸”งออà¸à¸—ั่วไปเหล่านี้จะไม่ถูà¸à¸›à¸à¸›à¹‰à¸­à¸‡à¸à¸±à¸šà¹€à¸­à¸à¸‹à¹Œà¹€à¸­à¸ªà¹€à¸­à¸ª">
+<!ENTITY noscriptMatchSample "ตัวอย่างà¸à¸²à¸£à¸ˆà¸±à¸šà¸„ู่พื้นผิว:">
+<!ENTITY noscriptReset "รีเซ็ต">
+<!ENTITY noscriptReset.accesskey "R">
+<!ENTITY noscriptResetDef "คืนค่าเป็นค่าดั้งเดิม">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Revoke Temporary Permissions">
+<!ENTITY noscriptRevokeTemp.accesskey "T">
+<!ENTITY noscriptNoUntrustedPlaceholder "No placeholder for objects coming from sites marked as untrusted">
+<!ENTITY noscriptCollapseBlockedObjects "Collapse blocked objects">
+<!ENTITY noscriptExceptions "Exceptions...">
+<!ENTITY noscriptBlockedObjects "Blocked Objects">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Block every object coming from a site marked as untrusted">
+<!ENTITY noscriptTempAllowPage "Temporarily allow all this page">
+<!ENTITY noscriptTempAllowPage.accesskey "P">
+<!ENTITY noscriptAllowPage "Allow all this page">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "Make page permissions permanent">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Behavior">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "Forbid active web content unless it comes from a secure (HTTPS) connection:">
+<!ENTITY noscriptHttps.never "Never">
+<!ENTITY noscriptHttps.proxy "When using a proxy (recommended with Tor)">
+<!ENTITY noscriptHttps.always "Always">
+<!ENTITY noscriptHttpsForced "Force the following sites to use secure (HTTPS) connections:">
+<!ENTITY noscriptHttpsForcedExceptions "Never force secure (HTTPS) connections for the following sites:">
+<!ENTITY noscriptSecureCookies "Enable Automatic Secure Cookies Management">
+<!ENTITY noscriptSecureCookiesForced "Force encryption for all the cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptSecureCookiesExceptions "Ignore unsafe cookies set over HTTPS by the following sites:">
+<!ENTITY noscriptClearClickTitle "ClearClick Warning">
+<!ENTITY noscriptClearClickHeader "Potential Clickjacking / UI Redressing Attempt!">
+<!ENTITY noscriptClearClickDescription "NoScript intercepted a mouse or keyboard interaction with a partially hidden element. Click on the image above to cycle beetween the obstructed and the clear version.">
+<!ENTITY noscriptClearClickOpt "ClearClick protection on pages…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "trusted">
+<!ENTITY noscriptUntrustedPagesAdj "untrusted">
+<!ENTITY noscriptKeepLocked "Keep this element locked (recommended)">
+<!ENTITY noscriptEmbeddings "Embedded Objects">
+<!ENTITY noscriptPrev "Previuous">
+<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/th/noscript/noscript.properties b/extensions/noscript/chrome/locale/th/noscript/noscript.properties
new file mode 100644
index 0000000..31235fa
--- /dev/null
+++ b/extensions/noscript/chrome/locale/th/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=อนุà¸à¸²à¸•à¸ªà¸„ริปต์โดยรวม (อันตราย)
+forbidGlobal=ไม่อนุà¸à¸²à¸•à¸ªà¸„ริปต์โดยรวม (พิจารณาà¹à¸¥à¹‰à¸§)
+allowLocal=อนุà¸à¸²à¸• %S
+allowTemp=อนุà¸à¸²à¸• %S ชั่วคราว
+forbidLocal=ไม่อนุà¸à¸²à¸• %S
+allowed.glb=อันตราย! อนุà¸à¸²à¸•à¸„ริปต์โดยรวมà¹à¸¥à¹‰à¸§
+allowed.yes=อนุà¸à¸²à¸•à¸ªà¸„ริปต์ปัจจุบันà¹à¸¥à¹‰à¸§
+allowed.prt=อนุà¸à¸²à¸•à¸ªà¸„ริปต์บางส่วนà¹à¸¥à¹‰à¸§
+allowed.no=ไม่อนุà¸à¸²à¸•à¸ªà¸„ริปต์ปัจจุบันà¹à¸¥à¹‰à¸§
+global.warning.title=คำเตือน!
+global.warning.text=สคริปต์à¸à¸³à¸¥à¸±à¸‡à¸ˆà¸°à¸–ูà¸à¸­à¸™à¸¸à¸à¸²à¸•à¹‚ดยทั่วไป (สำหรับทุà¸à¹„ซต์)\n นี่คือà¸à¸²à¸£à¸à¸£à¸°à¸—ำที่จะอันตรายได้\nคุณà¹à¸™à¹ˆà¹ƒà¸ˆà¸«à¸£à¸·à¸­à¸§à¹ˆà¸²à¸•à¹‰à¸­à¸‡à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸•à¹ˆà¸­
+audio.samples=ตัวอย่างเสียง
+confirm=คุณà¹à¸™à¹ˆà¹ƒà¸ˆà¸«à¸£à¸·à¸­
+alwaysAsk=ถามเรื่องà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¹€à¸ªà¸¡à¸­
+notifyHide=ซ่อนหลังจาภ%S วินาที
+trust=เชื่อ %S
+distrust=ทำสัà¸à¸¥à¸±à¸à¸©à¸“์ว่าเชื่อถือไม่ได้à¸à¸±à¸š %S
+untrustedOrigin=ที่มาไม่น่าไว้ใจ
+xss.notify.generic=NoScript à¸à¸£à¸­à¸‡à¸ªà¸„ริปต์ไซต์ผสมที่อาจเป็นไปได้ (XSS) ซึ่งพยายามจาภ%S รายละเอียดทางเทคนิคถูà¸à¸šà¸±à¸™à¸—ึà¸à¸­à¸¢à¸¹à¹ˆà¸—ี่ส่วนเà¸à¹‰à¸²à¸„ุม
+xss.notify.showConsole=à¹à¸ªà¸”งส่วนเà¸à¹‰à¸²à¸„ุม...
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=ความต้องà¸à¸²à¸£à¸—ี่น่าสงสัยที่ปราศจาà¸à¹€à¸Šà¸·à¹‰à¸­à¹‚รคà¹à¸¥à¹‰à¸§ ยูอาร์à¹à¸­à¸¥à¸”ั้งเดิม [%1$S] ต้องà¸à¸²à¸£à¸ˆà¸²à¸ [%2$S] ยูอาร์à¹à¸­à¸¥à¸—ี่ปราศจาà¸à¹€à¸Šà¸·à¹‰à¸­à¹‚รคà¹à¸¥à¹‰à¸§: [%3$S]
+xss.reason.filterXGetRef=ผู้เสนอความต้องà¸à¸²à¸£à¸—ี่น่าสงสัยที่ปราศจาà¸à¹€à¸Šà¸·à¹‰à¸­à¹‚รคà¹à¸¥à¹‰à¸§ ยูอาร์à¹à¸­à¸¥ [%1$S] ต้องà¸à¸²à¸£à¸ˆà¸²à¸ [%2$S] ผู้เสนอที่ปราศจาà¸à¹€à¸Šà¸·à¹‰à¸­à¹‚รคà¹à¸¥à¹‰à¸§: [%3$S]
+xss.reason.filterXPost=ส่วนที่น่าสงสัยที่ปราศจาà¸à¹€à¸Šà¸·à¹‰à¸­à¹‚รคà¹à¸¥à¹‰à¸§à¸­à¸±à¸›à¹‚หลดสู่ [%1$S] จาภ[%2$S]: à¹à¸›à¸¥à¸‡à¸ªà¸¹à¹ˆà¸„วามต้องà¸à¸²à¸£ GET งานดาวน์โหลดเท่านั้น
+unsafeReload.warning=โหลดสิ่งน่าสงสัยใหม่อย่างไม่ปลอดภัย\n\n%1$S [%2$S]\n\nจาภ[%3$S]\n\nNoScript จะไม่ปà¸à¸›à¹‰à¸­à¸‡à¸„ำขอนี้!\n
+metaRefresh.notify=NoScript บล็อภ<META> เปลี่ยนทางภายในส่วนประà¸à¸­à¸š <NOSCRIPT>: %S ใน %S วินาที
+metaRefresh.notify.follow=เปลี่ยนทางตาม
+metaRefresh.notify.follow.accessKey=F
+notify.options=ตัวเลือà¸
+notify.options.accessKey=O
+reset.title=รีเช็ต NoScript
+reset.warning=à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า NoScript à¹à¸¥à¸°à¸à¸²à¸£à¸­à¸™à¸¸à¸à¸²à¸•à¹„ซต์ทั้งหมดจะถูà¸à¸„ืนค่าไปยังค่าเริ่มต้นทีนที\nà¸à¸²à¸£à¸à¸£à¸°à¸—ำนี้ไม่สามารถà¸à¸¥à¸±à¸šà¸„ืนได้\nคุณต้องà¸à¸²à¸£à¸—ำต่อหรือไม่
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark's content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/tr/noscript/about.properties b/extensions/noscript/chrome/locale/tr/noscript/about.properties
new file mode 100644
index 0000000..4150405
--- /dev/null
+++ b/extensions/noscript/chrome/locale/tr/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Firefox'unuz için ek koruma: NoScript sadece güvendiğiniz sitelerde (örneğin bankanızın web sitesi) JavaScript, Java (ve diğer eklentiler) kullanımına izin verebilir veya yasaklayabilirsiniz. Beyaz liste tabanlı öncelikli engelleme yaklaşımı, güvenlik açıklarının yayılmasını hiçbir işlev kaybı olmadan önler (bilinen veya bilinmeyen!)… Uzmanlar Firefox'un NoScript eklentisi ile daha güvenli olduğunda hemfikir olacaklardır :-)
+aboutTitle=%S Hakkında
+extensionContributors=Emeği geçenler:
+extensionContributors.tip=Bu eklenti için teşekkür etmeniz gerekenler
+extensionCreatorLabel=Yazar:
+changelog=DeÄŸiÅŸiklikler
+changelog.tip=Değişiklikleri göster
+license=Lisans
+license.tip=Son kullanıcı lisansını oku
+logo.tip=Uzantı ana sayfasına git
+sponsor.tip=Sponsor ana sayfasına git
+informaction.tip=InformAction ana sayfasına git
+extensionHomepage.tip=Uzantı ana sayfasına git
+extensionCreator.tip=Yazarın ana sayfasına git
+version=Sürüm %S \ No newline at end of file
diff --git a/extensions/noscript/chrome/locale/tr/noscript/noscript.dtd b/extensions/noscript/chrome/locale/tr/noscript/noscript.dtd
new file mode 100644
index 0000000..c27cdd5
--- /dev/null
+++ b/extensions/noscript/chrome/locale/tr/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Seçenekler">
+<!ENTITY noscriptOptions.accesskey "S">
+<!ENTITY noscriptOptionsLong "NoScript Seçenekleri">
+<!ENTITY noscriptAbout "NoScript 5.1.8.5 @VERSION@ Hakkında">
+<!ENTITY noscriptPermissionsText "Hangi web sayfalarında JavaScript'e izni vereceğinizi kolayca seçebilirsiniz. Lütfen adresi tam olarak girin (örn. &quot;http://www.site.com&quot; veya &quot;site.com&quot;) ve 'İzin ver' düğmesine tıklayarak sayfanın JavaScript kullanmasına izin verin.">
+<!ENTITY noscriptWebAddress "Site adresi:">
+<!ENTITY noscriptAllow "Ä°zin ver">
+<!ENTITY noscriptAllow.accesskey "z">
+<!ENTITY noscriptForbid "Engelle">
+<!ENTITY noscriptForbid.accesskey "E">
+<!ENTITY noscriptTrust "Güvenilir Olarak İşaretle">
+<!ENTITY noscriptTrust.accesskey "G">
+<!ENTITY noscriptUntrust "Güvensiz Olarak İşaretle">
+<!ENTITY noscriptUntrust.accesskey "v">
+<!ENTITY noscriptRemoveSelected "Seçili Siteleri Kaldır">
+<!ENTITY noscriptGloballyEnabled "Betiklere Tüm Siteler İçin İzin Verilir (Tehlikelidir)">
+<!ENTITY noscriptAutoReload "İzinler değişince etkilenen sayfayı otomatik olarak tazele">
+<!ENTITY noscriptGeneral "Genel">
+<!ENTITY noscriptAppearance "Görünüm">
+<!ENTITY noscriptShow "Göster…">
+<!ENTITY noscriptCtxMenu "Bağlamsal menü">
+<!ENTITY noscriptStatusIcon "Durum çubugu simgesi">
+<!ENTITY noscriptFullAddr "Tam Adresler (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Tam Alan Adları (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Temel 2. Seviye Alan Adları (noscript.net)">
+<!ENTITY noscriptTempCmd "[…] eylemine geçici olarak izin ver">
+<!ENTITY noscriptSound "Kodlar engellenince ses dosyası çal">
+<!ENTITY noscriptImport "İçe aktar">
+<!ENTITY noscriptImport.accesskey "K">
+<!ENTITY noscriptExport "Dışa aktar">
+<!ENTITY noscriptExport.accesskey "A">
+<!ENTITY noscriptNotify "Betikler engellendiğinde ileti göster">
+<!ENTITY noscriptNotify.bottom "İletiyi aşağıdaki kenarda göster">
+<!ENTITY noscriptSound.choose "Seç">
+<!ENTITY noscriptSound.choose.accesskey "S">
+<!ENTITY noscriptSound.play "Çal">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "Varsayılanları yükle">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "GeliÅŸmiÅŸ">
+<!ENTITY noscriptAdditionalPermissions "Güvenli siteler için ek izinler">
+<!ENTITY noscriptAllowClipboard "Harici panoda zengin Kopyala ve Yapıştır işlemlerine izin ver">
+<!ENTITY noscriptAdditionalRestrictions "Güvensiz siteler için ek kısıtlamalar">
+<!ENTITY noscriptPlugins "Eklentiler">
+<!ENTITY noscriptContentBlocker "Bu sınırlamaları güvenilen sitelere de uygula">
+<!ENTITY noscriptForbidJava "Java™'yı yasakla">
+<!ENTITY noscriptForbidXSLT "XSLT'yı yasakla">
+<!ENTITY noscriptForbidSilverlight "Microsoft® Silverlight™'ı yasakla">
+<!ENTITY noscriptForbidIFrames "&lt;IFRAME&gt;'leri yasakla">
+<!ENTITY noscriptForbidFrames "&lt;FRAME&gt;'leri yasakla">
+<!ENTITY noscriptForbidFonts "Yazıtipi @font-face tanımını yasakla">
+<!ENTITY noscriptForbidMedia "&lt;AUDIO&gt; / &lt;VIDEO&gt; yasakla">
+<!ENTITY noscriptForbidFlash "Adobe® Flash®'ı yasakla">
+<!ENTITY noscriptForbidPlugins "DiÄŸer eklentileri yasakla">
+<!ENTITY noscriptForbidWebGL "Yazıtipi WebGL tanımını yasakla">
+<!ENTITY noscriptReloadWarn "Bu ayarlar sadece yeni veya kendinizin yeniden yüklediği sayfalar için geçerlidir.">
+<!ENTITY noscriptConfirmUnblock "Bir nesne engelini geçici olarak kaldırırken onay iste">
+<!ENTITY noscriptStatusLabel "Durum çubuğu etiketi">
+<!ENTITY noscriptForbidBookmarklets "Yer imlerini yasakla">
+<!ENTITY noscriptShowPlaceholder "Yer tutucu simgelerini göster">
+<!ENTITY noscriptTruncateTitle "Belge başlığını kes">
+<!ENTITY noscriptFixLinks "JavaScript bağlantılarını düzeltmeye çalış">
+<!ENTITY noscriptAllowBookmarks "Yer imlerimde kayıtlı sitelere izin ver">
+<!ENTITY noscriptAllowViaBookmarks "Yer imlerinden açılan sitelere izin ver">
+<!ENTITY noscriptAllowPing "&lt;A PING…&gt;'e izin ver">
+<!ENTITY noscriptAllowLocalLinks "Yerel bağlantılara izin ver">
+<!ENTITY noscriptForbidPing "&lt;A PING…&gt;'i yasakla">
+<!ENTITY noscriptForbidMetaRefresh "&lt;NOSCRIPT&gt; öğeleri içindeki META yeniden yönlendirmelerini engelle">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "M">
+<!ENTITY noscriptNotifyMeta "Engellenen META yeniden yönlendirmeleri hakkında bilgilendir">
+<!ENTITY noscriptNotifyMeta.accesskey "M">
+<!ENTITY noscriptWhitelist "Beyazliste">
+<!ENTITY noscriptPermissions "Ä°zinler">
+<!ENTITY noscriptRefresh "Tazele">
+<!ENTITY noscriptNotifications "Bildirimler">
+<!ENTITY noscriptToolbarToggle "Araç çubuğundaki NoScript düğmesine sol tıklayarak üst seviye sitenin erişim izinlerini değiştirebilirsiniz">
+<!ENTITY noscriptTrusted "Güvenilen">
+<!ENTITY noscriptUntrusted "Güvenilmeyen">
+<!ENTITY noscriptUnknown "Bilinmeyen">
+<!ENTITY noscriptAdd "Ekle">
+<!ENTITY noscriptAdd.accesskey "E">
+<!ENTITY noscriptClose "Kapat">
+<!ENTITY noscriptSiteManager "Site Yöneticisi">
+<!ENTITY noscriptSecurityManager "Güvenlik Yöneticisi">
+<!ENTITY noscriptPolicies "Ä°lkeler">
+<!ENTITY noscriptDefaultPolicies "Varsayılan İlkeler">
+<!ENTITY noscriptSitePolicies "Siteye özel ilkeler">
+<!ENTITY noscriptNselNever "&lt;NOSCRIPT&gt; öğelerini sakla">
+<!ENTITY noscriptNselForce "&lt;SCRIPT&gt;'den sonra oluşan &lt;NOSCRIPT&gt; öğelerini göster">
+<!ENTITY noscriptAutoAllowTopLevel "Varsayılan olarak üst seviye sitelere geçici izin ver">
+<!ENTITY noscriptDescription "Firefox'unuz için ek koruma: NoScript sadece güvendiğiniz sitelerde (örneğin bankanızın web sitesi) JavaScript, Java (ve diğer eklentiler) kullanımına izin verebilir veya yasaklayabilirsiniz. Beyaz liste tabanlı öncelikli engelleme yaklaşımı, güvenlik açıklarının yayılmasını hiçbir işlev kaybı olmadan önler (bilinen veya bilinmeyen!)… Uzmanlar Firefox'un NoScript eklentisi ile daha güvenli olduğunda hemfikir olacaklardır :-)">
+<!ENTITY noscriptOptBlockCssScanners "CSS temelli tarayıcıları engelle">
+<!ENTITY noscriptOptFilterXGet "Çapraz-site şüpheli isteklerini temizle">
+<!ENTITY noscriptOptFilterXPost "Çapraz-site POST isteklerini GET'e çevir">
+<!ENTITY noscriptShowConsole "Konsolu Göster…">
+<!ENTITY noscriptShowConsole.accesskey "K">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS SSS…">
+<!ENTITY noscriptXssFaq.accesskey "S">
+<!ENTITY noscriptUnsafeReload "Güvensiz Tekrar Yükleme">
+<!ENTITY noscriptUnsafeReload.accesskey "Y">
+<!ENTITY noscriptXssExceptions "Anti-XSS Koruma Ayrıcalıkları">
+<!ENTITY noscriptXssExceptions.description "Aşağıdaki tanımlara uyan hedefler XSS&apos;e karşı KORUNMAYACAKLAR.">
+<!ENTITY noscriptMatchSample "Eşleşen desen örneği:">
+<!ENTITY noscriptReset "Sıfırla">
+<!ENTITY noscriptReset.accesskey "s">
+<!ENTITY noscriptResetDef "Varsayılana Sıfırla">
+<!ENTITY noscriptResetDef.accesskey "v">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Geçici İzinleri Kaldır">
+<!ENTITY noscriptRevokeTemp.accesskey "K">
+<!ENTITY noscriptNoUntrustedPlaceholder "Güvensiz işaretlenen sitelerden gelen nesnelerde yer tutucuları gösterme">
+<!ENTITY noscriptCollapseBlockedObjects "Engellenen nesneleri daralt">
+<!ENTITY noscriptExceptions "Hariç tutulanlar…">
+<!ENTITY noscriptBlockedObjects "Engellenen Nesneler">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Güvensiz olarak işaretlenen sitelerden gelen tüm nesneleri engelle">
+<!ENTITY noscriptTempAllowPage "Geçici olarak bu sayfanın tümüne izin ver">
+<!ENTITY noscriptTempAllowPage.accesskey "G">
+<!ENTITY noscriptAllowPage "Bu sayfanın tümüne izin ver">
+<!ENTITY noscriptAllowPage.accesskey "z">
+<!ENTITY noscriptTempToPerm "Sayfa izinlerini kalıcı yap">
+<!ENTITY noscriptTempToPerm.accesskey "k">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS SSS...">
+<!ENTITY noscriptHttpsFaq.accesskey "S">
+<!ENTITY noscriptHttps.behavior "Davranış">
+<!ENTITY noscriptHttps.cookies "Çerezler">
+<!ENTITY noscriptHttps.description "Etkin web içeriği, güvenli bağlantı üzerinden gelmezse (HTTPS) engelle:">
+<!ENTITY noscriptHttps.never "Asla">
+<!ENTITY noscriptHttps.proxy "Vekil sunucu kullanırken (Tor kullanırken tavsiye edilir)">
+<!ENTITY noscriptHttps.always "Her zaman">
+<!ENTITY noscriptHttpsForced "Bu siteleri güvenli bağlantı kullanmaya zorla (HTTPS):">
+<!ENTITY noscriptHttpsForcedExceptions "Bu siteleri güvenli bağlantı (HTTPS) kullanmaya asla zorlama:">
+<!ENTITY noscriptSecureCookies "Otomatik Güvenli Çerez Yönetimini etkinleştir">
+<!ENTITY noscriptSecureCookiesForced "Bu sitelerin HTTPS üzerinden gönderilen çerezlerinin şifrelenmesini zorla:">
+<!ENTITY noscriptSecureCookiesExceptions "HTTPS üzerinden gönderilen güvensiz çerezleri bu siteler için yoksay:">
+<!ENTITY noscriptClearClickTitle "TemizTıklama Uyarısı">
+<!ENTITY noscriptClearClickHeader "Muhtemel Tıklama Hilesi/Yeniden Adresleme Denemesi">
+<!ENTITY noscriptClearClickDescription "NoScript kısmen gizlenmiş bir öğe ile fare veya klavyenin etkileşimini engelledi. Engellenmiş ve temiz sürüm arasında geçiş yapmak için üstteki resme tıklayın.">
+<!ENTITY noscriptClearClickOpt "Sayfalarda TemizTıklama koruması yap…">
+<!ENTITY noscriptClearClickReport "Bildir">
+<!ENTITY noscriptClearClickReport.accesskey "B">
+<!ENTITY noscriptClearClickReportId "Bildiri KimliÄŸi:">
+<!ENTITY noscriptTrustedPagesAdj "güvenilenlerde">
+<!ENTITY noscriptUntrustedPagesAdj "güvenilmeyenlerde">
+<!ENTITY noscriptKeepLocked "Bu öğeyi kilitli olarak bırak (tavsiye edilir)">
+<!ENTITY noscriptEmbeddings "Gömülü Nesneler">
+<!ENTITY noscriptPrev "Önceki">
+<!ENTITY noscriptNext "Sonraki">
+<!ENTITY noscriptFrameOptErr.title "Bu içerik bir çerçeve içerisinde gösterilemez">
+<!ENTITY noscriptFrameOptErr.desc "Güvenliğinizi korumak için, bu içeriğin sağlayıcısı bir çerçeve içerisinde gösterilmesine izin vermiyor.">
+<!ENTITY noscriptFrameOptErr.link "İçeriği yeni bir pencere içerisinde açmak için buraya tıklayın">
+<!ENTITY noscriptBookmarkSync "NoScript yapılandırmasını kolay eşitleme için yer imlerine yedekle">
+<!ENTITY noscriptShowReleaseNotes "Güncelleme olduğunda sürüm notlarını görüntüle">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Kural Kümeleri:">
+<!ENTITY ABE.enabled.label "ABE (Uygulama Sınır Zorlayıcı) Etkinleştir">
+<!ENTITY ABE.siteEnabled.label "Sitelerin kendi kural kümelerini kullanmasına izin ver">
+<!ENTITY ABE.edit.label "Düzenle…">
+<!ENTITY ABE.edit.accesskey "D">
+<!ENTITY ABE.enable.label "EtkinleÅŸtir">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Devre Dışı Bırak">
+<!ENTITY ABE.disable.accesskey "E">
+<!ENTITY ABE.refresh.label "Yenile">
+<!ENTITY ABE.refresh.accesskey "Y">
+<!ENTITY noscriptUninstall "Kaldır">
+<!ENTITY noscriptRecentBlocked "Yakın zamanda engellenen siteler">
+<!ENTITY noscriptExternalFilters "Harici Süzgeçler">
+<!ENTITY noscriptEF.enable "Harici süzgeçleri etkinleştir">
+<!ENTITY noscriptEF.add "Yeni Süzgeç…">
+<!ENTITY noscriptEF.executable "Uygulama dosyası:">
+<!ENTITY noscriptEF.browse "Gözat...">
+<!ENTITY noscriptEF.contentType "Süzülecek içerik türü (MIME) (tam metin veya düzenli ifade):">
+<!ENTITY noscriptEF.exceptions "Bu sitelerden gelen nesneleri süzme:">
+<!ENTITY noscriptEF.remove "Kaldır">
+<!ENTITY noscriptPreset "Güvenlik Seviyesi">
+<!ENTITY noscriptPreset.off "Kapalı (ciddi misiniz?!)">
+<!ENTITY noscriptPreset.low "Kolay kullanım (Karaliste + Web Güvenliği)">
+<!ENTITY noscriptPreset.medium "Klasik (Beyazliste + Web Güvenliği)">
+<!ENTITY noscriptPreset.high "Kale (Tamamen kilitle)">
+<!ENTITY noscript.hoverUI "Fare ile NoScript simgesi üzerine gidince izinler listesini aç">
+<!ENTITY noscriptDonate "Bağış Yap">
+<!ENTITY noscriptDonate.accesskey "B">
+<!ENTITY noscriptAutoReload.currentTab "Sadece geçerli sekmeyi yeniden yükle">
+<!ENTITY noscriptCascadePermissions "Ãœst belge izinlerini 3. parti betiklere de indir">
+<!ENTITY noscriptRestrictSubdocScripting "Beyaz listede olmayan sayfaların, beyaz listedeki alt sayfalarında bulunan betikleri engelle">
+<!ENTITY noscriptGlobalHttpsWhitelist "HTTPS belgelerinde HTTPS betiklerine genel olarak izin ver">
+<!ENTITY noscriptPermanentInPrivate "Özel pencerelerdeki komutlara kalıcı olarak &quot;İzin Ver&quot;">
+<!ENTITY noscriptCustom "Custom">
diff --git a/extensions/noscript/chrome/locale/tr/noscript/noscript.properties b/extensions/noscript/chrome/locale/tr/noscript/noscript.properties
new file mode 100644
index 0000000..ab88a07
--- /dev/null
+++ b/extensions/noscript/chrome/locale/tr/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Betiklere Tüm Sitelerde İzin Ver (tehlikeli)
+forbidGlobal=Betikleri Tüm Sitelerde Yasakla (tavsiye edilen)
+allowLocal=%S adresine izin ver
+allowTemp=%S adresine geçici izin ver
+forbidLocal=%S adresini yasakla
+allowed.glb=Dikkat! Betiklere Tüm Sitelerde İzin Veriliyor
+allowed.yes=Betiklere Åžu An Ä°zin Veriliyor
+allowed.prt=Betiklere Şu An Kısmen İzin Veriliyor
+allowed.no=Betikler Şu An Yasaklı
+global.warning.title=Uyarı!
+global.warning.text=Betiklere genel olarak izin verilecek (her site için).\n Bu muhtemel tehlikeli bir eylemdir.\nDevam etmek istediğinizden emin misiniz?
+audio.samples=Ses örnekleri
+confirm=Emin misiniz?
+alwaysAsk=Her zaman onay iste
+notifyHide=%S saniye sonra gizle
+trust=%S adresine güven
+distrust=%S adresine güvenme
+untrustedOrigin=güvensiz bir kaynak
+xss.notify.generic=NoScript, %S adresinden olan potansiyel bir çapraz-site betiğini (XSS) filtreledi. Teknik detaylar Konsola kaydedildi.
+xss.notify.showConsole=Konsolu Göster…
+xss.notify.showConsole.accessKey=K
+xss.reason.filterXGet=Şüpheli istek temizlendi. Özgün URL [%1$S], [%2$S] sayfasından istendi. Temizlenen URL: [%3$S].
+xss.reason.filterXGetRef=Şüpheli yönlendirici isteği temizlendi. URL [%1$S], [%2$S] sayfasından istendi. Temizlenen Referrer: [%3$S].)
+xss.reason.filterXPost=[%2$S] adresinden [%1$S] üzerine şüpheli yükleme temizlendi: sadece-indir GET isteğine çevrildi.
+unsafeReload.warning=GÜVENSİZ yeniden yükleme\n\n%1$S [%2$S]\n\nKAYNAK [%3$S]\n\nNoScript bu isteği KORUMAYACAK!\n
+metaRefresh.notify=NoScript <NOSCRIPT> içindeki bir <META> yeniden yönlendirmesini engelledi: %S için son %S saniye.
+metaRefresh.notify.follow=Yeniden Yönlendirmeleri Takip Et
+metaRefresh.notify.follow.accessKey=Y
+notify.options=Seçenekler
+notify.options.accessKey=s
+reset.title=NoScript Sıfırla
+reset.warning=Tüm NoScript ayarları ve site izinleri varsayılan değerlerine alınacaktır.\nBu işlem geri alınamaz.\nDevam etmek istediğinize emin misiniz?
+bookmarkSync.title=NoScript Ayar Yer Ä°mi
+bookmarkSync.message=Bu Yer İminin açılması gerekli DEĞİLDİR, fakat Weave veya XMarks uzantıları gibi hizmetler kullanarak eşitlemek içindir.
+bookmarkSync.confirm=NoScript %S tarihinde kaydedilen bir ayar yerimi buldu.\nYerel NoScript ayarınızın üzerine bu dosyayı yazmak istediğinize emin misiniz?
+ABE.notify=%1$S isteği ABE tarafından filtrelendi: <%2$S> %3$S
+ABE.chooseEditor=Lütfen ABE kural kümeleri için bir metin düzenleyici seçin
+ABE.syntaxError=ABE kural kümelerinde sözdizimi hatası var!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Åžuradan gelen her ÅŸeye izin ver: %S
+allowTempFrom=Şuradan gelen her şeye geçici izin ver: %S
+siteInfo.confirm=%2$S sorgusunu yaparak \n"%1$S" sitesi hakkında bilgi istemek üzeresiniz.\nDevam etmek istiyor musunuz?
+siteInfo.tooltip=Site hakkında bilgi almak için orta tuş ile tıklayın veya Üst Karakter tuşu ile tıklayın
+ef.activate=Süz: %S
+ef.options=%S seçenekleri…
+ef.newName=Yeni süzgeç adını girin:
+ef.locateExe=%S süzgeci için yürütülebilir dosyayı seçin
+disable=%S Devre Dışı Bırak
+disable.accessKey=K
+allowed.glb-emb=Betiklere Genel Olarak İzin Veriliyor ancak Bazı Gömülü Nesneler Engelli
+removal.title=Güvenlik Düşürme Uyarısı
+removal.message=NoScript'i devre dışı bırakarak veya kaldırarak, NoScript tarafından sağlanan TÜM korumalardan vazgeçiyorsunuz.\n\nHer site için betik izinlerini ayarlamaktan yorulduysanız, daha güvenli bir seçenek var.\n\nNoScript hala güvenilmez olarak işaretlediğiniz betikleri engellerken, en gelişmiş güvenlik önlemleri ile sizi XSS, Tıklama Hilesi (Clickjacking), CSRF ve diğer web tehditlerine karşı koruyabilir.\n\nGerçekten tüm NoScript korumalarını kaldırmak istiyor musunuz?\n
+removal.no=Hayır, sadece betikleri engellemeyi durdur
+removal.yes=Evet, TÜM korumaları kaldır
+incompatibleOptions.title=Uyumsuz Seçenek Uyarısı
+incompatibleOptions="%1$S"\n seçeneği "%2$S" ile uyumsuz.\bİlkini etkinleştirip ikinciyi devre dışı bırakmak ister misiniz? \ No newline at end of file
diff --git a/extensions/noscript/chrome/locale/uk/noscript/about.properties b/extensions/noscript/chrome/locale/uk/noscript/about.properties
new file mode 100644
index 0000000..bf56f7c
--- /dev/null
+++ b/extensions/noscript/chrome/locale/uk/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Додатковий захиÑÑ‚ Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Firefox: NoScript дозволÑÑ” JavaScript, Java (та інші модулі) лише на довірених Ñайтах по вашому вибору. (Скажімо, Ñайт вашого банка). Такий превентивний підхід «білого ÑпиÑку» дозволÑÑ” вберегтиÑÑŒ від уÑÑ–Ñ… вразливоÑтей (відомих та навіть невідомих!) без втрати функціональноÑÑ‚Ñ–. Знавці погодÑÑ‚ÑŒÑÑ: Firefox з додатком NoScript дійÑно безпечніший :-)
+aboutTitle=Про Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ %S
+extensionContributors=УчаÑники:
+extensionContributors.tip=Люді Ñкі допомагали вдоÑконалювати розширеннÑ
+extensionCreatorLabel=Ðвтор:
+changelog=ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ð²ÐµÑ€Ñій
+changelog.tip=ПодивитиÑÑ Ñ–Ñторію верÑій NoScript
+license=Ліцензійна угода
+license.tip=Ліцензійна угода кінцевого кориÑтувача
+logo.tip=Відкрити домашню Ñторінку розширеннÑ
+sponsor.tip=Відкрити домашню Ñторінку ÑпонÑора
+informaction.tip=Відкрити домашню Ñторінку InformAction
+extensionHomepage.tip=Відкрити домашню Ñторінку розширеннÑ
+extensionCreator.tip=Відкрити домашню Ñторінку автора
+version=ВерÑÑ–Ñ %S
diff --git a/extensions/noscript/chrome/locale/uk/noscript/noscript.dtd b/extensions/noscript/chrome/locale/uk/noscript/noscript.dtd
new file mode 100644
index 0000000..8872813
--- /dev/null
+++ b/extensions/noscript/chrome/locale/uk/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "ÐалаштуваннÑ…">
+<!ENTITY noscriptOptions.accesskey "ш">
+<!ENTITY noscriptOptionsLong "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ NoScript">
+<!ENTITY noscriptAbout "Про розширеннÑ…">
+<!ENTITY noscriptPermissionsText "Ви можете вÑтановити Ñким web-Ñайтам дозволено виконувати JavaScript. Введіть адреÑу або домен (напр. &quot;http://www.site.com&quot; або &quot;site.com&quot;) Ñайта Ñкому ви бажаєте дозволити виконувати JavaScript Ñ– потім натиÑніть Дозволити.">
+<!ENTITY noscriptWebAddress "ÐдреÑа web-Ñайта:">
+<!ENTITY noscriptAllow "Дозволити">
+<!ENTITY noscriptAllow.accesskey "о">
+<!ENTITY noscriptForbid "Заборонити">
+<!ENTITY noscriptForbid.accesskey "б">
+<!ENTITY noscriptTrust "Помітити Ñк «довірений»">
+<!ENTITY noscriptTrust.accesskey "в">
+<!ENTITY noscriptUntrust "Помітити Ñк «не довірений»">
+<!ENTITY noscriptUntrust.accesskey "е">
+<!ENTITY noscriptRemoveSelected "Вилучити вибрані Ñайти">
+<!ENTITY noscriptGloballyEnabled "JavaScript повніÑÑ‚ÑŽ дозволений (небезпечно)">
+<!ENTITY noscriptAutoReload "Ðвтоматично оновлювати Ñторінку піÑÐ»Ñ Ð·Ð¼Ñ–Ð½Ð¸ Ð´Ð»Ñ Ð½ÐµÑ— правил">
+<!ENTITY noscriptGeneral "ОÑновні">
+<!ENTITY noscriptAppearance "Зовнішній виглÑд">
+<!ENTITY noscriptShow "Показувати…">
+<!ENTITY noscriptCtxMenu "КонтекÑтне меню">
+<!ENTITY noscriptStatusIcon "Іконку в Ñ€Ñдку ÑтатуÑу">
+<!ENTITY noscriptFullAddr "Повні адреÑи (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Повні домени (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Базові домени другого Ñ€Ñ–Ð²Ð½Ñ (noscript.net)">
+<!ENTITY noscriptTempCmd "ТимчаÑово дозволити […]">
+<!ENTITY noscriptSound "Програти аудіо-файл Ñкщо заблокований Ñкрипт">
+<!ENTITY noscriptImport "Імпорт">
+<!ENTITY noscriptImport.accesskey "м">
+<!ENTITY noscriptExport "ЕкÑпорт">
+<!ENTITY noscriptExport.accesskey "к">
+<!ENTITY noscriptNotify "Показувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ заблоковані Ñкрипти">
+<!ENTITY noscriptNotify.bottom "Розташувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð½Ð¸Ð·Ñƒ">
+<!ENTITY noscriptSound.choose "Вибрати">
+<!ENTITY noscriptSound.choose.accesskey "б">
+<!ENTITY noscriptSound.play "ТеÑÑ‚">
+<!ENTITY noscriptSound.play.accesskey "Ñ">
+<!ENTITY noscriptSound.reset "Скинути">
+<!ENTITY noscriptSound.reset.accesskey "н">
+<!ENTITY noscriptAdvanced "Додатково">
+<!ENTITY noscriptAdditionalPermissions "Додаткові права Ð´Ð»Ñ Ð´Ð¾Ð²Ñ–Ñ€ÐµÐ½Ð¸Ñ… Ñайтів">
+<!ENTITY noscriptAllowClipboard "Дозволити розширене копіюваннÑ/вÑтавку із зовнішнього буфера обміну">
+<!ENTITY noscriptAdditionalRestrictions "Додаткові Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð½ÐµÐ½Ð°Ð´Ñ–Ð¹Ð½Ð¸Ñ… Ñайтів">
+<!ENTITY noscriptPlugins "Модулі">
+<!ENTITY noscriptContentBlocker "ЗаÑтоÑовувати ці Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ– до довірених Ñайтів">
+<!ENTITY noscriptForbidJava "Заборонити Java™">
+<!ENTITY noscriptForbidXSLT "Заборонити XSLT">
+<!ENTITY noscriptForbidWebGL "Заборонити WebGL">
+<!ENTITY noscriptForbidSilverlight "Заборонити Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Заборонити &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Заборонити &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "Заборонити @font-face">
+<!ENTITY noscriptForbidMedia "Заборонити &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Заборонити Macromedia® Flash®">
+<!ENTITY noscriptForbidPlugins "Заборонити інші модулі">
+<!ENTITY noscriptReloadWarn "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²ÑтуплÑÑ‚ÑŒ у Ñилу на новій Ñторінці або піÑÐ»Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ (вручну)">
+<!ENTITY noscriptConfirmUnblock "Питати Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ´ тимчаÑовим розблокуваннÑм об’єкту">
+<!ENTITY noscriptStatusLabel "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð² Ñ€Ñдку ÑтатуÑу">
+<!ENTITY noscriptForbidBookmarklets "Заборонити Bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Показати Ñ€Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ñ–ÐºÐ¾Ð½ÐºÐ¸">
+<!ENTITY noscriptTruncateTitle "ВідÑікати заголовки документів">
+<!ENTITY noscriptFixLinks "Пробувати виправлÑти поÑÐ¸Ð»Ð°Ð½Ð½Ñ JavaScript">
+<!ENTITY noscriptAllowBookmarks "ДозволÑти вÑім Ñайтам знайденим в закладках">
+<!ENTITY noscriptAllowViaBookmarks "Дозволити Ñайти, відкриті через закладки">
+<!ENTITY noscriptAllowPing "Дозволити &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "Дозволити локальні поÑиланнÑ">
+<!ENTITY noscriptForbidPing "Заборонити &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Заборонити Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ META в елементах &lt;noscript&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "M">
+<!ENTITY noscriptWhitelist "Білий ÑпиÑок">
+<!ENTITY noscriptPermissions "Дозволи">
+<!ENTITY noscriptRefresh "ОновленнÑ">
+<!ENTITY noscriptNotifications "СповіщеннÑ">
+<!ENTITY noscriptToolbarToggle "ÐšÐ»Ð°Ñ†Ð°Ð½Ð½Ñ Ð»Ñ–Ð²Ð¾ÑŽ клавішею мишки по кнопці NoScript перемикає дозволи Ð´Ð»Ñ Ð¿Ð¾Ñ‚Ð¾Ñ‡Ð½Ð¾Ð³Ð¾ Ñайту верхнього рівнÑ">
+<!ENTITY noscriptTrusted "Довірені">
+<!ENTITY noscriptUntrusted "Ðедовірені">
+<!ENTITY noscriptUnknown "Ðевідомий">
+<!ENTITY noscriptAdd "Додати">
+<!ENTITY noscriptAdd.accesskey "о">
+<!ENTITY noscriptClose "Закрити">
+<!ENTITY noscriptSiteManager "Менеджер Сайтів">
+<!ENTITY noscriptSecurityManager "Менеджер Безпеки">
+<!ENTITY noscriptPolicies "ВподобаннÑ">
+<!ENTITY noscriptDefaultPolicies "Типові вподобаннÑ">
+<!ENTITY noscriptSitePolicies "Ð’Ð¿Ð¾Ð´Ð¾Ð±Ð°Ð½Ð½Ñ Ð¿Ð¾ окремих Ñайтах">
+<!ENTITY noscriptNselNever "Приховати елементи &lt;noscript&gt;">
+<!ENTITY noscriptNselForce "Показати елементи &lt;noscript&gt; при заблокованому &lt;SCRIPT&gt;">
+<!ENTITY noscriptAutoAllowTopLevel "ТимчаÑово дозволити за умовчаннÑм Ñайти верхнього рівнÑ">
+<!ENTITY noscriptDescription "Додатковий захиÑÑ‚ Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Firefox: NoScript дозволÑÑ” JavaScript, Java (та інші модулі) лише на довірених Ñайтах по вашому вибору. (Скажімо, Ñайт вашого банка). Такий превентивний підхід «білого ÑпиÑку» дозволÑÑ” вберегтиÑÑŒ від уÑÑ–Ñ… вразливоÑтей (відомих та навіть невідомих!) без втрати функціональноÑті… Знавці погодÑÑ‚ÑŒÑÑ: Firefox з додатком NoScript дійÑно безпечніший :-)">
+<!ENTITY noscriptOptBlockCssScanners "Блокувати оÑновані на CSS Ñканери">
+<!ENTITY noscriptOptFilterXGet "Вичищати підозрілі міжÑайтові запити">
+<!ENTITY noscriptOptFilterXPost "Перетворювати міжÑайтові POST запити у GET запити без даних">
+<!ENTITY noscriptShowConsole "Показати КонÑоль…">
+<!ENTITY noscriptShowConsole.accesskey "К">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS FAQ...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "Ðебезпечне перезавантаженнÑ">
+<!ENTITY noscriptUnsafeReload.accesskey "п">
+<!ENTITY noscriptXssExceptions "ВинÑтки у захиÑÑ‚Ñ– від XSS">
+<!ENTITY noscriptXssExceptions.description "МіÑÑ†Ñ Ñ‰Ð¾ підходÑÑ‚ÑŒ під ці регулÑрні вирази ÐЕ будуть захищені від XSS">
+<!ENTITY noscriptMatchSample "Зразок відповідноÑÑ‚Ñ– шаблону:">
+<!ENTITY noscriptReset "Відновити">
+<!ENTITY noscriptReset.accesskey "в">
+<!ENTITY noscriptResetDef "Відновити до початкових налаштувань">
+<!ENTITY noscriptResetDef.accesskey "н">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Відкликати тимчаÑові дозволи">
+<!ENTITY noscriptRevokeTemp.accesskey "Ñ‚">
+<!ENTITY noscriptNoUntrustedPlaceholder "Ðе показувати замінник Ð´Ð»Ñ Ñ‚Ð¸Ñ… об’єктів що походÑÑ‚ÑŒ з недовірених Ñайтів.">
+<!ENTITY noscriptCollapseBlockedObjects "Приховувати заблоковані об’єкти">
+<!ENTITY noscriptExceptions "ВинÑтки…">
+<!ENTITY noscriptBlockedObjects "Заблоковані об’єкти">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Блокувати кожен об’єкт що походить з недовірених Ñайтів">
+<!ENTITY noscriptTempAllowPage "ТимчаÑово дозволити вÑÑŽ цю Ñторінку">
+<!ENTITY noscriptTempAllowPage.accesskey "Т">
+<!ENTITY noscriptAllowPage "Дозволити вÑÑŽ цю Ñторінку">
+<!ENTITY noscriptAllowPage.accesskey "Д">
+<!ENTITY noscriptTempToPerm "Зробити зміни поÑтійними">
+<!ENTITY noscriptTempToPerm.accesskey "п">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS FAQ…">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "Поведінка">
+<!ENTITY noscriptHttps.cookies "Куки">
+<!ENTITY noscriptHttps.description "Заборонити активний веб-зміÑÑ‚ Ñкщо він походить не з безпечного Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ (HTTPS):">
+<!ENTITY noscriptHttps.never "Ðіколи">
+<!ENTITY noscriptHttps.proxy "Коли викориÑтовуєтьÑÑ Ð¿Ñ€Ð¾ÐºÑÑ– (рекомендовано з Tor)">
+<!ENTITY noscriptHttps.always "Завжди">
+<!ENTITY noscriptHttpsForced "Ðав’Ñзувати наÑтупни Ñайтам безпечне Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ (HTTPS):">
+<!ENTITY noscriptHttpsForcedExceptions "Ðіколи не нав’Ñзувати безпечне Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ (HTTPS) на наÑтупних Ñайтах:">
+<!ENTITY noscriptSecureCookies "Дозволити автоматичне безпечне ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÑƒÐºÐ°Ð¼Ð¸">
+<!ENTITY noscriptSecureCookiesForced "ПримуÑити шифрувати вÑÑ– куки, що ÑтавлÑÑ‚ÑŒÑÑ Ñ‡ÐµÑ€ÐµÐ· HTTPS з наÑтупних Ñайтів:">
+<!ENTITY noscriptSecureCookiesExceptions "Ігнорувати небезпечні куки поÑтавлені через HTTPS з наÑтупних Ñайтів:">
+<!ENTITY noscriptClearClickTitle "ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ ClearClick">
+<!ENTITY noscriptClearClickHeader "Потенційна Ñпроба кражі клацань (clickjacking) /підміни інтерфейÑу!">
+<!ENTITY noscriptClearClickDescription "NoScript перехопив взаємодію мишки чи клавіатури з чаÑтково прихованим елементом. Клацніть на малюнку зверху Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð¼Ñ–Ð¶ заÑлоненою та чиÑтою верÑÑ–Ñми.">
+<!ENTITY noscriptClearClickOpt "ЗахиÑÑ‚ Ñторінок ClearClick…">
+<!ENTITY noscriptClearClickReport "Report">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "Report ID:">
+<!ENTITY noscriptTrustedPagesAdj "довірені">
+<!ENTITY noscriptUntrustedPagesAdj "недовірені">
+<!ENTITY noscriptKeepLocked "Продовжувати блокувати цей об’єкт (рекомендовано)">
+<!ENTITY noscriptEmbeddings "Вбудовані об’єкти">
+<!ENTITY noscriptPrev "Попереднє">
+<!ENTITY noscriptNext "ÐаÑтупне">
+<!ENTITY noscriptFrameOptErr.title "This content cannot be displayed in a frame">
+<!ENTITY noscriptFrameOptErr.desc "To protect your security, the publisher of this content does not allow it to be displayed in a frame.">
+<!ENTITY noscriptFrameOptErr.link "Click here to open this content in a new window">
+<!ENTITY noscriptBookmarkSync "Backup NoScript configuration in a bookmark for easy synchronization">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptNotifyMeta "Show message about blocked META redirections">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptShowReleaseNotes "Display the release notes on updates">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Rulesets:">
+<!ENTITY ABE.enabled.label "Enable ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "Allow sites to push their own rulesets">
+<!ENTITY ABE.edit.label "Edit…">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "Enable">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "Disable">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "Refresh">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "Uninstall">
+<!ENTITY noscriptRecentBlocked "Recently blocked sites">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/uk/noscript/noscript.properties b/extensions/noscript/chrome/locale/uk/noscript/noscript.properties
new file mode 100644
index 0000000..b6a5af8
--- /dev/null
+++ b/extensions/noscript/chrome/locale/uk/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Дозволити JavaScript повніÑÑ‚ÑŽ (небезпечно)
+forbidGlobal=Заборонити JavaScript повніÑÑ‚ÑŽ (рекомендуєтьÑÑ)
+allowLocal=Дозволити %S
+allowTemp=ТимчаÑово дозволити %S
+forbidLocal=Заборонити %S
+allowed.glb=Ðебезпека! JavaScript повніÑÑ‚ÑŽ дозволений
+allowed.yes=Ð’ даний Ñ‡Ð°Ñ JavaScript дозволений
+allowed.prt=JavaScript чаÑтково дозволений
+allowed.no=Ð’ даний Ñ‡Ð°Ñ JavaScript заборонений
+global.warning.title=Увага!
+global.warning.text=JavaScript буде повніÑÑ‚ÑŽ дозволений (Ð´Ð»Ñ Ð²ÑÑ–Ñ… Ñайтів).\n Це потенційно небезпечна діÑ.\nВи дійÑно бажаєте продовжити?
+audio.samples=Зразки аудіо
+confirm=Ви впевнені?
+alwaysAsk=Завжди питати підтвердженнÑ
+notifyHide=Приховувати піÑÐ»Ñ %S Ñекунд
+trust=ДовірÑти %S
+distrust=Позначити %S Ñк недовірений
+untrustedOrigin=недовірене походженнÑ
+xss.notify.generic=NoScript відфільтрував потенційну міжÑайтову атаку (XSS) з %S. Технічні подробиці занеÑено в КонÑоль.
+xss.notify.showConsole=Показати КонÑоль…
+xss.notify.showConsole.accessKey=К
+xss.reason.filterXGet=Вичищено підозрілий запит. Початковий URL [%1$S] запитано з [%2$S]. Вичищений URL: [%3$S].
+xss.reason.filterXGetRef=Вичищено підозрілий реферер. URL [%1$S] запитано з [%2$S]. Підозрілий реферер: [%3$S].
+xss.reason.filterXPost=Вичищно підозріле Ð²Ñ–Ð´Ð²Ñ–Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð° [%1$S] з [%2$S]: транÑформовано в Ñуто завантажувальний запит GET.
+unsafeReload.warning=ÐЕБЕЗПЕЧÐЕ перезавантаженнÑ\n\n%1$S [%2$S]\n\nЗ [%3$S]\n\nNoScript ÐЕ захиÑтить цей запит!\n
+metaRefresh.notify=NoScript заблокував <META> Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ñтавлене в Ñередині елемента <NOSCRIPT>: %S через %S Ñекунд.
+metaRefresh.notify.follow=Слідувати за перенаправленнÑм
+metaRefresh.notify.follow.accessKey=С
+notify.options=ÐалаштуваннÑ
+notify.options.accessKey=Ð
+reset.title=Скинути NoScript
+reset.warning=ВСІ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ NoScript та переліки дозволів будуть негайно Ñкинуті на початкові значеннÑ.\nЦю дію не можна буде повернути.\nХочете продовжити?
+bookmarkSync.title=NoScript Configuration Bookmark
+bookmarkSync.message=This bookmark is NOT meant to be opened, but to be synchronized using a service such as Weave or the XMarks extension.
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+bookmarkSync.confirm=NoScript has found a configuration bookmark seemingly saved on\n%S.\nDo you really want to overwrite your local NoScript configuration with this bookmark's content?
+ABE.notify=Request %1$S filtered by ABE: <%2$S> %3$S
+ABE.chooseEditor=Please choose a text editor for ABE rulesets
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Allow all from %S
+allowTempFrom=Temporarily allow all from %S
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/vi/noscript/about.properties b/extensions/noscript/chrome/locale/vi/noscript/about.properties
new file mode 100644
index 0000000..4a0f1b1
--- /dev/null
+++ b/extensions/noscript/chrome/locale/vi/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Thêm sá»± bảo vệ cho Firefox của bạn: NoScript chỉ cho phép JavaScript, Java (và các plugins khác) được chạy trên những tên miá»n đáng tin mà bạn chá»n (v.d., trang web ngân hàng của bạn). HÆ°á»›ng Ä‘i ngăn chặn trÆ°á»›c dá»±a trên sổ trắng này ngăn chặn việc khai thác lổ há»ng bảo mật (biết trÆ°á»›c và ngay cả chÆ°a biết!) mà không mất Ä‘i tính năng... Các chuyên gia sẽ đồng ý rằng: Firefox thật sá»± an toàn hÆ¡n vá»›i NoScript :-)
+aboutTitle=Thông tin vỠ%S
+extensionContributors=Những ngÆ°á»i đóng góp:
+extensionContributors.tip=Những ngÆ°á»i mà bạn nên cám Æ¡n vì sá»± đóng góp cho phần mở rá»™ng này:
+extensionCreatorLabel=Tác giả:
+changelog=Lưu kí thay đổi
+changelog.tip=Hiển thị lưu kí thay đổi
+license=Giấy phép
+license.tip=Äá»c giấy phép ngÆ°á»i dùng cuối
+logo.tip=Thăm trang nhà của phần mở rộng này
+sponsor.tip=Thăm trang chủ nhà tài trợ
+informaction.tip=Thăm trang chủ của InformAction
+extensionHomepage.tip=Thăm trang chủ của phần mở rộng này
+extensionCreator.tip=Thăm trang chủ của tác giả
+version=Phiên bản %S
diff --git a/extensions/noscript/chrome/locale/vi/noscript/noscript.dtd b/extensions/noscript/chrome/locale/vi/noscript/noscript.dtd
new file mode 100644
index 0000000..51d10e8
--- /dev/null
+++ b/extensions/noscript/chrome/locale/vi/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "Tùy chá»n">
+<!ENTITY noscriptOptions.accesskey "y">
+<!ENTITY noscriptOptionsLong "Tùy chá»n cho NoScript">
+<!ENTITY noscriptAbout "Thông tin vỠNoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "Bạn có thể chỉ định trang web nào được phép chạy script. Gõ địa chỉ hay tên miá»n (v.d. &quot;http://www.nhaccodien.com&quot; hay &quot;nhaccodien.com&quot;) của trang mà bạn muốn cho phép, rồi nhấn Cho phép.">
+<!ENTITY noscriptWebAddress "Äịa chỉ của trang web:">
+<!ENTITY noscriptAllow "Cho phép">
+<!ENTITY noscriptAllow.accesskey "C">
+<!ENTITY noscriptForbid "Ngăn cấm">
+<!ENTITY noscriptForbid.accesskey "N">
+<!ENTITY noscriptTrust "Äánh dấu Tin cậy">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "Äánh dấu Không tin cậy">
+<!ENTITY noscriptUntrust.accesskey "K">
+<!ENTITY noscriptRemoveSelected "Xóa Trang Äã Chá»n">
+<!ENTITY noscriptGloballyEnabled "Script Äược Cho Phép Ở Má»i Trang (nguy hiểm)">
+<!ENTITY noscriptAutoReload "Tá»± Ä‘á»™ng tải lại trang bị ảnh hưởng khi quyá»n hạn thay đổi">
+<!ENTITY noscriptGeneral "Tổng quát">
+<!ENTITY noscriptAppearance "Giao diện">
+<!ENTITY noscriptShow "Hiển thị...">
+<!ENTITY noscriptCtxMenu "Trình đơn ngữ cảnh">
+<!ENTITY noscriptStatusIcon "Biểu tượng trong thanh trạng thái">
+<!ENTITY noscriptFullAddr "Äịa chỉ đầy đủ (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Tên miá»n đầy đủ (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Tên miá»n cấp hai (noscript.net)">
+<!ENTITY noscriptTempCmd "Tạm thá»i cho phép [...]">
+<!ENTITY noscriptSound "Âm thanh cho biết khi script bị chặn">
+<!ENTITY noscriptImport "Nhập">
+<!ENTITY noscriptImport.accesskey "N">
+<!ENTITY noscriptExport "Xuất">
+<!ENTITY noscriptExport.accesskey "X">
+<!ENTITY noscriptNotify "Hiện thông tin vỠscript bị chặn">
+<!ENTITY noscriptNotify.bottom "Äặt thông tin ở bên dÆ°á»›i">
+<!ENTITY noscriptSound.choose "Chá»n">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "Nghe">
+<!ENTITY noscriptSound.play.accesskey "e">
+<!ENTITY noscriptSound.reset "ÄÆ°a vá» mặc định">
+<!ENTITY noscriptSound.reset.accesskey "v">
+<!ENTITY noscriptAdvanced "Nâng cao">
+<!ENTITY noscriptAdditionalPermissions "Quyá»n hạn bổ sung cho các trang tin cậy">
+<!ENTITY noscriptAllowClipboard "Cho phép chép và dán văn bản đa dạng từ clipboard bên ngoài">
+<!ENTITY noscriptAdditionalRestrictions "Những hạn chế bổ sung cho các trang không tin cậy">
+<!ENTITY noscriptPlugins "Plugins">
+<!ENTITY noscriptContentBlocker "Äồng thá»i áp dụng những hạn chế này cho các trang tin cậy">
+<!ENTITY noscriptForbidJava "Cấm Java™">
+<!ENTITY noscriptForbidXSLT "Cấm XSLT">
+<!ENTITY noscriptForbidSilverlight "Cấm Microsoft® Silverlight™">
+<!ENTITY noscriptForbidIFrames "Cấm &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "Cấm &lt;FRAMES&gt;">
+<!ENTITY noscriptForbidFonts "Cấm @font-face">
+<!ENTITY noscriptForbidWebGL "Cấm WebGL">
+<!ENTITY noscriptForbidMedia "Cấm &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "Cấm Macromedia® Flash®">
+<!ENTITY noscriptForbidPlugins "Cấm các plugins khác">
+<!ENTITY noscriptReloadWarn "Những tùy chá»n này sẽ có hiệu quả trong trang má»›i hay trang được tải lại">
+<!ENTITY noscriptConfirmUnblock "Há»i xác nhận trÆ°á»›c khi tạm thá»i không chặn má»™t đối tượng">
+<!ENTITY noscriptStatusLabel "Nhãn cho thanh trạng thái">
+<!ENTITY noscriptForbidBookmarklets "Cấm bookmarklets">
+<!ENTITY noscriptShowPlaceholder "Hiển thị biểu tượng giữ chỗ">
+<!ENTITY noscriptTruncateTitle "Cắt ngắn tựa đỠcủa tài liệu">
+<!ENTITY noscriptFixLinks "Cố gắng sửa liên kết JavaScript">
+<!ENTITY noscriptAllowBookmarks "Cho phép các trang được mở qua Äánh dấu">
+<!ENTITY noscriptAllowViaBookmarks "Cho phép các trang được mở qua Äánh dấu">
+<!ENTITY noscriptAllowPing "Cho phép &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "Cho phép các liên kết nội tại">
+<!ENTITY noscriptForbidPing "Cấm &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "Cấm đổi hướng bằng META trong các phần tử &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "M">
+<!ENTITY noscriptNotifyMeta "Hiện thông báo vỠcác chuyển hướng META bị chặn">
+<!ENTITY noscriptNotifyMeta.accesskey "y">
+<!ENTITY noscriptWhitelist "Sổ trắng">
+<!ENTITY noscriptPermissions "Quyá»n hạn">
+<!ENTITY noscriptRefresh "Tải lại">
+<!ENTITY noscriptNotifications "Khai báo">
+<!ENTITY noscriptToolbarToggle "Nhấn chuá»™t trái vào nút NoScript trên thanh công cụ để tắt/mở quyá»n hạn cho trang miá»n cấp má»™t hiện tại">
+<!ENTITY noscriptTrusted "Tin cậy">
+<!ENTITY noscriptUntrusted "Không tin cậy">
+<!ENTITY noscriptUnknown "Không biết">
+<!ENTITY noscriptAdd "Thêm">
+<!ENTITY noscriptAdd.accesskey "T">
+<!ENTITY noscriptClose "Äóng">
+<!ENTITY noscriptSiteManager "Quản lí Trang">
+<!ENTITY noscriptSecurityManager "Quản lí Bảo mật">
+<!ENTITY noscriptPolicies "Chính sách">
+<!ENTITY noscriptDefaultPolicies "Chính sách Mặc định">
+<!ENTITY noscriptSitePolicies "Chính sách Cho trang Riêng biệt">
+<!ENTITY noscriptNselNever "Ẩn các phần tử &lt;NOSCRIPT&gt;">
+<!ENTITY noscriptNselForce "Hiển thị phần tử &lt;noscript&gt; đi sau một phần tử &lt;SCRIPT&gt; bị chặn">
+<!ENTITY noscriptAutoAllowTopLevel "Tạm thá»i cho phép trang miá»n cấp má»™t theo mặc định">
+<!ENTITY noscriptDescription "Thêm sá»± bảo vệ cho Firefox của bạn: NoScript chỉ cho phép JavaScript, Java (và các plugins khác) được chạy trên những tên miá»n đáng tin mà bạn chá»n (v.d., trang web ngân hàng của bạn). HÆ°á»›ng Ä‘i chặn trÆ°á»›c dá»±a trên sổ trắng này ngăn chặn việc khai thác lổ há»ng bảo mật (biết trÆ°á»›c và ngay cả chÆ°a biết!) mà không mất Ä‘i tính năng... Các chuyên gia sẽ đồng ý rằng: Firefox thật sá»± an toàn hÆ¡n vá»›i NoScript :-)">
+<!ENTITY noscriptOptBlockCssScanners "Chặn các trình quét dựa trên CSS">
+<!ENTITY noscriptOptFilterXGet "Làm sạch các yêu cầu cross-site đáng ngá»">
+<!ENTITY noscriptOptFilterXPost "Äổi các yêu cầu dạng POST cross-site sang yêu cầu dạng GET">
+<!ENTITY noscriptShowConsole "Hiển thị Bảng kiểm soát...">
+<!ENTITY noscriptShowConsole.accesskey "H">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS Câu Há»i ThÆ°á»ng Gặp...">
+<!ENTITY noscriptXssFaq.accesskey "C">
+<!ENTITY noscriptUnsafeReload "Tải Lại Không An Toàn">
+<!ENTITY noscriptUnsafeReload.accesskey "L">
+<!ENTITY noscriptXssExceptions "Các Ngoại Lệ Phòng Ngừa Anti-XSS">
+<!ENTITY noscriptXssExceptions.description "Äích đến phù hợp vá»›i các biểu thức quy tắc này sẽ KHÔNG được bảo vệ tránh khá»i XSS.">
+<!ENTITY noscriptMatchSample "Mẫu phù hợp:">
+<!ENTITY noscriptReset "Hoàn lại">
+<!ENTITY noscriptReset.accesskey "H">
+<!ENTITY noscriptResetDef "Hoàn lại vỠmặc định">
+<!ENTITY noscriptResetDef.accesskey "v">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "Hủy Bá» Quyá»n Hạn Tạm Thá»i">
+<!ENTITY noscriptRevokeTemp.accesskey "Q">
+<!ENTITY noscriptNoUntrustedPlaceholder "Không có phần giữ chỗ nào cho các đối tượng đến từ các trang bị đánh dấu không tin cậy.">
+<!ENTITY noscriptCollapseBlockedObjects "Thu gá»n các đối tượng bị chặn">
+<!ENTITY noscriptExceptions "Ngoại lệ...">
+<!ENTITY noscriptBlockedObjects "Các đối tượng bị Chặn">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "Chặn má»i đối tượng đến từ má»™t trang bị đánh dấu không tin cậy.">
+<!ENTITY noscriptTempAllowPage "Tạm thá»i cho phép tất cả trên trang này">
+<!ENTITY noscriptTempAllowPage.accesskey "m">
+<!ENTITY noscriptAllowPage "Cho phép tất cả trên trang này">
+<!ENTITY noscriptAllowPage.accesskey "o">
+<!ENTITY noscriptTempToPerm "Äặt quyá»n hạn vÄ©nh viá»…n cho trang này">
+<!ENTITY noscriptTempToPerm.accesskey "q">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS Câu Há»i ThÆ°á»ng Gặp...">
+<!ENTITY noscriptHttpsFaq.accesskey "S">
+<!ENTITY noscriptHttps.behavior "Hành vi">
+<!ENTITY noscriptHttps.cookies "Cookie">
+<!ENTITY noscriptHttps.description "Cấm nội dung web hoạt động trừ khi nó đến từ một kết nối an toàn (HTTPS):">
+<!ENTITY noscriptHttps.never "Không bao giá»">
+<!ENTITY noscriptHttps.proxy "Khi sử dụng một proxy (khuyên dùng cho Tor)">
+<!ENTITY noscriptHttps.always "Luôn luôn">
+<!ENTITY noscriptHttpsForced "Cấm các trang sau sử dụng kết nối an toàn (HTTPS):">
+<!ENTITY noscriptHttpsForcedExceptions "Không bao giỠbắt buộc kết nối an toàn (HTTPS) cho các trang sau:">
+<!ENTITY noscriptSecureCookies "Kích Hoạt Việc Quản Lí Cookie An Toàn Tá»± Äá»™ng">
+<!ENTITY noscriptSecureCookiesForced "Bắt buộc mã hóa đối với tất cả cookie được tạo qua HTTPS bởi các trang sau:">
+<!ENTITY noscriptSecureCookiesExceptions "BỠqua các cookie không an toàn được tạo qua HTTPS bởi các trang sau:">
+<!ENTITY noscriptClearClickTitle "Cảnh Báo XóaNhấn">
+<!ENTITY noscriptClearClickHeader "Tiá»m Ẩn Hành Äá»™ng Chuyển HÆ°á»›ng Giao Diện / Chiếm Quyá»n Nhấp Chuá»™t!">
+<!ENTITY noscriptClearClickDescription "NoScript chặn một tương tác chuột hoặc bàn phím bởi một phần tử bị ẩn một phần. Nhấn lên hình ở trên để chuyển qua lại giữa phiên bản ban đầu và phiên bản đã chặn.">
+<!ENTITY noscriptClearClickOpt "Phòng ngừa XóaNhấn trên trang...">
+<!ENTITY noscriptClearClickReport "Báo cáo">
+<!ENTITY noscriptClearClickReport.accesskey "B">
+<!ENTITY noscriptClearClickReportId "ID Báo cáo:">
+<!ENTITY noscriptTrustedPagesAdj "tin cậy">
+<!ENTITY noscriptUntrustedPagesAdj "không tin cậy">
+<!ENTITY noscriptKeepLocked "Khóa phần tử này (khuyên dùng)">
+<!ENTITY noscriptEmbeddings "Các Äối Tượng Äược Nhúng">
+<!ENTITY noscriptPrev "TrÆ°á»›c">
+<!ENTITY noscriptNext "Tiếp">
+<!ENTITY noscriptFrameOptErr.title "Nội dung này không thể được hiển thị trong một frame">
+<!ENTITY noscriptFrameOptErr.desc "Äể bảo vệ bạn, ngÆ°á»i xuất bản ná»™i dung này không cho phép nó được hiển thị trong má»™t frame.">
+<!ENTITY noscriptFrameOptErr.link "Nhấn vào đây để mở nội dung này trong một cửa sổ mới">
+<!ENTITY noscriptBookmarkSync "Sao lưu cấu hình NoScript trong một trang đánh dấu để đồng bộ hóa dễ dàng">
+<!ENTITY noscriptShowReleaseNotes "Hiển thị ghi chú phát hành khi cập nhật">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "Bộ lệnh:">
+<!ENTITY ABE.enabled.label "Bật ABE (Application Boundaries Enforcer - Bắt buộc Biên giới Chương trình)">
+<!ENTITY ABE.siteEnabled.label "Cho phép các trang đưa ra bộ lệnh riêng của chúng">
+<!ENTITY ABE.edit.label "Chỉnh sửa...">
+<!ENTITY ABE.edit.accesskey "C">
+<!ENTITY ABE.enable.label "Bật">
+<!ENTITY ABE.enable.accesskey "B">
+<!ENTITY ABE.disable.label "Vô hiệu hóa">
+<!ENTITY ABE.disable.accesskey "V">
+<!ENTITY ABE.refresh.label "Làm tươi">
+<!ENTITY ABE.refresh.accesskey "L">
+<!ENTITY noscriptUninstall "Gỡ bá»">
+<!ENTITY noscriptRecentBlocked "Các trang bị chặn gần đây">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptExternalFilters "External Filters">
+<!ENTITY noscriptEF.enable "Enable external filters">
+<!ENTITY noscriptEF.add "New Filter…">
+<!ENTITY noscriptEF.executable "Executable file:">
+<!ENTITY noscriptEF.browse "Browse…">
+<!ENTITY noscriptEF.contentType "Content type (MIME) to be filtered (exact match or regular expression):">
+<!ENTITY noscriptEF.exceptions "Do not filter objects coming from these sites:">
+<!ENTITY noscriptEF.remove "Remove">
+<!ENTITY noscriptPreset "Security Level">
+<!ENTITY noscriptPreset.off "Off (are you serious?!)">
+<!ENTITY noscriptPreset.low "Easy going (Blacklist + Web Security)">
+<!ENTITY noscriptPreset.medium "Classic (Whitelist + Web Security)">
+<!ENTITY noscriptPreset.high "Fortress (Full lockdown)">
+<!ENTITY noscript.hoverUI "Open permissions menu when mouse hovers over NoScript's icon">
+<!ENTITY noscriptDonate "Donate">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/vi/noscript/noscript.properties b/extensions/noscript/chrome/locale/vi/noscript/noscript.properties
new file mode 100644
index 0000000..73ee049
--- /dev/null
+++ b/extensions/noscript/chrome/locale/vi/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=Cho Phép Script Trên Má»i Trang (nguy hiểm)
+forbidGlobal=Cấm Phép Script Trên Má»i Trang (nên làm vậy)
+allowLocal=Cho phép %S
+allowTemp=Tạm thá»i cho phép %S
+forbidLocal=Cấm %S
+allowed.glb=Nguy hiểm! Script Äược Phép Trên Má»i Trang
+allowed.yes=Các Script Äang Äược Cho Phép
+allowed.prt=Các Script Äang Äược Cho Phép Má»™t Phần
+allowed.no=Các Script Äang Bị Cấm
+global.warning.title=Cảnh Báo!
+global.warning.text=Script sẽ được phép chạy ở má»i nÆ¡i (ở má»i trang).\n Äây là má»™t thao tác nguy hiểm.\nBạn có thật sá»± muốn tiếp tục không?
+audio.samples=Âm thanh mẫu
+confirm=Bạn có chắc không?
+alwaysAsk=Luôn luôn há»i xác nhận
+notifyHide=Ẩn sau %S giây
+trust=Tin tưởng %S
+distrust=Äánh dấu %S không tin cậy
+untrustedOrigin=một nguồn không tin cậy
+xss.notify.generic=NoScript đã lá»c má»™t ná»— lá»±c cross-site scripting (XSS) từ %S. Các chi tiết kÄ© thuật đã được lÆ°u trong Bảng Kiểm Soát.
+xss.notify.showConsole=Hiển thị Bảng kiểm soát...
+xss.notify.showConsole.accessKey=H
+xss.reason.filterXGet=Äã làm sạch yêu cầu đáng ngá». URL nguyên gốc [%1$S] được yêu cầu từ [%2$S]. URL được làm sạch: [%3$S].
+xss.reason.filterXGetRef=Äã làm sạch liên kết chỉ hÆ°á»›ng yêu cầu đáng ngá». URL [%1$S] được yêu cầu từ [%2$S]. Liên kết chỉ hÆ°á»›ng được làm sạch: [%3$S].
+xss.reason.filterXPost=Äã làm sạch phần tải lên đáng ngá» [%1$S] từ [%2$S]: được đổi sang dạng yêu cầu GET chỉ-tải-xuống.
+unsafeReload.warning=Tải lại MỘT CÃCH KHÔNG AN TOÀN má»™t\n\n%1$S [%2$S] đáng ngá»\n\nTỪ[%3$S]\n\nNoScript sẽ KHÔNG bảo vệ yêu cầu này!\n
+metaRefresh.notify=NoScript đã chặn một yêu cầu đổi hướng dạng <META> trong một phần tử <NOSCRIPT>: %S trong %S giây.
+metaRefresh.notify.follow=Äi theo Yêu cầu đổi hÆ°á»›ng
+metaRefresh.notify.follow.accessKey=i
+notify.options=Tùy Chá»n
+notify.options.accessKey=y
+reset.title=Trở Vá» Mặc Äịnh
+reset.warning=TẤT CẢ các tùy chá»n và quyá»n hạn cho các trang sẽ trở vá» các giá trị mặc định ngay lập tức.\nThao tác này không thể phục hồi.\nBạn có muốn tiếp tục không?
+bookmarkSync.title=Äánh dấu Cấu hình NoScript
+bookmarkSync.message=Trang đánh dấu này KHÔNG được mở, mà được đồng bộ hóa bằng một dịch vụ như Weave hoặc phần mở rộng XMarks.
+bookmarkSync.confirm=NoScript tìm thấy một trang đánh dấu cấu hình được lưu trên\n%S.\nBạn có thật sự muốn ghi đè cấu hình NoScript trong máy bằng nội dung của trang đánh dấu này không?
+ABE.notify=Yêu cầu %1$S bị lá»c bởi ABE: <%2$S> %3$S
+ABE.chooseEditor=Vui lòng chá»n má»™t trình soạn thảo cho bá»™ lệnh ABE
+allowFrom=Cho phép tất cả từ %S
+allowTempFrom=Tạm thá»i cho phép tất cả từ %S
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+ABE.syntaxError=Syntax error in ABE ruleset!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+siteInfo.confirm=You're about to ask for information about the "%1$S" site\nby submitting a query to %2$S.\nDo you want to continue?
+siteInfo.tooltip=Middle-click or shift+click for site info...
+ef.activate=Filter %S
+ef.options=%S options…
+ef.newName=Enter the name of the new filter:
+ef.locateExe=Select the executable file for the %S filter
+disable=Disable %S
+disable.accessKey=D
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/zh-CN/noscript/about.properties b/extensions/noscript/chrome/locale/zh-CN/noscript/about.properties
new file mode 100644
index 0000000..5654aed
--- /dev/null
+++ b/extensions/noscript/chrome/locale/zh-CN/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=为您的 Firefox æä¾›é¢å¤–ä¿æŠ¤: NoScript åªå…许在您选择的信任域(例如您的家庭银行网站)上执行 JavaScriptã€Java(和其他æ’件)。该白åå•åŸºäºŽæŠ¢å…ˆé˜»æ­¢æœºåˆ¶ï¼Œåœ¨ä¸æŸå¤±ä»»ä½•åŠŸèƒ½çš„å‰æ下,防止利用已知或未知安全æ¼æ´žçš„攻击。专家们åŒæ„:拥有 NoScript çš„ Firefox 更安全 :-)
+aboutTitle=关于 %S
+extensionContributors=贡献者:
+extensionContributors.tip=对于此扩展你应该感谢的人
+extensionCreatorLabel=作者:
+changelog=更新日志
+changelog.tip=显示更新日志
+license=许å¯åè®®
+license.tip=阅读最终用户åè®®
+logo.tip=访问扩展主页
+sponsor.tip=访问赞助者主页
+informaction.tip=访问 InformAction 主页
+extensionHomepage.tip=访问扩展主页
+extensionCreator.tip=访问作者主页
+version=版本 %S
diff --git a/extensions/noscript/chrome/locale/zh-CN/noscript/noscript.dtd b/extensions/noscript/chrome/locale/zh-CN/noscript/noscript.dtd
new file mode 100644
index 0000000..7c12980
--- /dev/null
+++ b/extensions/noscript/chrome/locale/zh-CN/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "选项...">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript 选项">
+<!ENTITY noscriptAbout "关于 NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "您å¯ä»¥æŒ‡å®šå…许执行脚本的网站。请输入您想è¦å…许的网站地å€æˆ–域å(例如: “http://www.site.comâ€æˆ–者“site.comâ€)然åŽå•å‡»â€œå…许â€ã€‚">
+<!ENTITY noscriptWebAddress "网站地å€:">
+<!ENTITY noscriptAllow "å…许">
+<!ENTITY noscriptAllow.accesskey "l">
+<!ENTITY noscriptForbid "ç¦æ­¢">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "标记为å¯ä¿¡çš„">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "标记为ä¸å¯ä¿¡çš„">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "删除选择的网站">
+<!ENTITY noscriptGloballyEnabled "全局å…许脚本(å±é™©)">
+<!ENTITY noscriptAutoReload "更改许å¯è®¾ç½®åŽè‡ªåŠ¨é‡æ–°è½½å…¥ç›¸å…³é¡µé¢">
+<!ENTITY noscriptGeneral "常规">
+<!ENTITY noscriptAppearance "外观">
+<!ENTITY noscriptShow "显示...">
+<!ENTITY noscriptCtxMenu "å³é”®èœå•">
+<!ENTITY noscriptStatusIcon "状æ€æ å›¾æ ‡">
+<!ENTITY noscriptFullAddr "å®Œæ•´åœ°å€ (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "全域å (www.noscript.net)">
+<!ENTITY noscriptBaseDom "二级域å (noscript.net)">
+<!ENTITY noscriptTempCmd "临时å…许 [...]">
+<!ENTITY noscriptSound "脚本被阻止时å‘出声音">
+<!ENTITY noscriptImport "导入">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "导出">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "显示被阻止脚本的信æ¯">
+<!ENTITY noscriptNotify.bottom "在æµè§ˆå™¨åº•éƒ¨æ˜¾ç¤ºä¿¡æ¯">
+<!ENTITY noscriptSound.choose "选择">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "播放">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "æ¢å¤é»˜è®¤è®¾ç½®">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "高级">
+<!ENTITY noscriptAdditionalPermissions "对信任站点的é¢å¤–许å¯">
+<!ENTITY noscriptAllowClipboard "å…许由外部剪贴æ¿è¿›è¡Œå¯Œæ–‡æœ¬(rich text)çš„å¤åˆ¶å’Œç²˜è´´">
+<!ENTITY noscriptAdditionalRestrictions "对ä¸ä¿¡ä»»ç«™ç‚¹çš„é¢å¤–é™åˆ¶">
+<!ENTITY noscriptPlugins "æ’件">
+<!ENTITY noscriptContentBlocker "对å—信任站点ä»ç„¶åº”用这些é™åˆ¶">
+<!ENTITY noscriptForbidJava "ç¦æ­¢ Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "ç¦æ­¢ XSLT">
+<!ENTITY noscriptForbidSilverlight "ç¦æ­¢ Microsoft® Silverlightâ„¢">
+<!ENTITY noscriptForbidIFrames "ç¦æ­¢ &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "ç¦æ­¢ &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "ç¦æ­¢ @font-face">
+<!ENTITY noscriptForbidWebGL "ç¦æ­¢ WebGL">
+<!ENTITY noscriptForbidMedia "ç¦æ­¢ &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "ç¦æ­¢ Adobe® Flash®">
+<!ENTITY noscriptForbidPlugins "ç¦æ­¢å…¶ä»–æ’件">
+<!ENTITY noscriptReloadWarn "下é¢è¿™äº›é€‰é¡¹å°†åœ¨æ–°é¡µé¢ä¸­æˆ–手动é‡æ–°è½½å…¥åŽç”Ÿæ•ˆã€‚">
+<!ENTITY noscriptConfirmUnblock "需è¦ç¡®è®¤åŽå†å…许æŸäº›ä¸´æ—¶é¡¹ç›®">
+<!ENTITY noscriptStatusLabel "状æ€æ æ ‡ç­¾">
+<!ENTITY noscriptForbidBookmarklets "ç¦æ­¢ Bookmarklets">
+<!ENTITY noscriptShowPlaceholder "显示图åƒå ä½ç¬¦">
+<!ENTITY noscriptTruncateTitle "截短文档标题">
+<!ENTITY noscriptFixLinks "å°è¯•å®šä½ JavaScript 链接">
+<!ENTITY noscriptAllowBookmarks "å…许通过书签打开的网站(脚本)">
+<!ENTITY noscriptAllowViaBookmarks "å…许通过书签打开的网站(脚本)">
+<!ENTITY noscriptAllowPing "å…许 &lt;A PING...&gt;">
+<!ENTITY noscriptAllowLocalLinks "å…许本地的链接">
+<!ENTITY noscriptForbidPing "ç¦æ­¢ &lt;A PING...&gt;">
+<!ENTITY noscriptForbidMetaRefresh "ç¦æ­¢ &lt;NOSCRIPT&gt; 元素内的 META é‡å®šå‘">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "显示关于被å±è”½çš„ META é‡å®šå‘ä¿¡æ¯">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "白åå•">
+<!ENTITY noscriptPermissions "许å¯">
+<!ENTITY noscriptRefresh "刷新">
+<!ENTITY noscriptNotifications "通知">
+<!ENTITY noscriptToolbarToggle "左键å•å‡» NoScript 工具æ æŒ‰é’®åˆ‡æ¢å¯¹å½“å‰é¡¶å±‚站点的许å¯">
+<!ENTITY noscriptTrusted "å¯ä¿¡ä»»çš„">
+<!ENTITY noscriptUntrusted "ä¸å¯ä¿¡ä»»çš„">
+<!ENTITY noscriptUnknown "未知">
+<!ENTITY noscriptAdd "添加">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "关闭">
+<!ENTITY noscriptSiteManager "站点管ç†å™¨">
+<!ENTITY noscriptSecurityManager "安全管ç†å™¨">
+<!ENTITY noscriptPolicies "ç­–ç•¥">
+<!ENTITY noscriptDefaultPolicies "默认策略">
+<!ENTITY noscriptSitePolicies "站点特殊策略">
+<!ENTITY noscriptNselNever "éšè— &lt;NOSCRIPT&gt; 元素">
+<!ENTITY noscriptNselForce "显示已被å±è”½çš„ &lt;SCRIPT&gt; 标签下的 &lt;NOSCRIPT&gt; 元素">
+<!ENTITY noscriptAutoAllowTopLevel "默认临时å…许顶层站点">
+<!ENTITY noscriptDescription "为您的 Firefox æä¾›é¢å¤–ä¿æŠ¤: NoScript åªå…许在您选择的信任域 (例如您的家庭银行网站) 上执行 JavaScriptã€Java(和其他æ’件)。该白åå•åŸºäºŽæŠ¢å…ˆé˜»æ­¢æœºåˆ¶ï¼Œåœ¨ä¸æŸå¤±ä»»ä½•åŠŸèƒ½çš„å‰æ下,防止利用已知或未知安全æ¼æ´žçš„攻击。专家们åŒæ„:拥有 NoScript çš„ Firefox 更安全 :-)">
+<!ENTITY noscriptOptBlockCssScanners "阻止基于 CSS 的扫æ器">
+<!ENTITY noscriptOptFilterXGet "净化跨站点的å¯ç–‘请求">
+<!ENTITY noscriptOptFilterXPost "把跨站点 POST 请求转æ¢ä¸ºæœ€å°‘æ•°æ®çš„ GET 请求">
+<!ENTITY noscriptShowConsole "显示控制å°...">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS 问答...">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "éžå®‰å…¨çš„é‡æ–°è½½å…¥">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "å XSS ä¿æŠ¤çš„例外情况">
+<!ENTITY noscriptXssExceptions.description "匹é…以下正则表达å¼çš„目标将ä¸ä¼šè¢«ä¿æŠ¤ä¸é­å— XSS (跨站脚本攻击)。">
+<!ENTITY noscriptMatchSample "模å¼åŒ¹é…示例:">
+<!ENTITY noscriptReset "é‡ç½®">
+<!ENTITY noscriptReset.accesskey "S">
+<!ENTITY noscriptResetDef "é‡ç½®ä¸ºé»˜è®¤å€¼">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "撤销临时å…许">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "对于已标记为ä¸å¯ä¿¡ç«™ç‚¹çš„对象ä¸æ˜¾ç¤ºå ä½ç¬¦">
+<!ENTITY noscriptCollapseBlockedObjects "瓦解已阻止的对象">
+<!ENTITY noscriptExceptions "例外...">
+<!ENTITY noscriptBlockedObjects "已阻止的对象">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "阻止æ¥è‡ªå·²ç»æ ‡è®°ä¸ºä¸å¯ä¿¡ç«™ç‚¹çš„任何对象">
+<!ENTITY noscriptTempAllowPage "临时å…许本页é¢æ‰€æœ‰å¯¹è±¡">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "å…许本页é¢æ‰€æœ‰å¯¹è±¡">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "永久å…许页é¢å†…的临时许å¯å¯¹è±¡">
+<!ENTITY noscriptTempToPerm.accesskey "m">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPS 问答...">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "特性">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "ç¦æ­¢æ´»åŠ¨çš„页é¢å…§å®¹é™¤éžå®ƒä¾†è‡ªå®‰å…¨çš„ (HTTPS) 连接:">
+<!ENTITY noscriptHttps.never "从ä¸">
+<!ENTITY noscriptHttps.proxy "当使用代ç†æ—¶ (推èé…åˆ Tor 使用)">
+<!ENTITY noscriptHttps.always "总是">
+<!ENTITY noscriptHttpsForced "强制以下站点使用安全的 (HTTPS) 连接:">
+<!ENTITY noscriptHttpsForcedExceptions "æ°¸ä¸å¼ºåˆ¶ä»¥ä¸‹ç«™ç‚¹ä½¿ç”¨å®‰å…¨çš„ (HTTPS) 连接:">
+<!ENTITY noscriptSecureCookies "å¯ç”¨è‡ªåŠ¨å®‰å…¨ Cookies 管ç†">
+<!ENTITY noscriptSecureCookiesForced "强制以下站点通过 HTTPS 加密所有 Cookies 设置:">
+<!ENTITY noscriptSecureCookiesExceptions "以下站点通过 HTTPS 忽略ä¸å®‰å…¨çš„ Cookies 设置:">
+<!ENTITY noscriptClearClickTitle "ClearClick 警告">
+<!ENTITY noscriptClearClickHeader "æ½œåœ¨çš„ç‚¹å‡»åŠ«æŒ / UI 跳转攻击!">
+<!ENTITY noscriptClearClickDescription "NoScript 拦截了一个部分éšè—元素的鼠标或键盘互动。点击图片切æ¢æ‹¦æˆªå’Œå–消拦截。">
+<!ENTITY noscriptClearClickOpt "å¯ç”¨ ClearClick ä¿æŠ¤äºŽ...">
+<!ENTITY noscriptClearClickReport "报告">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "报告 ID:">
+<!ENTITY noscriptTrustedPagesAdj "å¯ä¿¡ä»»é¡µé¢">
+<!ENTITY noscriptUntrustedPagesAdj "ä¸å¯ä¿¡ä»»é¡µé¢">
+<!ENTITY noscriptKeepLocked "ä¿æŒé”定此元素 (推è)">
+<!ENTITY noscriptEmbeddings "嵌入的对象">
+<!ENTITY noscriptPrev "上一个">
+<!ENTITY noscriptNext "下一个">
+<!ENTITY noscriptFrameOptErr.title "此内容ä¸èƒ½è¢«æ˜¾ç¤ºåœ¨å¸§ä¸­">
+<!ENTITY noscriptFrameOptErr.desc "为了ä¿æŠ¤ä½ çš„安全, 此内容æ供者ä¸å…许它被显示在帧中。">
+<!ENTITY noscriptFrameOptErr.link "点击这里在新窗å£ä¸­æ‰“开此内容">
+<!ENTITY noscriptBookmarkSync "备份 NoScript é…置到书签以便轻æ¾åœ°åŒæ­¥">
+<!ENTITY noscriptShowReleaseNotes "更新时显示å‘布注释">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "规则集:">
+<!ENTITY ABE.enabled.label "å¯ç”¨ ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "å…许网站推é€å®ƒä»¬è‡ªå·±çš„规则集">
+<!ENTITY ABE.edit.label "编辑...">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "å¯ç”¨">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "ç¦ç”¨">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "刷新">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "å¸è½½">
+<!ENTITY noscriptRecentBlocked "最近被å±è”½çš„站点">
+<!ENTITY noscriptExternalFilters "外部过滤器">
+<!ENTITY noscriptEF.enable "å¯ç”¨å¤–部过滤器">
+<!ENTITY noscriptEF.add "新建过滤器…">
+<!ENTITY noscriptEF.executable "å¯æ‰§è¡Œæ–‡ä»¶:">
+<!ENTITY noscriptEF.browse "æµè§ˆâ€¦">
+<!ENTITY noscriptEF.contentType "被过滤的内容类型(MIME)(精确匹é…或使用正则表达å¼ï¼‰">
+<!ENTITY noscriptEF.exceptions "ä¸è¿‡æ»¤æ¥è‡ªè¿™äº›ç½‘站的对象:">
+<!ENTITY noscriptEF.remove "移除">
+<!ENTITY noscriptPreset "安全级别">
+<!ENTITY noscriptPreset.off "关闭(你确定å—?)">
+<!ENTITY noscriptPreset.low "温和(黑åå•+网络安全)">
+<!ENTITY noscriptPreset.medium "典型(白åå•+网络安全)">
+<!ENTITY noscriptPreset.high "严密(全部é”定)">
+<!ENTITY noscript.hoverUI "当鼠标划过 NoScript 图标时打开许å¯èœå•">
+<!ENTITY noscriptDonate "æ助">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/zh-CN/noscript/noscript.properties b/extensions/noscript/chrome/locale/zh-CN/noscript/noscript.properties
new file mode 100644
index 0000000..789d5a8
--- /dev/null
+++ b/extensions/noscript/chrome/locale/zh-CN/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=全局å…许脚本(å±é™©)
+forbidGlobal=全局ç¦æ­¢è„šæœ¬(推è)
+allowLocal=å…许 %S
+allowTemp=临时å…许 %S
+forbidLocal=ç¦æ­¢ %S
+allowed.glb=å±é™©! 全局å…许了脚本
+allowed.yes=当å‰å…许的脚本
+allowed.prt=部分å…许的脚本
+allowed.no=当å‰ç¦æ­¢çš„脚本
+global.warning.title=警告!
+global.warning.text=所有网站都将å…许使用脚本。这是一个会有潜在å±é™©çš„行为。\n您确定è¦è¿™æ ·åšå—?
+audio.samples=音频文件示例
+confirm=您确定�
+alwaysAsk=总是需è¦ç¡®è®¤
+notifyHide=%S 秒钟åŽéšè—
+trust=ä¿¡ä»» %S
+distrust=标记 %S 为ä¸å¯ä¿¡çš„
+untrustedOrigin=ä¸å¯ä¿¡çš„æ¥æº
+xss.notify.generic=NoScript 过滤了一个æ¥è‡ª %S 的潜在跨站点脚本攻击(XSS)。已将详细的技术资料记录到控制å°ã€‚
+xss.notify.showConsole=显示控制å°...
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=净化å¯ç–‘请求。从 [%2$S] 请求的原始 URL [%1$S] 已净化为 [%3$S]。
+xss.reason.filterXGetRef=净化å¯ç–‘的引用请求。从 [%2$S] 请求的引用 URL [%1$S] 已净化为 [%3$S]。
+xss.reason.filterXPost=净化从 [%2$S] 至 [%1$S] çš„å¯ç–‘上传: 已转æ¢ä¸ºä»…下载的 GET 请求。
+unsafeReload.warning=ç›®å‰æ­£ä»Ž\n\n[%3$S]\n\néžå®‰å…¨åœ°é‡æ–°è½½å…¥\n\n%1$S [%2$S]\n\nNoScript ä¸ä¼šä¿æŠ¤è¯¥è¯·æ±‚!\n
+metaRefresh.notify=NoScript 阻止了一个 <NOSCRIPT> 元素内的 <META> é‡å®šå‘: %S 于 %S 秒。
+metaRefresh.notify.follow=å…许é‡å®šå‘
+metaRefresh.notify.follow.accessKey=F
+notify.options=选项
+notify.options.accessKey=O
+reset.title=é‡ç½® NoScript
+reset.warning=所有的 NoScript 首选项和站点许å¯è®¾ç½®å°†è¢«ç«‹å³æ¢å¤ä¸ºé»˜è®¤å€¼ã€‚\n该æ“作无法还原。\n您想è¦ç»§ç»­å—?
+bookmarkSync.title=NoScript é…置书签
+bookmarkSync.message=此书签并ä¸ç”¨äºŽæ‰“å¼€, 而是使用网络书签æœåŠ¡(如: Weave 或 XMarks 扩展)æ¥åŒæ­¥ NoScript é…置。
+bookmarkSync.confirm=NoScript å‘现了一个åƒæ˜¯åœ¨ %S ä¿å­˜çš„é…置书签。\n你真的想è¦ç”¨ä½ çš„ NoScript 本地é…ç½®æ¥è¦†ç›–这个书签的内容?
+ABE.notify=%1$S 请求已ç»è¢« ABE 过滤: <%2$S> %3$S
+ABE.chooseEditor=请为 ABE 规则集选择一个文本编辑器
+ABE.syntaxError=ABE 规则设定存在å¥æ³•é”™è¯¯!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=å…许 %S 的全部内容
+allowTempFrom=临时å…许 %S 的全部内容
+siteInfo.confirm=您正准备å‘%2$Sæ交一个查询以查看"%1$S"站点信æ¯ã€‚您è¦ç»§ç»­å—?
+siteInfo.tooltip=中键点击或shift+左键点击以查看站点信æ¯...
+ef.activate=过滤器 %S
+ef.options=%S 选项...
+ef.newName=输入新过滤器的å称:
+ef.locateExe=为 %S 过滤器选择å¯æ‰§è¡Œç¨‹åº
+disable=ç¦ç”¨ %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/locale/zh-TW/noscript/about.properties b/extensions/noscript/chrome/locale/zh-TW/noscript/about.properties
new file mode 100644
index 0000000..1f69c68
--- /dev/null
+++ b/extensions/noscript/chrome/locale/zh-TW/noscript/about.properties
@@ -0,0 +1,15 @@
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=為您的 Firefox æä¾›é¡å¤–çš„ä¿è­·
+aboutTitle=關於 %S ç¹é«”中文化語系由FreeXD翻譯和修改
+extensionContributors=è²¢ç»äººå“¡:
+extensionContributors.tip=您應該為此感è¬é€™äº›äºº
+extensionCreatorLabel=作者:
+changelog=版本訊æ¯
+changelog.tip=顯示版本訊æ¯
+license=許å¯å”è­°
+license.tip=閱讀使用者å”è­°
+logo.tip=拜訪套件首é 
+sponsor.tip=拜訪贊助商首é 
+informaction.tip=拜訪 InformAction 首é 
+extensionHomepage.tip=拜訪套件首é 
+extensionCreator.tip=拜訪作者首é 
+version=版本 %S
diff --git a/extensions/noscript/chrome/locale/zh-TW/noscript/noscript.dtd b/extensions/noscript/chrome/locale/zh-TW/noscript/noscript.dtd
new file mode 100644
index 0000000..6ba36f7
--- /dev/null
+++ b/extensions/noscript/chrome/locale/zh-TW/noscript/noscript.dtd
@@ -0,0 +1,192 @@
+<!ENTITY noscriptOptions "é¸é ……">
+<!ENTITY noscriptOptions.accesskey "O">
+<!ENTITY noscriptOptionsLong "NoScript é¸é …">
+<!ENTITY noscriptAbout "關於 NoScript 5.1.8.5">
+<!ENTITY noscriptPermissionsText "您å¯ä»¥æŒ‡å®šå…許執行 JavaScript 的網站。輸入您è¦å…許的網å€æˆ–網域(例如 &quot;http://www.site.com&quot; 或 &quot;site.com&quot;),然後按下å…許.">
+<!ENTITY noscriptWebAddress "網å€ï¼š">
+<!ENTITY noscriptAllow "å…許">
+<!ENTITY noscriptAllow.accesskey "A">
+<!ENTITY noscriptForbid "ç¦æ­¢">
+<!ENTITY noscriptForbid.accesskey "F">
+<!ENTITY noscriptTrust "標記為信任的">
+<!ENTITY noscriptTrust.accesskey "T">
+<!ENTITY noscriptUntrust "標記為ä¸ä¿¡ä»»çš„">
+<!ENTITY noscriptUntrust.accesskey "U">
+<!ENTITY noscriptRemoveSelected "移除é¸å–的網站">
+<!ENTITY noscriptGloballyEnabled "å…¨é¢å…許 JavaScript(å±éšª)">
+<!ENTITY noscriptAutoReload "更改許å¯è¨­å®šå¾Œè‡ªå‹•é‡æ–°è®€å–相關的é é¢.">
+<!ENTITY noscriptGeneral "一般">
+<!ENTITY noscriptAppearance "外觀">
+<!ENTITY noscriptShow "顯示…">
+<!ENTITY noscriptCtxMenu "å³éµé¸å–®">
+<!ENTITY noscriptStatusIcon "狀態列圖示">
+<!ENTITY noscriptFullAddr "完整的網å€ï¼ˆhttp://www.noscript.net)">
+<!ENTITY noscriptFullDom "完整的網域(www.noscript.net)">
+<!ENTITY noscriptBaseDom "第二層網域(noscript.net)">
+<!ENTITY noscriptTempCmd "暫時å…許 […]">
+<!ENTITY noscriptSound "有 Script 被å°éŽ–時播放音效">
+<!ENTITY noscriptImport "匯入">
+<!ENTITY noscriptImport.accesskey "I">
+<!ENTITY noscriptExport "匯出">
+<!ENTITY noscriptExport.accesskey "E">
+<!ENTITY noscriptNotify "顯示阻擋 Script 的訊æ¯">
+<!ENTITY noscriptNotify.bottom "將訊æ¯æ”¾åœ¨åº•éƒ¨">
+<!ENTITY noscriptSound.choose "é¸æ“‡">
+<!ENTITY noscriptSound.choose.accesskey "C">
+<!ENTITY noscriptSound.play "播放">
+<!ENTITY noscriptSound.play.accesskey "a">
+<!ENTITY noscriptSound.reset "æ¢å¾©é è¨­">
+<!ENTITY noscriptSound.reset.accesskey "R">
+<!ENTITY noscriptAdvanced "進階">
+<!ENTITY noscriptAdditionalPermissions "å°æ–¼ä¿¡ä»»ç¶²ç«™çš„é¡å¤–許å¯">
+<!ENTITY noscriptAllowClipboard "å…許從外部剪貼簿複製與貼上 Rich Format Text(RTFæ ¼å¼)">
+<!ENTITY noscriptAdditionalRestrictions "å°ä¸ä¿¡ä»»ç¶²ç«™çš„é¡å¤–é™åˆ¶">
+<!ENTITY noscriptPlugins "外掛">
+<!ENTITY noscriptContentBlocker "一併將這些é™åˆ¶æ‡‰ç”¨åˆ°ä¿¡ä»»çš„網站">
+<!ENTITY noscriptForbidJava "ç¦æ­¢ Javaâ„¢">
+<!ENTITY noscriptForbidXSLT "ç¦æ­¢ XSLT">
+<!ENTITY noscriptForbidSilverlight "ç¦æ­¢ Microsoft® Silverlightâ„¢">
+<!ENTITY noscriptForbidIFrames "ç¦æ­¢ &lt;IFRAME&gt;">
+<!ENTITY noscriptForbidFrames "ç¦æ­¢ &lt;FRAME&gt;">
+<!ENTITY noscriptForbidFonts "ç¦æ­¢ @font-face">
+<!ENTITY noscriptForbidWebGL "ç¦æ­¢ WebGL">
+<!ENTITY noscriptForbidMedia "ç¦æ­¢ &lt;AUDIO&gt; / &lt;VIDEO&gt;">
+<!ENTITY noscriptForbidFlash "ç¦æ­¢ Macromedia® Flash®">
+<!ENTITY noscriptForbidPlugins "ç¦æ­¢å…¶ä»–外掛">
+<!ENTITY noscriptReloadWarn "這些é¸é …會套用在新的或(手動)é‡è®€çš„é é¢">
+<!ENTITY noscriptConfirmUnblock "暫時å–消阻擋物件需è¦ç¢ºèª">
+<!ENTITY noscriptStatusLabel "狀態列標籤">
+<!ENTITY noscriptForbidBookmarklets "ç¦æ­¢ Bookmarklets">
+<!ENTITY noscriptShowPlaceholder "顯示圖片é ç•™ä½ç½®">
+<!ENTITY noscriptTruncateTitle "簡短文件標題">
+<!ENTITY noscriptFixLinks "嘗試修復 JavaScript 連çµ">
+<!ENTITY noscriptAllowBookmarks "å…許書籤裡的所有網站">
+<!ENTITY noscriptAllowViaBookmarks "å…許用書籤開啟網站">
+<!ENTITY noscriptAllowPing "å…許 &lt;A PING…&gt;">
+<!ENTITY noscriptAllowLocalLinks "å…許本機連çµ">
+<!ENTITY noscriptForbidPing "ç¦æ­¢ &lt;A PING…&gt;">
+<!ENTITY noscriptForbidMetaRefresh "ç¦æ­¢ &lt;NoScript&gt; 元素中的 META é‡æ–°å°Žå‘">
+<!ENTITY noscriptForbidMetaRefresh.accesskey "R">
+<!ENTITY noscriptNotifyMeta "顯示關於被å°éŽ–çš„ META é‡å°Žå‘">
+<!ENTITY noscriptNotifyMeta.accesskey "R">
+<!ENTITY noscriptWhitelist "白åå–®">
+<!ENTITY noscriptPermissions "許å¯">
+<!ENTITY noscriptRefresh "é‡æ–°æ•´ç†">
+<!ENTITY noscriptNotifications "通知">
+<!ENTITY noscriptToolbarToggle "在 NoScript 工具列按鈕上按左éµä¾†å›ºå®šç›®å‰ç¬¬ä¸€å±¤ç¶²åŸŸçš„許å¯">
+<!ENTITY noscriptTrusted "信任的">
+<!ENTITY noscriptUntrusted "ä¸ä¿¡ä»»çš„">
+<!ENTITY noscriptUnknown "未知">
+<!ENTITY noscriptAdd "新增">
+<!ENTITY noscriptAdd.accesskey "A">
+<!ENTITY noscriptClose "關閉">
+<!ENTITY noscriptSiteManager "網站管ç†">
+<!ENTITY noscriptSecurityManager "安全管ç†">
+<!ENTITY noscriptPolicies "原則">
+<!ENTITY noscriptDefaultPolicies "é è¨­åŽŸå‰‡">
+<!ENTITY noscriptSitePolicies "網站特殊原則">
+<!ENTITY noscriptNselNever "éš±è— &lt;NoScript&gt; 元素">
+<!ENTITY noscriptNselForce "顯示被å°éŽ–çš„ &lt;Script&gt; çš„ &lt;NoScript&gt; 元素">
+<!ENTITY noscriptAutoAllowTopLevel "é è¨­æš«æ™‚å…許第一層網域">
+<!ENTITY noscriptDescription "為您的 Firefox æä¾›é¡å¤–ä¿è­·: NoScript åªå…許您é¸æ“‡çš„信任網域 (例如您的家庭金èžç¶²ç«™) 上的 JavaScript, Java (和其他的外掛). 這份白å單基於é å…ˆè™•ç†ä¾†é˜²æ­¢å®‰å…¨å¼±é»ž (已知和未知的!) 被利用,且ä¸æ失功能… 專家們都åŒæ„: Firefox 加上 NoScript 真的是更加安全 :-)">
+<!ENTITY noscriptOptBlockCssScanners "å°éŽ–基於 CSS 的掃瞄器">
+<!ENTITY noscriptOptFilterXGet "消除å¯ç–‘的跨站請除">
+<!ENTITY noscriptOptFilterXPost "轉æ›è·¨ç«™ POST 請求為ä¸å«æ•¸æ“šçš„ GET 請求">
+<!ENTITY noscriptShowConsole "顯示控制å°â€¦">
+<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptXss "XSS">
+<!ENTITY noscriptXss.accesskey "X">
+<!ENTITY noscriptXssFaq "XSS å•èˆ‡ç­”…">
+<!ENTITY noscriptXssFaq.accesskey "Q">
+<!ENTITY noscriptUnsafeReload "ä¸å®‰å…¨çš„é‡æ–°è®€å–">
+<!ENTITY noscriptUnsafeReload.accesskey "R">
+<!ENTITY noscriptXssExceptions "Anti-XSS ä¿è­·ä¾‹å¤–">
+<!ENTITY noscriptXssExceptions.description "符åˆé€™äº›è¦å‰‡è¡¨ç­”å¼çš„目標將ä¸æœƒè¢«ä¿è­·ä¸å— XSS (跨站腳本攻擊)">
+<!ENTITY noscriptMatchSample "樣本符åˆç¯„例:">
+<!ENTITY noscriptReset "æ¢å¾©">
+<!ENTITY noscriptReset.accesskey "s">
+<!ENTITY noscriptResetDef "æ¢å¾©é è¨­">
+<!ENTITY noscriptResetDef.accesskey "d">
+<!ENTITY noscriptOptionsWidth "40em">
+<!ENTITY noscriptRevokeTemp "å–消暫時許å¯">
+<!ENTITY noscriptRevokeTemp.accesskey "R">
+<!ENTITY noscriptNoUntrustedPlaceholder "無物件進入ä½ç½®æ¨™èªŒç¬¦å¾žæ¨™è¨˜ä¿¡ä»»çš„網站">
+<!ENTITY noscriptCollapseBlockedObjects "撤銷已å°éŽ–的物件">
+<!ENTITY noscriptExceptions "例外…">
+<!ENTITY noscriptBlockedObjects "å·²å°éŽ–物件">
+<!ENTITY noscriptAlwaysBlockUntrustedContent "å°éŽ–æ¯å€‹ä¾†è‡ªä¸ä¿¡ä»»ç¶²ç«™çš„物件">
+<!ENTITY noscriptTempAllowPage "暫時å…許此é é¢çš„所有物件">
+<!ENTITY noscriptTempAllowPage.accesskey "T">
+<!ENTITY noscriptAllowPage "å…¨é¢å…許本é ç‰©ä»¶">
+<!ENTITY noscriptAllowPage.accesskey "A">
+<!ENTITY noscriptTempToPerm "為本é å»ºç«‹æ°¸ä¹…許å¯">
+<!ENTITY noscriptTempToPerm.accesskey "M">
+<!ENTITY noscriptHttps "HTTPS">
+<!ENTITY noscriptHttpsFaq "HTTPSå•èˆ‡ç­”...">
+<!ENTITY noscriptHttpsFaq.accesskey "Q">
+<!ENTITY noscriptHttps.behavior "特性">
+<!ENTITY noscriptHttps.cookies "Cookies">
+<!ENTITY noscriptHttps.description "ç¦æ­¢ä¸»å‹•é é¢çš„內容除éžå®ƒä¾†è‡ªå®‰å…¨çš„(HTTPS)連線:">
+<!ENTITY noscriptHttps.never "æ°¸ä¸">
+<!ENTITY noscriptHttps.proxy "當使用代ç†æ™‚(需è¦æ­é…Tor)">
+<!ENTITY noscriptHttps.always "總是">
+<!ENTITY noscriptHttpsForced "強制下é¢ç¶²ç«™ä½¿ç”¨å®‰å…¨çš„(HTTPS)連線:">
+<!ENTITY noscriptHttpsForcedExceptions "下é¢ç¶²ç«™æ°¸ä¸å¼·åˆ¶å®‰å…¨çš„(HTTPS)連線:">
+<!ENTITY noscriptSecureCookies "啟用自動安全Cookies管ç†">
+<!ENTITY noscriptSecureCookiesForced "強制下é¢ç¶²ç«™è—‰ç”±HTTPS加密所有Cookies:">
+<!ENTITY noscriptSecureCookiesExceptions "忽略下é¢ç¶²ç«™ä¸å®‰å…¨çš„Cookies藉由HTTPS:">
+<!ENTITY noscriptClearClickTitle "解除點é¸è­¦å‘Š">
+<!ENTITY noscriptClearClickHeader "潛在的點é¸åŠ«æŒ/使用者介é¢è£œå„Ÿä¼åœ–攻擊!">
+<!ENTITY noscriptClearClickDescription "NoScript 攔截一個滑鼠或éµç›¤æ“作的隱è—元素. 點é¸åœ–片將會進行å°ä¸Šè¿°éŽç¨‹ä¹‹é–“的阻止和解除改變.">
+<!ENTITY noscriptClearClickOpt "解除é é¢ä¸Šçš„點é¸ä¿è­·...">
+<!ENTITY noscriptClearClickReport "報告">
+<!ENTITY noscriptClearClickReport.accesskey "R">
+<!ENTITY noscriptClearClickReportId "報告ID:">
+<!ENTITY noscriptTrustedPagesAdj "å¯ä¿¡ä»»">
+<!ENTITY noscriptUntrustedPagesAdj "ä¸ä¿¡ä»»">
+<!ENTITY noscriptKeepLocked "ä¿æŒéŽ–定此元素(推薦)">
+<!ENTITY noscriptEmbeddings "嵌入的物件">
+<!ENTITY noscriptPrev "上一個">
+<!ENTITY noscriptNext "下一個">
+<!ENTITY noscriptFrameOptErr.title "此內容無法在框架é ä¸­é¡¯ç¤º">
+<!ENTITY noscriptFrameOptErr.desc "為ä¿è¡›æ‚¨çš„安全性,此æ供者的內容ä¸å…許於框架é ä¸­é¡¯ç¤ºã€‚">
+<!ENTITY noscriptFrameOptErr.link "按此於一個新視窗中開啟此內容。">
+<!ENTITY noscriptBookmarkSync "輕鬆把 NoScript 組態備份到書籤中來é”到åŒæ­¥">
+<!ENTITY noscriptShowReleaseNotes "顯示更新發行公告">
+<!ENTITY ABE "ABE">
+<!ENTITY ABE.accesskey "A">
+<!ENTITY ABE.rulesets.label "è¦å‰‡æŽ§åˆ¶:">
+<!ENTITY ABE.enabled.label "啟用ABE (Application Boundaries Enforcer)">
+<!ENTITY ABE.siteEnabled.label "å…許網站使用自己的è¦å‰‡">
+<!ENTITY ABE.edit.label "編輯">
+<!ENTITY ABE.edit.accesskey "E">
+<!ENTITY ABE.enable.label "啟用">
+<!ENTITY ABE.enable.accesskey "n">
+<!ENTITY ABE.disable.label "åœç”¨">
+<!ENTITY ABE.disable.accesskey "D">
+<!ENTITY ABE.refresh.label "é‡æ–°æ•´ç†">
+<!ENTITY ABE.refresh.accesskey "R">
+<!ENTITY noscriptUninstall "移除">
+<!ENTITY noscriptRecentBlocked "最近å°éŽ–的網站">
+<!ENTITY noscriptExternalFilters "外部篩é¸å™¨">
+<!ENTITY noscriptEF.enable "啟用外部篩é¸å™¨">
+<!ENTITY noscriptEF.add "新增篩é¸å™¨â€¦">
+<!ENTITY noscriptEF.executable "å¯åŸ·è¡Œæª”:">
+<!ENTITY noscriptEF.browse "ç€è¦½â€¦">
+<!ENTITY noscriptEF.contentType "欲篩é¸çš„內容類型(MIME)(完全符åˆæ­£è¦è¡¨é”å¼)">
+<!ENTITY noscriptEF.exceptions "當進入這些網站時ä¸ç¯©é¸ç‰©ä»¶ï¼š">
+<!ENTITY noscriptEF.remove "移除">
+<!ENTITY noscriptPreset "安全層級">
+<!ENTITY noscriptPreset.off "關閉(您是èªçœŸçš„嗎?)">
+<!ENTITY noscriptPreset.low "輕鬆é”æˆ(黑åå–®+網é å®‰å…¨)">
+<!ENTITY noscriptPreset.medium "傳統(白åå–®+網é å®‰å…¨)">
+<!ENTITY noscriptPreset.high "堡壘(完全鎖定)">
+<!ENTITY noscript.hoverUI "當滑鼠移至 NoScript's 圖示時開啟權é™é¸å–®">
+<!ENTITY noscriptDonate "贊助">
+<!ENTITY noscriptDonate.accesskey "o">
+<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
+<!ENTITY noscriptCustom "Custom">
+<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
+<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
+<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
+<!ENTITY noscriptPermanentInPrivate "Permanent &quot;Allow&quot; commands in private windows">
diff --git a/extensions/noscript/chrome/locale/zh-TW/noscript/noscript.properties b/extensions/noscript/chrome/locale/zh-TW/noscript/noscript.properties
new file mode 100644
index 0000000..578eb88
--- /dev/null
+++ b/extensions/noscript/chrome/locale/zh-TW/noscript/noscript.properties
@@ -0,0 +1,56 @@
+allowGlobal=å…¨é¢å…許 JavaScript(å±éšªï¼‰
+forbidGlobal=ç¦æ­¢å…¨é¢å…許 JavaScript(建議)
+allowLocal=å…許 %S
+allowTemp=暫時å…許 %S
+forbidLocal=ç¦æ­¢ %S
+allowed.glb=å±éšªï¼å·²å…¨é¢å…許 JavaSript
+allowed.yes=å·²å…許目å‰çš„ JavaScript
+allowed.prt=å·²å…許部分的 JavaScript
+allowed.no=å·²ç¦æ­¢ç›®å‰çš„ JavaScript
+global.warning.title=警告ï¼
+global.warning.text=將全é¢å…許 JavaScript (å°æ¯ä¸€å€‹ç¶²ç«™çš†æ˜¯ï¼‰ã€‚這有潛在的å±éšªæ€§ã€‚您確定嗎?
+audio.samples=音效樣本
+confirm=您確定嗎?
+alwaysAsk=總是è¦æ±‚確èª
+notifyHide=%S 秒é˜å¾Œéš±è—
+trust=ä¿¡ä»» %S
+distrust=標記 %S 為ä¸ä¿¡ä»»
+untrustedOrigin=ä¸ä¿¡ä»»åŽŸå› 
+xss.notify.generic=NoScript å·²éŽæ¿¾æŽ‰ä¸€å€‹æ½›åœ¨çš„跨站腳本 (XSS) 攻擊從 %S. 詳情已紀錄到控制å°.
+xss.notify.showConsole=顯示控制å°â€¦
+xss.notify.showConsole.accessKey=S
+xss.reason.filterXGet=消除å¯ç–‘的請求. 原始 URL [%1$S] 請求來自於 [%2$S]. 被處ç†çš„ URL: [%3$S].)
+xss.reason.filterXGetRef=消除å¯ç–‘的請求引用. URL [%1$S] 請求來自於 [%2$S]. 被處ç†çš„引用: [%3$S].)
+xss.reason.filterXPost=從 [%2$S] 至 [%1$S] çš„å¯ç–‘上傳已被消除 : 改變æˆåªä¸‹è¼‰çš„ GET 請求.
+unsafeReload.warning=ä¸å®‰å…¨çš„é‡æ–°è®€å–一個å¯ç–‘çš„\n\n%1$S [%2$S]\n\n來自於 [%3$S]\n\nNoScript å°‡ä¸ä¿è­·é€™å€‹è«‹æ±‚!\n
+metaRefresh.notify=NoScript å°éŽ–了一個 <NOSCRIPT> 元素內的 <META> é‡å°Žå‘ : %S 在 %S 秒.
+metaRefresh.notify.follow=å…許é‡å°Žå‘
+metaRefresh.notify.follow.accessKey=F
+notify.options=é¸é …
+notify.options.accessKey=O
+reset.title=æ¢å¾© NoScript
+reset.warning=所有 NoScript å好和網站許å¯å°‡æœƒç«‹å³æ¢å¾©åˆ°å®ƒå€‘çš„é è¨­å€¼.\n這個æ“作無法回覆.\n確定è¦ç¹¼çºŒ?
+bookmarkSync.title=NoScript 組態設定書籤
+bookmarkSync.message=此書籤ä¸é©ç”¨æ–¼é–‹å•Ÿï¼Œä½†èƒ½å¤ ä½¿ç”¨åƒWeave或XMarks等擴充元件æ供的線上書籤åŒæ­¥æœå‹™ã€‚
+bookmarkSync.confirm=NoScript發ç¾ä¸€å€‹çµ„態書籤似乎儲存在\n%S。\n您確定è¦è¦†å¯«æœ¬æ©ŸNoScript組態與這個書籤內容?
+ABE.notify=請求 %1$S 已由ABEéŽæ¿¾: <%2$S> %3$S
+ABE.chooseEditor=è«‹é¸æ“‡ä¸€å€‹çµ¦ABEè¦å‰‡è¨­å®šä½¿ç”¨çš„文字編輯器
+ABE.syntaxError=ABE è¦å‰‡é›†çš„語法錯誤ï¼
+ABE.wanIpAsLocal=廣域網路IP (%S) ∈ 本機
+allowFrom=å…許來自 %S 的所有內容
+allowTempFrom=暫時å…許來自 %S 的所有內容
+siteInfo.confirm=您å¯èƒ½é€éŽä¸€å€‹æŸ¥è©¢çµ¦ %2$S 來索å–關於 %1$S 網站的資訊,是å¦è¦ç¹¼çºŒï¼Ÿ
+siteInfo.tooltip=按一下滑鼠中éµæˆ–Shift+å·¦éµé¡¯ç¤ºç¶²ç«™è³‡è¨Š...
+ef.activate=ç¯©é¸ %S
+ef.options=%S é¸é …...
+ef.newName=輸入新篩é¸å™¨å稱:
+ef.locateExe=é¸å– %S 篩é¸å™¨çš„執行檔
+disable=åœç”¨ %S
+disable.accessKey=D
+allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+removal.title=Security Downgrade Warning
+removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.no=No, just stop blocking scripts
+removal.yes=Yes, remove ALL protections
+incompatibleOptions.title=Incompatible Options Warning
+incompatibleOptions="%1$S"\nis incompatible with "%2$S".\nDo you want to enable the former and disable the latter?
diff --git a/extensions/noscript/chrome/skin/classic/noscript/abe16.png b/extensions/noscript/chrome/skin/classic/noscript/abe16.png
new file mode 100644
index 0000000..b11dd73
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/abe16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/about.css b/extensions/noscript/chrome/skin/classic/noscript/about.css
new file mode 100644
index 0000000..59d7eb3
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/about.css
@@ -0,0 +1,88 @@
+#genericAbout {
+ padding: 0px 0px 10px 0px;
+ background: #FFF none;
+ background-image: none;
+}
+
+dialog, .dialog-content-box {
+ background: white none;
+ border: none;
+}
+
+#clientBox {
+ color: #000;
+ padding: 0px; margin: 0px;
+ background: white none;
+ border: none;
+}
+
+#clientBoxInternal {
+ padding: 0px; margin: 10px;
+ background: white none;
+}
+
+#headBox {
+ border: solid #448;
+ border-width: 0px 0px 1px 0px;
+ padding: 0px;
+ margin: 2px;
+ background-image: none;
+}
+
+#extensionName {
+ font-size: large;
+ font-weight: bold;
+ color: #448;
+}
+
+#extensionVersion {
+ color: #448;
+}
+
+.sponsorline {
+ color: #444;
+}
+
+#extensionDescription {
+ color: #444;
+ text-align: justify;
+ max-width: 550px;
+ overflow: auto;
+}
+
+#extensionHomepage {
+
+}
+
+.text-link, .text-link:focus {
+ color: #00f;
+ text-decoration: none;
+ cursor: pointer;
+
+}
+.text-link:hover {
+ color: #00f;
+ text-decoration: underline ;
+}
+
+#contributorsBox {
+ overflow: auto;
+ border: 1px solid black;
+ padding: 4px;
+ margin: 0px 6px;
+ height: 150px;
+}
+
+.contributor {
+ margin: 0px;
+ color: #444;
+}
+
+#extensionCreator, #extensionContributors, #extensionSponsor {
+ font-weight: bold;
+}
+
+text-link {
+ text-decoration: none;
+}
+
diff --git a/extensions/noscript/chrome/skin/classic/noscript/block.wav b/extensions/noscript/chrome/skin/classic/noscript/block.wav
new file mode 100644
index 0000000..48f92c1
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/block.wav
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/browser.css b/extensions/noscript/chrome/skin/classic/noscript/browser.css
new file mode 100644
index 0000000..173542d
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/browser.css
@@ -0,0 +1,322 @@
+#palette-box #noscript-tbb {
+ list-style-image: url("icon24.png");
+}
+#noscript-tbb[type="menu"]:not([cui-areatype="menu-panel"]) {
+ -moz-box-orient: horizontal !important;
+}
+toolbar[mode="full"] #noscript-tbb[type="menu"] {
+ -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#menu-vertical");
+}
+
+
+#noscript-statusIcon,
+#noscript-statusRedirect,
+#noscript-statusXss {
+ cursor: pointer;
+
+}
+
+.noscript-cmd {
+ font-weight: normal;
+}
+
+.noscript-temp, .noscript-cmd.noscript-temp {
+ font-style: italic;
+ font-weight: normal;
+}
+
+.noscript-toplevel, .noscript-toplevel.noscript-temp.noscript-forbid,
+#noscript-menu-recent-blocked .noscript-embed.noscript-toplevel {
+ font-weight: bold;
+}
+
+.noscript-embed .noscript-temp, .noscript-embed.noscript-temp {
+ font-style: normal;
+}
+
+.noscript-unsafe-reload {
+ list-style-image: url(unsafe-reload16.png);
+}
+
+
+
+.noscript-console {
+ list-style-image: url(console16.png);
+}
+.noscript-faq {
+ list-style-image: url(faq16.png);
+}
+
+.noscript-redirect,
+#noscript-statusRedirect {
+ list-style-image: url(redirect16.png);
+}
+.noscript-xss,
+#noscript-statusXss {
+ list-style-image: url(xss16.png);
+}
+
+.noscript-yes,
+#noscript-tbb.noscript-yes,
+#noscript-statusIcon.noscript-yes,
+.noscript-allow,
+.noscript-allow-from {
+ list-style-image: url(yes16.png);
+}
+
+
+
+#noscript-tbb-temp-page,
+.noscript-temp.noscript-allow,
+.noscript-temp.noscript-allow-from {
+ list-style-image: url(temp16.png);
+}
+
+
+
+.noscript-no,
+#noscript-tbb.noscript-no,
+#noscript-statusIcon.noscript-no,
+.noscript-forbid {
+ list-style-image: url(no16.png);
+}
+.noscript-prt,
+#noscript-tbb.noscript-prt,
+#noscript-statusIcon.noscript-prt
+{
+ list-style-image: url(prt16.png);
+}
+.noscript-subprt,
+#noscript-tbb.noscript-subprt,
+#noscript-statusIcon.noscript-subprt
+{
+ list-style-image: url(subprt16.png);
+}
+
+.noscript-emb,
+#noscript-tbb.noscript-emb,
+#noscript-statusIcon.noscript-emb
+{
+ list-style-image: url(emb16.png);
+}
+
+.noscript-no-emb,
+#noscript-tbb.noscript-no-emb,
+#noscript-statusIcon.noscript-no-emb
+{
+ list-style-image: url(no-emb16.png);
+}
+
+.noscript-glb-emb,
+#noscript-tbb.noscript-glb-emb,
+#noscript-statusIcon.noscript-glb-emb,
+.noscript-inactive-glb-emb,
+#noscript-tbb.noscript-inactive-glb-emb,
+#noscript-statusIcon.noscript-inactive-glb-emb
+{
+ list-style-image: url(glb-emb16.png);
+}
+
+
+.noscript-inactive-subprt,
+#noscript-tbb.noscript-inactive-subprt,
+#noscript-statusIcon.noscript-inactive-subprt,
+.noscript-inactive-prt,
+#noscript-tbb.noscript-inactive-prt,
+#noscript-statusIcon.noscript-inactive-prt
+{
+ list-style-image: url(inactive-prt16.png);
+}
+
+.noscript-inactive-emb,
+#noscript-tbb.noscript-inactive-emb,
+#noscript-statusIcon.noscript-inactive-emb
+{
+ list-style-image: url(inactive-emb16.png);
+}
+
+.noscript-yu,
+#noscript-tbb.noscript-yu,
+#noscript-statusIcon.noscript-yu {
+ list-style-image: url(yu16.png);
+}
+
+
+.noscript-glb,
+#noscript-tbb.noscript-glb,
+#noscript-statusIcon.noscript-glb,
+.noscript-inactive-glb,
+#noscript-tbb.noscript-inactive-glb,
+#noscript-statusIcon.noscript-inactive-glb {
+ list-style-image: url(glb16.png);
+}
+
+.noscript-no.noscript-glb, .noscript-forbid.noscript-glb {
+ list-style-image: url(glb-no16.png);
+}
+
+.noscript-inactive-yes,
+#noscript-tbb.noscript-inactive-yes,
+#noscript-statusIcon.noscript-inactive-yes {
+ list-style-image: url(inactive-yes16.png);
+}
+.noscript-inactive-no,
+#noscript-tbb.noscript-inactive-no,
+#noscript-statusIcon.noscript-inactive-no,
+#noscript-menu-recent-blocked {
+ list-style-image: url(inactive-no16.png);
+}
+
+
+.noscript-inactive-no-emb,
+#noscript-tbb.noscript-inactive-no-emb,
+#noscript-statusIcon.noscript-inactive-no-emb,
+#noscript-menu-recent-blocked {
+ list-style-image: url(inactive-no-emb16.png);
+}
+
+.noscript-distrust,
+.noscript-untrusted,
+#noscript-tbb.noscript-untrusted,
+#noscript-tbb.noscript-inactive-untrusted,
+#noscript-statusIcon.noscript-untrusted
+#noscript-statusIcon.noscript-inactive-untrusted
+{
+ list-style-image: url(untrusted16.png);
+}
+
+
+
+
+.noscript-inactive-yu,
+#noscript-tbb.noscript-inactive-yu,
+#noscript-statusIcon.noscript-inactive-yu {
+ list-style-image: url(inactive-yu16.png);
+}
+
+.noscript-yu-emb, .noscript-inactive-yu-emb,
+#noscript-tbb.noscript-yu-emb, #noscript-tbb.noscript-inactive-yu-emb,
+#noscript-statusIcon.noscript-yu-emb, #noscript-statusIcon.noscript-inactive-yu-emb {
+ list-style-image: url(yu-emb16.png);
+}
+
+.noscript-yu-glb, .noscript-inactive-yu-glb,
+#noscript-tbb.noscript-yu-glb, #noscript-tbb.noscript-inactive-yu-glb,
+#noscript-statusIcon.noscript-yu-glb, #noscript-statusIcon.noscript-inactive-yu-glb {
+ list-style-image: url(yu-glb16.png);
+}
+
+.noscript-untrusted-glb, .noscript-inactive-untrusted-glb,
+#noscript-tbb.noscript-untrusted-glb, #noscript-tbb.noscript-inactive-untrusted-glb,
+#noscript-statusIcon.noscript-untrusted-glb, #noscript-statusIcon.noscript-inactive-untrusted-glb {
+ list-style-image: url(untrusted-glb16.png);
+}
+
+.noscript-https {
+ list-style-image: url(https16.png);
+}
+.noscript-abe {
+ list-style-image: url(abe16.png);
+}
+
+.noscript-clearclick {
+ list-style-image: url(clearclick16.png);
+}
+
+
+.noscript-error {
+ color: red !important;
+ background: #ffa !important;
+}
+.noscript-error[selected="true"] {
+ background: red !important;
+ color: #ffa !important;
+}
+
+#noscript-tbb-revoke-temp,
+.noscript-revoke-temp {
+ list-style-image: url(revtemp16.png);
+}
+
+.noscript-embed {
+ list-style-image: url(embed-no16.png);
+}
+
+.noscript-allow-from.noscript-embed {
+ list-style-image: url(embed16.png)
+}
+
+.noscript-ef {
+ list-style-image: url(ef16.png);
+}
+
+.noscript-ef.inactive {
+ list-style-image: url(ef-no16.png);
+}
+
+
+#noscript-sticky-ui {
+ cursor: pointer;
+ -moz-binding: url("chrome://noscript/content/noscript.xbl#scrollable-popup");
+}
+
+.noscript-menu, .noscript-menu menupopup {
+ background-color: menu !important;
+ opacity: 1.0;
+ color: menutext;
+ border: 1px solid #444;
+ padding: 2px;
+}
+
+menupopup[sticky="true"] {
+ border: 1px solid #444 !important;
+}
+
+menupopup[sticky="true"][disabled="true"] {
+ border: 1px solid #ccc;
+ cursor: wait;
+ background-color: #ccc;
+ color: #888;
+}
+
+#noscript-tbb-revoke-temp[disabled="true"], #noscript-tbb-temp-page[disabled="true"] {
+ opacity: .5;
+}
+#noscript-tbb-revoke-temp > .toolbarbutton-icon, #noscript-tbb-temp-page > .toolbarbutton-icon, #noscript-tbb .toolbarbutton-icon[label=NoScript] {
+ width: auto !important;
+ height: auto !important;
+}
+
+toolbar #noscript-tbb-revoke-temp, toolbar #noscript-tbb-temp-page, toolbar #noscript-tbb {
+ max-width: 48px;
+}
+#nav-bar-customization-target > #noscript-tbb {
+ max-width: none;
+}
+
+
+#addon-bar > #noscript-tbb .toolbarbutton-text,
+#addon-bar > #noscript-tbb-page .toolbarbutton-text,
+#addon-bar > #noscript-tbb-revoke-temp .toolbarbutton-text
+{ display: none !important }
+#addon-bar > #noscript-tbb .toolbarbutton-icon,
+#addon-bar > #noscript-tbb-page .toolbarbutton-icon,
+#addon-bar > #noscript-tbb-revoke-temp .toolbarbutton-icon,
+#addon-bar[mode="full"] > #noscript-tbb .toolbarbutton-menubutton-button,
+#addon-bar[mode="full"] > #noscript-tbb-page .toolbarbutton-menubutton-button,
+#addon-bar[mode="full"] > #noscript-tbb-revoke-temp .toolbarbutton-menubutton-button
+{ min-width: 16px; display: -moz-box }
+#addon-bar > #noscript-tbb, #addon-bar > #noscript-tbb-page, #addon-bar > #noscript-tbb-revoke-temp
+{ min-width: 16px !important }
+
+notification {
+ word-wrap: break-word !important;
+}
+
+.menu-iconic[id*="noscript-"] > .menu-iconic-left,
+.menu-iconic[class*="noscript-"] > .menu-iconic-left,
+.menuitem-iconic[class*="noscript-"] > .menu-iconic-left {
+ visibility: visible !important;
+}
+
+#navigator-toolbox > #status-bar { display: none }
diff --git a/extensions/noscript/chrome/skin/classic/noscript/clearclick16.png b/extensions/noscript/chrome/skin/classic/noscript/clearclick16.png
new file mode 100644
index 0000000..1c8f1c9
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/clearclick16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/close.png b/extensions/noscript/chrome/skin/classic/noscript/close.png
new file mode 100644
index 0000000..e559a70
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/close.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/console16.png b/extensions/noscript/chrome/skin/classic/noscript/console16.png
new file mode 100644
index 0000000..928fd83
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/console16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/content.css b/extensions/noscript/chrome/skin/classic/noscript/content.css
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/content.css
@@ -0,0 +1 @@
+
diff --git a/extensions/noscript/chrome/skin/classic/noscript/ef-no16.png b/extensions/noscript/chrome/skin/classic/noscript/ef-no16.png
new file mode 100644
index 0000000..024e158
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/ef-no16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/ef16.png b/extensions/noscript/chrome/skin/classic/noscript/ef16.png
new file mode 100644
index 0000000..1adfd74
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/ef16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/emb16.png b/extensions/noscript/chrome/skin/classic/noscript/emb16.png
new file mode 100644
index 0000000..6944ca9
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/emb16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/embed-no16.png b/extensions/noscript/chrome/skin/classic/noscript/embed-no16.png
new file mode 100644
index 0000000..9130c40
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/embed-no16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/embed16.png b/extensions/noscript/chrome/skin/classic/noscript/embed16.png
new file mode 100644
index 0000000..ab9a323
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/embed16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/faq16.png b/extensions/noscript/chrome/skin/classic/noscript/faq16.png
new file mode 100644
index 0000000..760b88d
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/faq16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/flash16.png b/extensions/noscript/chrome/skin/classic/noscript/flash16.png
new file mode 100644
index 0000000..ee4a1b3
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/flash16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/flash32.png b/extensions/noscript/chrome/skin/classic/noscript/flash32.png
new file mode 100644
index 0000000..8535f07
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/flash32.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/folder_closed.png b/extensions/noscript/chrome/skin/classic/noscript/folder_closed.png
new file mode 100644
index 0000000..e247603
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/folder_closed.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/folder_open.png b/extensions/noscript/chrome/skin/classic/noscript/folder_open.png
new file mode 100644
index 0000000..d896bf7
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/folder_open.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/font.png b/extensions/noscript/chrome/skin/classic/noscript/font.png
new file mode 100644
index 0000000..b7960db
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/font.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/glb-emb16.png b/extensions/noscript/chrome/skin/classic/noscript/glb-emb16.png
new file mode 100644
index 0000000..4bcbdd3
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/glb-emb16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/glb-no16.png b/extensions/noscript/chrome/skin/classic/noscript/glb-no16.png
new file mode 100644
index 0000000..02d167c
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/glb-no16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/glb16.png b/extensions/noscript/chrome/skin/classic/noscript/glb16.png
new file mode 100644
index 0000000..e0b9084
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/glb16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/https16.png b/extensions/noscript/chrome/skin/classic/noscript/https16.png
new file mode 100644
index 0000000..2ebc4f6
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/https16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/ia.png b/extensions/noscript/chrome/skin/classic/noscript/ia.png
new file mode 100644
index 0000000..1866fa6
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/ia.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/icon24.png b/extensions/noscript/chrome/skin/classic/noscript/icon24.png
new file mode 100644
index 0000000..1048eba
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/icon24.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/icon32.png b/extensions/noscript/chrome/skin/classic/noscript/icon32.png
new file mode 100644
index 0000000..8003d11
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/icon32.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/icon64.png b/extensions/noscript/chrome/skin/classic/noscript/icon64.png
new file mode 100644
index 0000000..0e528f7
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/icon64.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/icon80.png b/extensions/noscript/chrome/skin/classic/noscript/icon80.png
new file mode 100644
index 0000000..fb62fbe
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/icon80.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/inactive-emb16.png b/extensions/noscript/chrome/skin/classic/noscript/inactive-emb16.png
new file mode 100644
index 0000000..02bb8bf
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/inactive-emb16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/inactive-glb16.png b/extensions/noscript/chrome/skin/classic/noscript/inactive-glb16.png
new file mode 100644
index 0000000..db669e1
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/inactive-glb16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/inactive-no-emb16.png b/extensions/noscript/chrome/skin/classic/noscript/inactive-no-emb16.png
new file mode 100644
index 0000000..a8fa907
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/inactive-no-emb16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/inactive-no16.png b/extensions/noscript/chrome/skin/classic/noscript/inactive-no16.png
new file mode 100644
index 0000000..a1d3ac0
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/inactive-no16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/inactive-prt16.png b/extensions/noscript/chrome/skin/classic/noscript/inactive-prt16.png
new file mode 100644
index 0000000..fe7acd8
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/inactive-prt16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/inactive-yes16.png b/extensions/noscript/chrome/skin/classic/noscript/inactive-yes16.png
new file mode 100644
index 0000000..4b55619
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/inactive-yes16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/inactive-yu16.png b/extensions/noscript/chrome/skin/classic/noscript/inactive-yu16.png
new file mode 100644
index 0000000..2964bab
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/inactive-yu16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/java16.png b/extensions/noscript/chrome/skin/classic/noscript/java16.png
new file mode 100644
index 0000000..97602f6
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/java16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/java32.png b/extensions/noscript/chrome/skin/classic/noscript/java32.png
new file mode 100644
index 0000000..8308284
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/java32.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/mobile.css b/extensions/noscript/chrome/skin/classic/noscript/mobile.css
new file mode 100644
index 0000000..8510e88
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/mobile.css
@@ -0,0 +1,67 @@
+#noscript-tbb.noscript-fennec, #noscript-statusXss.noscript-fennec {
+ -moz-appearance: none;
+ background: transparent !important;
+ -moz-box-orient: vertical;
+ width: 44px;
+ height: 44px;
+ -moz-user-focus: ignore;
+}
+
+.noscript-options {
+ display: none !important;
+}
+
+#noscriptPopupSet menu, #noscriptPopupSet menuitem {
+ font-size: 24px;
+ padding: 8px;
+ margin: 0;
+ border: none;
+ background: -moz-linear-gradient(#fff, #fff, #fff, #ddd);
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ccc;
+ min-height: 30px;
+}
+
+#noscriptPopupSet menu:hover, #noscriptPopupSet menuitem:hover,
+#noscriptPopupSet menu:focus, #noscriptPopupSet menuitem:focus,
+#noscriptPopupSet menu:active, #noscriptPopupSet menuitem:active,
+#noscriptPopupSet menu:active[active="true"], #noscriptPopupSet menuitem[active="true"]{
+ background: -moz-linear-gradient(#ddd, #444, #666, #ddd);
+ color: #fff;
+}
+
+#noscriptPopupSet menuseparator {
+ padding: 8px 0;
+ margin: 0;
+ background: #eee;
+ border: none;
+}
+
+menupopup[sticky="true"] {
+ margin: 0;
+}
+
+.scrollbutton-up, .scrollbutton-down {
+ height: 24px !important;
+ border: 1px solid #888;
+ -moz-image-region: auto;
+ background: -moz-linear-gradient(#ddd, #fff, #fff, #eee);
+}
+
+.scrollbutton-up {
+ list-style-image: url("chrome://browser/skin/images/arrowup-16.png");
+}
+
+.scrollbutton-down {
+ list-style-image: url("chrome://browser/skin/images/arrowdown-16.png");
+}
+
+.scrollbutton-up[disabled="true"] {
+ list-style-image: url("chrome://browser/skin/images/arrowupdark-16.png");
+ -moz-image-region: auto; /* cut off inheritance */
+}
+
+.scrollbutton-down[disabled="true"] {
+ list-style-image: url("chrome://browser/skin/images/arrowdowndark-16.png");
+ -moz-image-region: auto; /* cut off inheritance */
+} \ No newline at end of file
diff --git a/extensions/noscript/chrome/skin/classic/noscript/no-emb16.png b/extensions/noscript/chrome/skin/classic/noscript/no-emb16.png
new file mode 100644
index 0000000..eb37a09
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/no-emb16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/no16.png b/extensions/noscript/chrome/skin/classic/noscript/no16.png
new file mode 100644
index 0000000..b023583
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/no16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/options.css b/extensions/noscript/chrome/skin/classic/noscript/options.css
new file mode 100644
index 0000000..eb25a7f
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/options.css
@@ -0,0 +1,46 @@
+.ia-indent {
+ padding-left: 24px;
+}
+
+.text-link {
+ text-decoration: none;
+}
+.text-link:hover {
+ text-decoration: underline;
+}
+
+tabbox#nsopt-tabsAdvanced > tab image.tab-icon {
+ width: 16px !important;
+ height: 16px !important;
+ max-height: 16px !important;
+ max-width: 16px !important;
+}
+
+tabbox#nsopt-tabsAdvanced > tab {
+ min-height: 16px;
+ marker-offset: 24px;
+}
+
+#imgs-stack {
+ -moz-user-focus: normal;
+}
+
+#imgs-stack:focus {
+ outline: 1px dotted #444;
+}
+.flexible-cbx {
+ white-space: normal;
+}
+
+#urlListDisplay treecols {
+ height: 0px;
+ overflow: hidden;
+}
+
+#urlListDisplay treechildren::-moz-tree-cell-text(temp) {
+ font-style: italic;
+}
+
+#urlListDisplay treechildren::-moz-tree-cell-text(mandatory) {
+ color: #999;
+}
diff --git a/extensions/noscript/chrome/skin/classic/noscript/prt16.png b/extensions/noscript/chrome/skin/classic/noscript/prt16.png
new file mode 100644
index 0000000..45b7ce3
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/prt16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/redirect16.png b/extensions/noscript/chrome/skin/classic/noscript/redirect16.png
new file mode 100644
index 0000000..a03c916
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/redirect16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/revtemp16.png b/extensions/noscript/chrome/skin/classic/noscript/revtemp16.png
new file mode 100644
index 0000000..b54f9fb
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/revtemp16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/somelight16.png b/extensions/noscript/chrome/skin/classic/noscript/somelight16.png
new file mode 100644
index 0000000..ed139ce
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/somelight16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/somelight32.png b/extensions/noscript/chrome/skin/classic/noscript/somelight32.png
new file mode 100644
index 0000000..a7e9635
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/somelight32.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/subprt16.png b/extensions/noscript/chrome/skin/classic/noscript/subprt16.png
new file mode 100644
index 0000000..eb83756
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/subprt16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/temp16.png b/extensions/noscript/chrome/skin/classic/noscript/temp16.png
new file mode 100644
index 0000000..a468951
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/temp16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/unsafe-reload16.png b/extensions/noscript/chrome/skin/classic/noscript/unsafe-reload16.png
new file mode 100644
index 0000000..5de9b2c
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/unsafe-reload16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/untrusted-glb16.png b/extensions/noscript/chrome/skin/classic/noscript/untrusted-glb16.png
new file mode 100644
index 0000000..09de467
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/untrusted-glb16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/untrusted16.png b/extensions/noscript/chrome/skin/classic/noscript/untrusted16.png
new file mode 100644
index 0000000..e0b9951
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/untrusted16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/webgl16.png b/extensions/noscript/chrome/skin/classic/noscript/webgl16.png
new file mode 100644
index 0000000..1b5969d
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/webgl16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/webgl32.png b/extensions/noscript/chrome/skin/classic/noscript/webgl32.png
new file mode 100644
index 0000000..af27a3c
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/webgl32.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/xss16.png b/extensions/noscript/chrome/skin/classic/noscript/xss16.png
new file mode 100644
index 0000000..2804e73
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/xss16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/yes16.png b/extensions/noscript/chrome/skin/classic/noscript/yes16.png
new file mode 100644
index 0000000..cf6ce95
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/yes16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/yu-emb16.png b/extensions/noscript/chrome/skin/classic/noscript/yu-emb16.png
new file mode 100644
index 0000000..7164ca5
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/yu-emb16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/yu-glb16.png b/extensions/noscript/chrome/skin/classic/noscript/yu-glb16.png
new file mode 100644
index 0000000..a13d822
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/yu-glb16.png
Binary files differ
diff --git a/extensions/noscript/chrome/skin/classic/noscript/yu16.png b/extensions/noscript/chrome/skin/classic/noscript/yu16.png
new file mode 100644
index 0000000..daaefe5
--- /dev/null
+++ b/extensions/noscript/chrome/skin/classic/noscript/yu16.png
Binary files differ
diff --git a/extensions/noscript/components/noscriptService.js b/extensions/noscript/components/noscriptService.js
new file mode 100644
index 0000000..dae3792
--- /dev/null
+++ b/extensions/noscript/components/noscriptService.js
@@ -0,0 +1,15 @@
+Components.utils.import("resource://gre/modules/Services.jsm");
+Services.scriptloader.loadSubScript("chrome://noscript/content/loader.js", this);
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+INCLUDE("Main");
+
+Main.bootstrap();
+
+function NSGetFactory(cid) {
+ if (cid.toString() === SERVICE_ID) {
+ return ns;
+ }
+ throw Cr.NS_ERROR_FACTORY_NOT_REGISTERED;
+}
diff --git a/extensions/noscript/defaults/preferences/noscript.js b/extensions/noscript/defaults/preferences/noscript.js
new file mode 100644
index 0000000..8264271
--- /dev/null
+++ b/extensions/noscript/defaults/preferences/noscript.js
@@ -0,0 +1,434 @@
+pref("extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description", "chrome://noscript/locale/about.properties");
+pref("noscript.autoReload", true);
+pref("noscript.autoReload.global", true);
+pref("noscript.autoReload.allTabs", true);
+pref("noscript.autoReload.allTabsOnPageAction", true);
+pref("noscript.autoReload.allTabsOnGlobal", false);
+pref("noscript.autoReload.onMultiContent", false);
+pref("noscript.autoReload.useHistory", false);
+pref("noscript.autoReload.useHistory.exceptCurrent", true);
+pref("noscript.autoReload.embedders", 1);
+pref("noscript.ctxMenu", true);
+pref("noscript.statusIcon", true);
+pref("noscript.sound", false);
+pref("noscript.sound.oncePerSite", true);
+pref("noscript.notify", true);
+pref("noscript.notify.bottom", true);
+pref("noscript.showAddress", false);
+pref("noscript.showDomain", false);
+pref("noscript.showTemp", true);
+pref("noscript.showPermanent", true);
+pref("noscript.showDistrust", true);
+pref("noscript.showUntrusted", true);
+pref("noscript.showBaseDomain", true);
+pref("noscript.showAbout", true);
+pref("noscript.showGlobal", true);
+pref("noscript.showTempToPerm", true);
+pref("noscript.showRevokeTemp", true);
+pref("noscript.showBlockedObjects", true);
+pref("noscript.showExternalFilters", true);
+pref("noscript.showTempAllowPage", true);
+pref("noscript.showAllowPage", true);
+pref("noscript.mandatory", "[System+Principal] about: about:addons about:blocked about:certerror about:config about:crashes about:feeds about:home about:memory about:neterror about:plugins about:preferences about:privatebrowsing about:sessionrestore about:srcdoc about:support about:tabcrashed blob: chrome: mediasource: moz-extension: moz-safe-about: resource:");
+pref("noscript.default", "about:blank about:pocket-saved about:pocket-signup addons.mozilla.org afx.ms ajax.aspnetcdn.com ajax.googleapis.com bootstrapcdn.com code.jquery.com firstdata.com firstdata.lv gfx.ms google.com googlevideo.com gstatic.com hotmail.com live.com live.net maps.googleapis.com mozilla.net netflix.com nflxext.com nflximg.com nflxvideo.net noscript.net outlook.com passport.com passport.net passportimages.com paypal.com paypalobjects.com securecode.com securesuite.net sfx.ms tinymce.cachefly.net wlxrs.com yahoo.com yahooapis.com yimg.com youtube.com ytimg.com");
+pref("noscript.allowWhitelistUpdates", true);
+pref("noscript.volatilePrivatePermissions", false);
+pref("noscript.showVolatilePrivatePermissionsToggle", true);
+
+pref("noscript.eraseFloatingElements", true);
+
+pref("noscript.bgThumbs.allowed", false);
+pref("noscript.bgThumbs.disableJS", true);
+
+pref("noscript.forbidJava", true);
+pref("noscript.forbidFlash", true);
+pref("noscript.forbidSilverlight", true);
+pref("noscript.forbidPlugins", true);
+pref("noscript.forbidMedia", true);
+pref("noscript.forbidFonts", true);
+pref("noscript.forbidWebGL", false);
+pref("noscript.forbidActiveContentParentTrustCheck", true);
+pref("noscript.forbidIFrames", false);
+pref("noscript.forbidIFramesContext", 3);
+pref("noscript.forbidIFramesParentTrustCheck", true);
+pref("noscript.forbidFrames", false);
+pref("noscript.forbidMixedFrames", true);
+
+pref("noscript.sound.block", "chrome://noscript/skin/block.wav");
+pref("noscript.allowClipboard", false);
+pref("noscript.allowLocalLinks", false);
+pref("noscript.allowLocalLinks.from", "");
+pref("noscript.allowLocalLinks.to", "");
+pref("noscript.allowCachingObjects", true);
+
+pref("noscript.showPlaceholder", true);
+pref("noscript.global", false);
+pref("noscript.globalHttpsWhitelist", false);
+
+pref("noscript.confirmUnblock", true);
+pref("noscript.confirmUnsafeReload", true);
+pref("noscript.statusLabel", false);
+pref("noscript.forbidBookmarklets", false);
+pref("noscript.allowBookmarkletImports", true);
+pref("noscript.allowBookmarks", false);
+pref("noscript.notify.hideDelay", 5);
+pref("noscript.notify.hidePermanent", true);
+
+pref("noscript.notify.hide", false);
+pref("noscript.truncateTitleLen", 255);
+pref("noscript.truncateTitle", true);
+pref("noscript.fixLinks", true);
+
+pref("noscript.noping", true);
+pref("noscript.consoleDump", 0);
+pref("noscript.excaps", true);
+pref("noscript.nselForce", true);
+pref("noscript.nselNever", false);
+pref("noscript.nselNoMeta", true);
+pref("noscript.autoAllow", 0);
+pref("noscript.toolbarToggle", 3);
+pref("noscript.allowPageLevel", 0);
+
+pref("noscript.forbidImpliesUntrust", false);
+pref("noscript.keys.toggle", "ctrl shift VK_BACK_SLASH.|");
+pref("noscript.keys.ui", "ctrl shift S");
+pref("noscript.keys.tempAllowPage", "");
+pref("noscript.keys.revokeTemp", "");
+
+pref("noscript.menuAccelerators", false);
+
+pref("noscript.forbidMetaRefresh", false);
+pref("noscript.forbidMetaRefresh.remember", false);
+pref("noscript.forbidMetaRefresh.notify", true);
+pref("noscript.forbidMetaRefresh.exceptions", "^https?://(?:www|encrypted)\\.google\\.(?:[a-z]{2,3}|[a-z]{2}\\.[a-z]{2,3})/ t.co");
+
+pref("noscript.contentBlocker", false);
+
+pref("noscript.toggle.temp", true);
+pref("noscript.firstRunRedirection", true);
+
+pref("noscript.xss.notify", true);
+pref("noscript.xss.notify.subframes", true);
+pref("noscript.xss.trustReloads", false);
+pref("noscript.xss.trustData", true);
+pref("noscript.xss.trustExternal", true);
+pref("noscript.xss.trustTemp", true);
+pref("noscript.xss.checkInclusions", true);
+pref("noscript.xss.checkInclusions.exceptions", "intensedebate.com/idc/js/");
+pref("noscript.xss.checkCharset.exceptions", "");
+
+pref("noscript.filterXPost", true);
+pref("noscript.filterXGet", true);
+pref("noscript.filterXGetRx", "<+(?=[^<>=\\d. /(-])|[\\\\\"\\x00-\\x07\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F]");
+pref("noscript.filterXGetUserRx", "");
+pref("noscript.filterXExceptions", "^https?://([a-z]+)\\.google\\.(?:[a-z]{1,3}\\.)?[a-z]+/(?:search|custom|\\1)\\?\n^https?://([a-z]*)\\.?search\\.yahoo\\.com/search(?:\\?|/\\1\\b)\n^https?://[a-z]+\\.wikipedia\\.org/wiki/[^\"<>?%]+$\n^https?://translate\\.google\\.com/translate_t[^\"'<>?%]+$\n^https://secure\\.wikimedia\\.org/wikipedia/[a-z]+/wiki/[^\"<>\\?%]+$");
+pref("noscript.filterXExceptions.blogspot", true);
+pref("noscript.filterXExceptions.darla_name", true);
+pref("noscript.filterXExceptions.deviantart", true);
+pref("noscript.filterXExceptions.fbconnect", true);
+pref("noscript.filterXExceptions.ebay", true);
+pref("noscript.filterXExceptions.ggadgets", true);
+pref("noscript.filterXExceptions.letitbit", true);
+pref("noscript.filterXExceptions.livejournal", true);
+pref("noscript.filterXExceptions.lycosmail", true);
+pref("noscript.filterXExceptions.medicare", true);
+pref("noscript.filterXException.photobucket", true);
+pref("noscript.filterXExceptions.printfriendly", true);
+pref("noscript.filterXExceptions.readability", true);
+pref("noscript.filterXExceptions.yahoo", true);
+pref("noscript.filterXExceptions.visa", true);
+pref("noscript.filterXExceptions.verizon", true);
+pref("noscript.filterXExceptions.zendesk", true);
+pref("noscript.filterXExceptions.yt_comments", true);
+
+pref("noscript.protectWindowNameXAssignment", true);
+
+pref("noscript.injectionCheck", 2);
+pref("noscript.injectionCheckPost", true);
+pref("noscript.injectionCheckHTML", true);
+
+pref("noscript.globalwarning", true);
+
+pref("noscript.jsredirectIgnore", false);
+pref("noscript.jsredirectFollow", false);
+pref("noscript.jsredirectForceShow", false);
+
+pref("noscript.removeSMILKeySniffer", true);
+
+pref("noscript.utf7filter", true);
+
+pref("noscript.safeJSRx", "(?:window\\.)?close\\s*\\(\\)");
+
+pref("noscript.badInstall", false);
+
+pref("noscript.fixURI", true);
+pref("noscript.fixURI.exclude", "");
+
+pref("noscript.urivalid.aim", "\\w[^\\\\?&\\x00-\\x1f#]*(?:\\?[^\\\\\\x00-\\x1f#]*(?:#[\\w.@+-]{2,32})?)?");
+pref("noscript.urivalid.mailto", "[^\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]*");
+
+pref("noscript.forbidExtProtSubdocs", true);
+
+pref("noscript.forbidXBL", 1);
+pref("noscript.forbidXHR", 1);
+
+pref("noscript.whitelistRegExp", "");
+
+pref("noscript.tempGlobal", false);
+
+pref("noscript.lockPrivilegedUI", false);
+
+pref("noscript.collapseObject", false);
+
+pref("noscript.showUntrustedPlaceholder", true);
+
+pref("noscript.jsHack", "");
+pref("noscript.jsHackRegExp", "");
+
+pref("noscript.canonicalFQDN", false);
+
+pref("noscript.allowedMimeRegExp", "");
+pref("noscript.alwaysBlockUntrustedContent", true);
+
+pref("noscript.consoleLog", false);
+
+pref("noscript.dropXssProtection", true);
+pref("noscript.flashPatch", true);
+pref("noscript.silverlightPatch", true);
+
+
+pref("noscript.allowURLBarJS", false);
+pref("noscript.allowURLBarImports", false);
+
+pref("noscript.hideOnUnloadRegExp", "video/.*");
+
+pref("noscript.untrusted", "");
+pref("noscript.untrustedGranularity", 3);
+pref("noscript.requireReloadRegExp", "application/x-vnd\\.moveplayer\\b.*");
+
+pref("noscript.restrictSubdocScripting", false);
+pref("noscript.cascadePermissions", false);
+
+pref("noscript.secureCookies", false);
+pref("noscript.secureCookiesExceptions", "");
+pref("noscript.secureCookiesForced", "");
+pref("noscript.secureCookies.recycle", false);
+pref("noscript.secureCookies.perTab", false);
+
+pref("noscript.httpsForced", "");
+pref("noscript.httpsForcedBuiltIn", "www.youtube.com");
+pref("noscript.httpsDefWhitelist", true);
+pref("noscript.allowHttpsOnly", 0);
+
+pref("noscript.https.showInConsole", true);
+
+pref("noscript.clearClick", 3);
+pref("noscript.clearClick.plugins", true);
+pref("noscript.clearClick.prompt", true);
+pref("noscript.clearClick.debug", false);
+pref("noscript.clearClick.exceptions", ".mail.yahoo.com https://mail.google.com/ *.ebay.com *.photobucket.com .youtube.com");
+pref("noscript.clearClick.subexceptions", "^http://bit(?:ly\\.com|\\.ly)/a/sidebar\\?u= http://*.uservoice.com/*/popin.html?* http://w.sharethis.com/share3x/lightbox.html?* http://disqus.com/embed/* *.disqus.com/*/reply.html* http://www.feedly.com/mini abine:*");
+pref("noscript.clearClick.rapidFireCheck", true);
+pref("noscript.clearClick.threshold", 18);
+
+pref("noscript.emulateFrameBreak", true);
+
+pref("noscript.stickyUI.liveReload", false);
+pref("noscript.stickyUI", true);
+pref("noscript.stickyUI.onKeyboard", true);
+pref("noscript.hoverUI", true);
+pref("noscript.hoverUI.delayEnter", 250);
+pref("noscript.hoverUI.delayStop", 50);
+pref("noscript.hoverUI.delayExit1", 250);
+pref("noscript.hoverUI.delayExit2", 300);
+pref("noscript.hoverUI.excludeToggling", true);
+
+pref("noscript.ignorePorts", true);
+
+pref("noscript.cp.last", true);
+
+pref("noscript.sanitizePaste", true);
+
+pref("noscript.surrogate.enabled", true);
+pref("noscript.surrogate.debug", false);
+pref("noscript.surrogate.sandbox", true);
+pref("noscript.surrogate.matchPrivileged", false);
+pref("noscript.surrogate.2mdn.replacement", "if('Proxy' in window){let _f=function(){}; google=$S(); Object.defineProperty(google,'__noSuchMethod__',{configurable:true,enumerable:false,value:_f});let ima={};ima.AdsManagerLoadedEvent=ima.AdErrorEvent={Type:new Proxy({},{get:function(){return 0}}),};ima.settings=new Proxy({},{get:function(){return _f}});ima.AdsLoader=ima.AdsRequest=ima.AdDisplayContainer=function(){return new Proxy({},{get:function(){return _f}});};google.ima=ima;}");
+pref("noscript.surrogate.2mdn.sources", ".2mdn.net");
+pref("noscript.surrogate.360Haven.sources", "@www.360haven.com");
+pref("noscript.surrogate.360Haven.replacement", "Object.defineProperty(window,'adblock',{get:function() false,set: function() false});Object.defineProperty(window,'google_ad_client',{get: function () { return $S({__noSuchMethod__: function() this})}});Object.defineProperty(window.HTMLBodyElement.prototype,'innerHTML',{get:function() ''});");
+pref("noscript.surrogate.adagionet.sources", ".adagionet.com");
+pref("noscript.surrogate.adagionet.replacement", "adagioWriteTag=adagioWriteBanner=function(){}");
+pref("noscript.surrogate.addthis.sources", "^https?://(?:[^/:]+\\.)?addthis\\.com/.*addthis_widget\\.js");
+pref("noscript.surrogate.addthis.replacement", "addthis=(function(){var f=$S(arguments.callee);return f.__noSuchMethod__=f.data=f.bar=f.dynamic=f.login=f.ad=f.util=f.user=f.session=f})();");
+pref("noscript.surrogate.adfly.sources", "!@^https?://adf.ly/\\w+/?$");
+pref("noscript.surrogate.adfly.replacement", "for(var a=/ysmm = '(.*?)';/gi.exec(document.documentElement.innerHTML)[1],b='',c='',d=0;d<a.length;d++)0==d%2?b+=a.charAt(d):c=a.charAt(d)+c;window.location=atob(b+c).substring(2)");
+pref("noscript.surrogate.ampush.sources", ".ampush.io");
+pref("noscript.surrogate.ampush.replacement", "window.ampt=$S({__noSuchMethod__:function(){}});");
+pref("noscript.surrogate.digg.sources", "!@digg.com/newsbar/*");
+pref("noscript.surrogate.digg.replacement", "window.location.href=document.querySelector('link[rel=canonical]').href");
+pref("noscript.surrogate.dimtus.sources", "!@^http://(?:dimtus|imageteam)\\.(?:com|org)/img-");
+pref("noscript.surrogate.dimtus.replacement", "document.querySelector('.overlay_ad').style.display='none'");
+pref("noscript.surrogate.ga.sources", "*.google-analytics.com");
+pref("noscript.surrogate.ga.replacement", "(function(){var _0=$S(function()_0),_u=function(){};_0.__noSuchMethod__=_0;('ga'in window)||(ga=_u);window.urchinTracker=window._u||_u;window._gaq=$S({__noSuchMethod__:_0,push:function(f){if(typeof f=='function')f();else if(f&&f.shift&&f[0]in this)this[f.shift()].apply(this,f)},_set:function(a,b){if(typeof b=='function')b()},_link:function(h){if(h)location.href=h},_linkByPost:function(f){if(f&&f.submit)f.submit();return true},_getLinkerUrl:function(u){return u},_trackEvent:_0});window._gat=$S({__noSuchMethod__:function(){return _gaq},_getTrackerByName:function(){return {_visitCode:function(){return 0}}}});window.cxApi=$S({__noSuchMethod__:_0,getChosenVariation:function(x){return typeof x == 'number' ? x : x[0]},chooseVariation:function(x){return 0}})})()");
+pref("noscript.surrogate.glinks.replacement", "['focus','mouseover','mousedown','click'].forEach(function(et){addEventListener(et,function(e){var a=e.target,href=a.href&&a.getAttribute&&a.getAttribute('href');if(href&&/^(?:http|\\/url)/.test(href)&&!a._href){a._href=a.href=a.href.replace(/.*\\/url.*[?&](?:url|q)=(http[^&]+).*/,function(a,b)decodeURIComponent(b));do{if(/\\brwt\\(/.test(a.getAttribute('onmousedown')))a.removeAttribute('onmousedown')}while((a=a.parentElement))}},true)})");
+pref("noscript.surrogate.glinks.sources", "!@^https?://[^/]+google\\..*/search");
+pref("noscript.surrogate.googletag.replacement", "if(typeof googletag==='undefined'){googletag={slots:{},cmd:$S({__noSuchMethod__:function(){return $S(this)},push:function(f){return f()}})};}googletag.defineSlot=function(){return $S({__noSuchMethod__:function(){return $S(this)}})};let _gt=googletag;googletag=new Proxy(_gt,{get:function(s,w,e){return w in s?s[w]:function(){return $S({__noSuchMethod__:function(){return googletag;}})};}});let _renderedAds=new Proxy({},{get:function(a,b){return b in a?a[b]:{size:[729,90]};}});let _adsRenderedInfo=new Proxy({get:function(n){return _renderedAds[n];}},{get:function(x,c){return c in x?x[c]:function(){};},set:function(x,c,v){}});Object.defineProperty(googletag,'adsRenderedInfo',{configurable:true,enumerable:true,set:function(){},get:function(){return _adsRenderedInfo;}});");
+pref("noscript.surrogate.googletag.sources", ".googletagservices.com");
+pref("noscript.surrogate.gravatar.sources", ".gravatar.com");
+pref("noscript.surrogate.gravatar.replacement", "Gravatar=$S({my_hash:'', profile_cb:function(){}, init:function(){}, __noSuchMethod__:function(){}})");
+pref("noscript.surrogate.microsoftSupport.replacement", "let c=document.getElementById('contentArea');if(c)c.style.display=''");
+pref("noscript.surrogate.microsoftSupport.sources", "!support.microsoft.com");
+pref("noscript.surrogate.modpagespeed.replacement", "let s=document.querySelector('noscript>meta[http-equiv=refresh]+style');if(s)s.parentNode.removeChild(s)");
+pref("noscript.surrogate.modpagespeed.sources", "!@^https?:");
+pref("noscript.surrogate.qs.sources", "*.quantserve.com");
+pref("noscript.surrogate.qs.replacement", "window.quantserve=function(){}");
+pref("noscript.surrogate.uniblue.sources", "!@.uniblue.com .liutilities.com");
+pref("noscript.surrogate.uniblue.replacement", "Array.forEach(document.links,function(l){if(/^https:\\/\\/store\\./.test(l.href)){l.setAttribute('href',l.href.replace(/.*?:/, ''));l.parentNode.replaceChild(l,l)}})");
+pref("noscript.surrogate.yieldman.sources", "*.yieldmanager.com");
+pref("noscript.surrogate.yieldman.replacement", "rmAddKey=rmAddCustomKey=rmShowAd=rmShowPop=rmShowInterstitial=rmGetQueryParameters=rmGetSize=rmGetWindowUrl=rmGetPubRedirect=rmGetClickUrl=rmReplace=rmTrim=rmUrlEncode=rmCanShowPop=rmCookieExists=rmWritePopFrequencyCookie=rmWritePopExpirationCookie=flashIntalledCookieExists=writeFlashInstalledCookie=flashDetection=rmGetCookie=function(){}");
+pref("noscript.surrogate.popunder.sources", "@^http:\\/\\/[\\w\\-\\.]+\\.[a-z]+ wyciwyg:");
+pref("noscript.surrogate.popunder.replacement", "(function(){var unloading=false;addEventListener('pagehide',function(){unloading=true;setTimeout(function(){unloading=false},100)},true);var cookie=document.__proto__.__lookupGetter__('cookie');document.__proto__.__defineGetter__('cookie',function() {if(unloading)return cookie.apply(this);var c='; popunder=yes; popundr=yes; setover18=1';return(cookie.apply(this).replace(c,'')+c).replace(/^; /, '')});var fid='_FID_'+(Date.now().toString(16));var open=window.__proto__.open;window.__proto__.open=function(url,target,features){try{if(!(/^_(?:top|parent|self)$/i.test(target)||target in frames)){var suspSrc,suspCall,ff=[],ss=new Error().stack.split('\\n').length;if(/popunde?r/i.test(target))return ko();for(var f,ev,aa=arguments;stackSize-->2&&aa.callee&&(f=aa.callee.caller)&&ff.indexOf(f)<0;ff.push(f)){aa=f.arguments;if(!aa)break;ev=aa[0];suspCall=f.name=='doPopUnder';if(!suspSrc)suspSrc=suspCall||/(?:\\bpopunde?r|\\bfocus\\b.*\\bblur|\\bblur\\b.*\\bfocus|[pP]uShown)\\b/.test(f.toSource());if(suspCall||ev&&typeof ev=='object'&&('type' in ev)&&ev.type=='click'&&ev.button===0&&(ev.currentTarget===document||('tagName' in ev.currentTarget)&&'body'==ev.currentTarget.tagName.toLowerCase())&&!(('href' in ev.target)&&ev.target.href&&(ev.target.href.indexOf(url)===0||url.indexOf(ev.target.href)===0))){if(suspSrc)return ko();}}}}catch(e){}return open.apply(null, arguments);function ko(){var fr=document.getElementById(fid)||document.body.appendChild(document.createElement('iframe'));fr.id=fid;fr.src='data:text/html,';fr.style.display='none';var w=fr.contentWindow;w.blur=function(){};return w;}}})()");
+pref("noscript.surrogate.popunder.exceptions", ".meebo.com");
+pref("noscript.surrogate.imdb.sources", "@*.imdb.com/video/*");
+pref("noscript.surrogate.imdb.replacement", "addEventListener('DOMContentLoaded',function(ev){ad_utils.render_ad=function(w){w.location=w.location.href.replace(/.*\\bTRAILER=([^&]+).*/,'$1')}},true)");
+pref("noscript.surrogate.nscookie.sources", "@*.facebook.com");
+pref("noscript.surrogate.nscookie.replacement", "document.cookie='noscript=; domain=.facebook.com; path=/; expires=Thu, 01-Jan-1970 00:00:01 GMT;'");
+pref("noscript.surrogate.imagebam.replacement", "(function(){if(\"over18\" in window){var _do=doOpen;doOpen=function(){};over18();doOpen=_do}else{var e=document.getElementById(Array.slice(document.getElementsByTagName(\"script\")).filter(function(s){return !!s.innerHTML})[0].innerHTML.match(/over18[\\s\\S]*?'([^']+)/)[1]);e.style.display='none'}})()");
+pref("noscript.surrogate.imagebam.sources", "!@*.imagebam.com");
+pref("noscript.surrogate.imagehaven.replacement", "['agreeCont','TransparentBlack'].forEach(function(id){var o=document.getElementById(id);if(o)o.style.display='none'})");
+pref("noscript.surrogate.imagehaven.sources", "!@*.imagehaven.net");
+pref("noscript.surrogate.imgreserve.sources", "!imgreserve.com");
+pref("noscript.surrogate.imgreserve.replacement", "let b=document.querySelector('input[value=\"YES\"]');if(b)b.addEventListener('click',function(){document.cookie='AgeVerification=1';location.href=location},true)");
+pref("noscript.surrogate.interstitialBox.replacement", "__defineSetter__('interstitialBox',function(){});__defineGetter__('interstitialBox',function(){return{}})");
+pref("noscript.surrogate.interstitialBox.sources", "@*.imagevenue.com");
+pref("noscript.surrogate.invodo.sources", ".invodo.com");
+pref("noscript.surrogate.invodo.replacement", "Invodo=$S({__noSuchMethod__:function(){}})");
+pref("noscript.surrogate.googleThumbs.replacement", "(function(){var ss=document.getElementsByTagName('script');var s,t,m,id,i;for(var j=ss.length;j-->0;)if(((s=ss[j])&&(t=s.firstChild&&s.firstChild.nodeValue)&&(id=t.match(/\\w+thumb\\d+/))&&(m=t.match(/['\"](data:[^'\"]+)/)))&&(i=document.getElementById(id)))i.src=m[1].replace(/\\\\(u[0-9a-f]{4}|x[0-9a-f]{2})/ig,function(a,b){return String.fromCharCode(parseInt(b.substring(1), 16))})})()");
+pref("noscript.surrogate.googleThumbs.sources", "!^https?://www\\.google\\.[a-z]+/search");
+pref("noscript.surrogate.amo.replacement", "addEventListener('click',function(e){if(e.button)return;var a=e.target.parentNode;var hash=a.getAttribute('data-hash');if(hash){var b=a.parentNode.parentNode;InstallTrigger.install({x:{URL:a.href,IconURL:b.getAttribute('data-icon'),Hash:hash,toString:function(){return a.href}}});e.preventDefault()}},false)");
+pref("noscript.surrogate.amo.sources", "!https://addons.mozilla.org/");
+pref("noscript.surrogate.ab_adsense.sources", "pagead2.googlesyndication.com");
+pref("noscript.surrogate.ab_adsense.replacement", "gaGlobal={}");
+pref("noscript.surrogate.ab_adscale.sources", "js.adscale.de");
+pref("noscript.surrogate.ab_adscale.replacement", "adscale={}");
+pref("noscript.surrogate.ab_adtiger.sources", "^http://ads\\.adtiger\\.");
+pref("noscript.surrogate.ab_adtiger.replacement", "adspirit_pid={}");
+pref("noscript.surrogate.ab_bidvertiser.sources", "^http://bdv\\.bidvert");
+pref("noscript.surrogate.ab_bidvertiser.replacement", "report_error=function(){}");
+pref("noscript.surrogate.ab_binlayer.sources", "^http://view\\.binlay(?:er)\\.");
+pref("noscript.surrogate.ab_binlayer.replacement", "blLayer={}");
+pref("noscript.surrogate.ab_mirago.sources", "^http://intext\\.mirago\\.");
+pref("noscript.surrogate.ab_mirago.replacement", "HLSysBannerUrl=''");
+pref("noscript.surrogate.ab_mirando.sources", "^http://get\\.mirando\\.");
+pref("noscript.surrogate.ab_mirando.replacement", "Mirando={}");
+pref("noscript.surrogate.facebook_connect.sources", "connect.facebook.net");
+pref("noscript.surrogate.facebook_connect.replacement", "FB=(function(){var f=$S(arguments.callee);return f.__noSuchMethod__=f.Event=f.XFBML=f;})();");
+pref("noscript.surrogate.revsci.sources", "js.revsci.net");
+pref("noscript.surrogate.revsci.replacement", "rsinetsegs=[];DM_addEncToLoc=DM_tag=function(){};");
+pref("noscript.surrogate.adriver.sources", "ad.adriver.ru/cgi-bin/erle.cgi");
+pref("noscript.surrogate.adriver.replacement", "if(top!==self&&top.location.href===location.href)setTimeout('try{document.close();}catch(e){}',100)");
+pref("noscript.surrogate.twitter.sources", "platform.twitter.com");
+pref("noscript.surrogate.twitter.replacement", "twttr=(function(){var f=$S(arguments.callee); var ro = f.__noSuchMethod__=f.events=f.anywhere=f; ro.widgets=$S({__noSuchMethod__:function(){}}); return ro})();");
+pref("noscript.surrogate.plusone.sources", "apis.google.com/js/plusone.js");
+pref("noscript.surrogate.plusone.replacement", "gapi=(function(){var f=$S(arguments.callee);return f.__noSuchMethod__=f.plusone=f;})();");
+pref("noscript.surrogate.disqus-theme.sources", ">.disqus.com/*/build/themes/t_c4ca4238a0b923820dcc509a6f75849b.js*");
+pref("noscript.surrogate.disqus-theme.replacement", "DISQUS.dtpl.actions.register('comments.reply.new.onLoadingStart', function() { DISQUS.dtpl.actions.remove('comments.reply.new.onLoadingStart'); DISQUS.dtpl.actions.remove('comments.reply.new.onLoadingEnd');});");
+pref("noscript.surrogate.skimlinks.sources", ".skimlinks.com/api/");
+pref("noscript.surrogate.skimlinks.replacement", "window.skimlinks=function(){}");
+pref("noscript.surrogate.picbucks.sources", "!*.picbucks.com http://www.imagebax.com/show.php/*");
+pref("noscript.surrogate.picbucks.replacement", "Array.forEach(document.getElementsByTagName('script'), function(s){let m = s.textContent.match(/(?:Lbjs\\.TargetUrl\\s*=\\s*|Array\\s*\\().*(\\bhttp[^'\"]*)/); if (m) { location.href = m[1]; throw 'break'; }})");
+pref("noscript.surrogate.imagebunk.sources", "!http://imagebunk.com/image/*");
+pref("noscript.surrogate.imagebunk.replacement", "document.body.insertBefore(document.getElementById('img_obj'), document.body.firstChild)");
+pref("noscript.surrogate.picsee.sources", "!^https?://picsee\\.net/2\\d.*\\.html");
+pref("noscript.surrogate.picsee.replacement", "location.replace(location.href.replace(/(\\/2\\d{3}[^\\/]*)(.*)\\.html/, '/upload$1/$2'));");
+pref("noscript.surrogate.owasp_antiClickjack.sources", "!^https?://");
+pref("noscript.surrogate.owasp_antiClickjack.replacement", "if(window.top===window&&document.body.offsetWidth===0)['body','documentElement'].forEach(function(e){document[e].style.setProperty('display','unset','important')})");
+pref("noscript.surrogate.gigya.replacement", "gigya=$S({__noSuchMethod__:function(){}, isGigya:true, __initialized:true});gigya.socialize=$S({__noSuchMethod__:function(){}, addEventHandlers:function(){}});gigya.accounts=$S({__noSuchMethod__:function(){}})");
+pref("noscript.surrogate.gigya.sources", ".gigya.com");
+pref("noscript.surrogate.stripe.replacement", "Stripe=$S({__noSuchMethod__:function(){}})");
+pref("noscript.surrogate.stripe.sources", "js.stripe.com");
+pref("noscript.surrogate.wp.sources", "!^.*\\/20\\d{2}\\/\\d{2}\\/\\d{2}\\/");
+pref("noscript.surrogate.wp.replacement", "let s=document.createElement('style');s.textContent='.site{opacity: 1 !important}';document.documentElement.appendChild(s)");
+
+pref("noscript.fakeScriptLoadEvents.enabled", true);
+pref("noscript.fakeScriptLoadEvents.onlyRequireJS", true);
+pref("noscript.fakeScriptLoadEvents.exceptions", "");
+pref("noscript.fakeScriptLoadEvents.docExceptions", "");
+
+pref("noscript.placeholderMinSize", 32);
+pref("noscript.placeholderLongTip", true);
+pref("noscript.placeholderCollapseOnClose", false);
+
+pref("noscript.compat.evernote", true);
+pref("noscript.compat.gnotes", true);
+
+pref("noscript.forbidXSLT", true);
+
+pref("noscript.oldStylePartial", false);
+pref("noscript.proxiedDNS", 0);
+pref("noscript.placesPrefs", false);
+
+pref("noscript.ABE.enabled", true);
+pref("noscript.ABE.siteEnabled", false);
+pref("noscript.ABE.allowRulesetRedir", false);
+pref("noscript.ABE.legacyPrompt", false);
+pref("noscript.ABE.disabledRulesetNames", "");
+pref("noscript.ABE.skipBrowserRequests", true);
+pref("noscript.ABE.notify", true);
+pref("noscript.ABE.notify.namedLoopback", false);
+pref("noscript.ABE.wanIpAsLocal", false);
+pref("noscript.ABE.wanIpCheckURL", "https://secure.informaction.com/ipecho/");
+pref("noscript.ABE.localExtras", "");
+
+pref("noscript.asyncNetworking", true);
+pref("noscript.inclusionTypeChecking", true);
+pref("noscript.inclusionTypeChecking.exceptions", "https://scache.vzw.com/ http://cache.vzw.com .sony-europe.com .amazonaws.com .hp-ww.com .yandex.st cdn.directvid.com/*.jsx");
+pref("noscript.inclusionTypeChecking.checkDynamic", false);
+pref("noscript.nosniff", true);
+
+pref("noscript.recentlyBlockedCount", 10);
+pref("noscript.showRecentlyBlocked", true);
+pref("noscript.recentlyBlockedLevel", 0);
+
+pref("noscript.frameOptions.enabled", true);
+pref("noscript.frameOptions.parentWhitelist", "https://mail.google.com/*");
+pref("noscript.logDNS", false);
+
+
+pref("noscript.subscription.lastCheck", 0);
+pref("noscript.subscription.checkInterval", 24);
+pref("noscript.subscription.trustedURL", "");
+pref("noscript.subscription.untrustedURL", "");
+
+pref("noscript.siteInfoProvider", "https://noscript.net/about/%utf8%;%ace%");
+pref("noscript.alwaysShowObjectSources", false);
+
+pref("noscript.ef.enabled", false);
+
+pref("noscript.showBlankSources", false);
+pref("noscript.preset", "medium");
+
+pref("noscript.forbidBGRefresh", 1);
+pref("noscript.forbidBGRefresh.exceptions", ".mozilla.org");
+
+pref("noscript.toStaticHTML", true);
+pref("noscript.liveConnectInterception", true);
+pref("noscript.audioApiInterception", true);
+
+pref("noscript.doNotTrack.enabled", true);
+pref("noscript.doNotTrack.exceptions", "");
+pref("noscript.doNotTrack.forced", "");
+
+pref("noscript.ajaxFallback.enabled", true);
+pref("noscript.sync.enabled", false);
+
+pref("noscript.ABE.rulesets.SYSTEM", "# Prevent Internet sites from requesting LAN resources.\r\nSite LOCAL\r\nAccept from LOCAL\r\nDeny");
+pref("noscript.ABE.rulesets.USER", "# User-defined rules. Feel free to experiment here.\r\n");
+pref("noscript.ABE.migration", 0);
+
+pref("noscript.smartClickToPlay", true);
+
+pref("noscript.removalWarning", true);
+pref("noscript.middlemouse_temp_allow_main_site", true);
+pref("noscript.webext.enabled", true);
diff --git a/extensions/noscript/install.rdf b/extensions/noscript/install.rdf
new file mode 100644
index 0000000..4d2fd5b
--- /dev/null
+++ b/extensions/noscript/install.rdf
@@ -0,0 +1,102 @@
+<?xml version="1.0"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+ <Description about="urn:mozilla:install-manifest">
+
+ <em:id>{73a6fe31-595d-460b-a920-fcc0f8843232}</em:id>
+ <em:name>NoScript</em:name>
+ <em:version>5.1.8.5</em:version>
+ <em:description>Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality... Experts will agree: Firefox is really safer with NoScript :-)</em:description>
+ <em:creator>Giorgio Maone</em:creator>
+ <em:type>2</em:type>
+ <em:updateURL>https://secure.informaction.com/download/classic/?v=5.1.8.5</em:updateURL>
+ <em:contributor>aivo (Estonian translation)</em:contributor>
+ <em:contributor>Alberto Martínez, EduLeo &amp; Urko (Spanish translation)</em:contributor>
+ <em:contributor>Algimantas Margevi&#x10d;ius (Lithuanian translation)</em:contributor>
+ <em:contributor>Asaf Bartov &amp; baryoni (Hebrew translation)</em:contributor>
+ <em:contributor>Alf and Liesbeth (Dutch translation)</em:contributor>
+ <em:contributor>Alexander Sokolov, Sergei Smirnov and negodnik (Russian translation)</em:contributor>
+ <em:contributor>Batuhan Çetin, Volkan Gezer and eveterinary (Turkish translation)</em:contributor>
+ <em:contributor>Baurzhan Muftakhidinov (Kazakh translation)</em:contributor>
+ <em:contributor>Beerboy &amp; Haebaru (Japanese translation)</em:contributor>
+ <em:contributor>Carsten Winkler (Danish translation)</em:contributor>
+ <em:contributor>Chiou Po-Jung (Chinese Traditional translation)</em:contributor>
+ <em:contributor>Dario Ornelas (Portuguese translation)</em:contributor>
+ <em:contributor>drAcOniS and Petr Jirsa (Czech translation)</em:contributor>
+ <em:contributor>Drive DRKA and Dzmitry Drazdou (Belarusian translation)</em:contributor>
+ <em:contributor>Engin Yazılan, Erkan Kaplan &amp; Fathi (Turkish translation)</em:contributor>
+ <em:contributor>Georgi Marchev (Bulgarian translation)</em:contributor>
+ <em:contributor>Håvard Mork (Norwegian bokmål translation)</em:contributor>
+ <em:contributor>Hwasung Kim (Places bookmarklet patch)</em:contributor>
+ <em:contributor>Ivan Pesic, dragan021 (Serbian translation)</em:contributor>
+ <em:contributor>Ivan Jonoski (Macedonian translation)</em:contributor>
+ <em:contributor>Jameka (Swedish translation)</em:contributor>
+ <em:contributor>Joan-Josep Bargues (Catalan translation)</em:contributor>
+ <em:contributor>Joshua Issac (Malay translation)</em:contributor>
+ <em:contributor>Khaled Hosny &amp; Nassim Dhaher (Arabic translation)</em:contributor>
+ <em:contributor>Krcko (Croatian translation)</em:contributor>
+ <em:contributor>Ian Moody (English GB translation)</em:contributor>
+ <em:contributor>LocaLiceR (Hungarian translation)</em:contributor>
+ <em:contributor>Lukasz Biegaj &amp; Teo (Polish translation)</em:contributor>
+ <em:contributor>Michela Venuto (inspiration)</em:contributor>
+ <em:contributor>Mika Pirinen (Finnish translation)</em:contributor>
+ <em:contributor>Mindaugas Jakutis (Lithuanian translation)</em:contributor>
+ <em:contributor>Mikes Kaszmán István (Hungarian translation)</em:contributor>
+ <em:contributor>MozUA (Ukrainian translation)</em:contributor>
+ <em:contributor>Pedram Veisi (Persian translation)</em:contributor>
+ <em:contributor>Peter Bradley (Welsh translation)</em:contributor>
+ <em:contributor>Raryel Costa Souza (Brazilian Portuguese)</em:contributor>
+ <em:contributor>regfreak (Indonesian translation)</em:contributor>
+ <em:contributor>roebek (Galician translation)</em:contributor>
+ <em:contributor>Qen (Thai translation)</em:contributor>
+ <em:contributor>seaousak (Korean translation)</em:contributor>
+ <em:contributor>SlovakSoft (Slovak translation)</em:contributor>
+ <em:contributor>Sonickydon (Greek translation)</em:contributor>
+ <em:contributor>Stiepan A. Kovac (Croatian translation)</em:contributor>
+ <em:contributor>swarnava (Bengali translation)</em:contributor>
+ <em:contributor>Tomaz Macus (Slovenian translation)</em:contributor>
+ <em:contributor>Thomas, milupo &amp; Volker Hable (German translation)</em:contributor>
+ <em:contributor>tonynguyen and loveleeyoungae (Vietnamese translation)</em:contributor>
+ <em:contributor>x10firefox and Ultravioletu (Romanian translation)</em:contributor>
+ <em:contributor>Xavier Robin &amp; BlackJack (French translation)</em:contributor>
+ <em:contributor>X.F Mao &amp; George C. Tsoi (Simplified Chinese)</em:contributor>
+ <em:optionsURL>chrome://noscript/content/noscriptOptions.xul</em:optionsURL>
+ <em:homepageURL>https://noscript.net</em:homepageURL>
+ <em:iconURL>chrome://noscript/skin/icon32.png</em:iconURL>
+ <em:icon64URL>chrome://noscript/skin/icon64.png</em:icon64URL>
+ <em:aboutURL>chrome://noscript/content/about.xul</em:aboutURL>
+ <em:multiprocessCompatible>true</em:multiprocessCompatible>
+ <em:hasEmbeddedWebExtension>true</em:hasEmbeddedWebExtension>
+ <em:bootstrap>true</em:bootstrap>
+ <!-- Firefox -->
+ <em:targetApplication>
+ <Description>
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+ <em:minVersion>45.0</em:minVersion>
+ <em:maxVersion>56.0</em:maxVersion>
+ <em:strictCompatibility>true</em:strictCompatibility>
+ </Description>
+ </em:targetApplication>
+
+ <!-- SeaMonkey -->
+ <em:targetApplication>
+ <Description>
+ <em:id>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</em:id>
+ <em:minVersion>2.42</em:minVersion>
+ <em:maxVersion>*</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+ <!-- Pale Moon -->
+ <em:targetApplication>
+ <Description>
+ <em:id>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</em:id>
+ <em:minVersion>27.0.2</em:minVersion>
+ <em:maxVersion>*</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+ </Description>
+
+
+
+
+</RDF>
diff --git a/extensions/noscript/mozilla.cfg b/extensions/noscript/mozilla.cfg
new file mode 100644
index 0000000..cac13e4
--- /dev/null
+++ b/extensions/noscript/mozilla.cfg
@@ -0,0 +1,13 @@
+//
+// sample configuration to lock whitelist using the method explained here:
+// http://ilias.ca/blog/2005/03/locking-mozilla-firefox-settings/
+
+
+// you'd better copy the site list from the "capability.policy.maonoscript.sites"
+// key in the prefs.js file found in a test profile
+lockPref("noscript.default", "informaction.com https://informaction.com flashgot.net https://flashgot.net noscript.net https://noscript.net");
+
+lockPref("noscript.ctxMenu", false); // hide context menu
+lockPref("noscript.statusIcon", false); // hide statusIcon
+lockPref("noscript.notify", false); // hide notification bar
+lockPref("noscript.lockPrivilegedUI"); // disable DOM Inspector and Error Console (which may be used to programmatically unlock the prefs)
diff --git a/extensions/noscript/webextension/legacy.js b/extensions/noscript/webextension/legacy.js
new file mode 100644
index 0000000..80ed81d
--- /dev/null
+++ b/extensions/noscript/webextension/legacy.js
@@ -0,0 +1,36 @@
+var legacyPort;
+try {
+ let oldBackupCleared = false;
+ legacyPort = browser.runtime.connect({name: "legacy"});
+ legacyPort.onMessage.addListener(msg => {
+ switch(msg.type) {
+ case "saveData":
+ let backup = msg.data;
+ browser.storage.local.set({legacyBackup: backup}).then(() => {
+ console.log("NoScript preferences backup on the WebExtension side");
+ if (!oldBackupCleared) {
+ oldBackupCleared = true;
+ browser.storage.local.remove(Object.keys(backup)).then(() => {
+ console.log("Old format backup (pre-5.1) cleared");
+ }, (e) => {
+ console.error(e);
+ });
+
+ }
+ }, (e) => {
+ console.error("NoScript failed to back up non-default preference in WebExtension! %o", e);
+ });
+
+ break;
+
+ case "dumpData":
+ browser.storage.local.get(null, items => console.log(JSON.stringify(items)));
+ break;
+ }
+ });
+ browser.runtime.sendMessage("Hybrid WebExtension NoScript Ready");
+} catch(e) {
+ legacyPort = null;
+ console.error(e);
+}
+
diff --git a/extensions/noscript/webextension/manifest.json b/extensions/noscript/webextension/manifest.json
new file mode 100644
index 0000000..c03347b
--- /dev/null
+++ b/extensions/noscript/webextension/manifest.json
@@ -0,0 +1,28 @@
+{
+ "manifest_version": 2,
+ "name": "NoScript",
+ "applications": {
+ "gecko": {
+ "id": "{73a6fe31-595d-460b-a920-fcc0f8843232}",
+ "strict_min_version": "52.0"
+ }
+ },
+ "version": "10.1.0",
+ "description": "NoScript Security Suite",
+
+ "permissions": [
+ "contextMenus",
+ "privacy",
+ "storage",
+ "tabs",
+ "unlimitedStorage",
+ "webNavigation",
+ "webRequest",
+ "webRequestBlocking",
+ "<all_urls>"
+ ],
+
+ "background": {
+ "scripts": ["legacy.js"]
+ }
+}
diff --git a/extensions/pdfjs/LICENSE b/extensions/pdfjs/LICENSE
deleted file mode 100644
index f433b1a..0000000
--- a/extensions/pdfjs/LICENSE
+++ /dev/null
@@ -1,177 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
diff --git a/extensions/pdfjs/README.mozilla b/extensions/pdfjs/README.mozilla
deleted file mode 100644
index 884f85e..0000000
--- a/extensions/pdfjs/README.mozilla
+++ /dev/null
@@ -1,3 +0,0 @@
-This is the pdf.js project output, https://github.com/mozilla/pdf.js
-
-Current extension version is: 1.6.315
diff --git a/extensions/pdfjs/chrome.manifest b/extensions/pdfjs/chrome.manifest
deleted file mode 100644
index 1aef83a..0000000
--- a/extensions/pdfjs/chrome.manifest
+++ /dev/null
@@ -1 +0,0 @@
-resource pdf.js content/
diff --git a/extensions/pdfjs/content/PdfJs.jsm b/extensions/pdfjs/content/PdfJs.jsm
deleted file mode 100644
index b3d8543..0000000
--- a/extensions/pdfjs/content/PdfJs.jsm
+++ /dev/null
@@ -1,348 +0,0 @@
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* jshint esnext:true */
-/* globals Components, Services, XPCOMUtils, PdfjsChromeUtils,
- PdfjsContentUtils, PdfStreamConverter */
-
-'use strict';
-
-var EXPORTED_SYMBOLS = ['PdfJs'];
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-const Cm = Components.manager;
-const Cu = Components.utils;
-
-const PREF_PREFIX = 'pdfjs';
-const PREF_DISABLED = PREF_PREFIX + '.disabled';
-const PREF_MIGRATION_VERSION = PREF_PREFIX + '.migrationVersion';
-const PREF_PREVIOUS_ACTION = PREF_PREFIX + '.previousHandler.preferredAction';
-const PREF_PREVIOUS_ASK = PREF_PREFIX +
- '.previousHandler.alwaysAskBeforeHandling';
-const PREF_DISABLED_PLUGIN_TYPES = 'plugin.disable_full_page_plugin_for_types';
-const TOPIC_PDFJS_HANDLER_CHANGED = 'pdfjs:handlerChanged';
-const TOPIC_PLUGINS_LIST_UPDATED = 'plugins-list-updated';
-const TOPIC_PLUGIN_INFO_UPDATED = 'plugin-info-updated';
-const PDF_CONTENT_TYPE = 'application/pdf';
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-
-var Svc = {};
-XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
- '@mozilla.org/mime;1',
- 'nsIMIMEService');
-XPCOMUtils.defineLazyServiceGetter(Svc, 'pluginHost',
- '@mozilla.org/plugin/host;1',
- 'nsIPluginHost');
-XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsChromeUtils',
- 'resource://pdf.js/PdfjsChromeUtils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsContentUtils',
- 'resource://pdf.js/PdfjsContentUtils.jsm');
-
-function getBoolPref(aPref, aDefaultValue) {
- try {
- return Services.prefs.getBoolPref(aPref);
- } catch (ex) {
- return aDefaultValue;
- }
-}
-
-function getIntPref(aPref, aDefaultValue) {
- try {
- return Services.prefs.getIntPref(aPref);
- } catch (ex) {
- return aDefaultValue;
- }
-}
-
-function isDefaultHandler() {
- if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) {
- return PdfjsContentUtils.isDefaultHandlerApp();
- }
- return PdfjsChromeUtils.isDefaultHandlerApp();
-}
-
-function initializeDefaultPreferences() {
- var DEFAULT_PREFERENCES =
-{
- "showPreviousViewOnLoad": true,
- "defaultZoomValue": "",
- "sidebarViewOnLoad": 0,
- "enableHandToolOnLoad": false,
- "enableWebGL": false,
- "pdfBugEnabled": false,
- "disableRange": false,
- "disableStream": false,
- "disableAutoFetch": false,
- "disableFontFace": false,
- "disableTextLayer": false,
- "useOnlyCssZoom": false,
- "externalLinkTarget": 0,
- "enhanceTextSelection": false,
- "renderInteractiveForms": false,
- "disablePageLabels": false
-}
-
-
- var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
- var defaultValue;
- for (var key in DEFAULT_PREFERENCES) {
- defaultValue = DEFAULT_PREFERENCES[key];
- switch (typeof defaultValue) {
- case 'boolean':
- defaultBranch.setBoolPref(key, defaultValue);
- break;
- case 'number':
- defaultBranch.setIntPref(key, defaultValue);
- break;
- case 'string':
- defaultBranch.setCharPref(key, defaultValue);
- break;
- }
- }
-}
-
-// Register/unregister a constructor as a factory.
-function Factory() {}
-Factory.prototype = {
- register: function register(targetConstructor) {
- var proto = targetConstructor.prototype;
- this._classID = proto.classID;
-
- var factory = XPCOMUtils._getFactory(targetConstructor);
- this._factory = factory;
-
- var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
- registrar.registerFactory(proto.classID, proto.classDescription,
- proto.contractID, factory);
-
- if (proto.classID2) {
- this._classID2 = proto.classID2;
- registrar.registerFactory(proto.classID2, proto.classDescription,
- proto.contractID2, factory);
- }
- },
-
- unregister: function unregister() {
- var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
- registrar.unregisterFactory(this._classID, this._factory);
- if (this._classID2) {
- registrar.unregisterFactory(this._classID2, this._factory);
- }
- this._factory = null;
- }
-};
-
-var PdfJs = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
- _registered: false,
- _initialized: false,
-
- init: function init(remote) {
- if (Services.appinfo.processType !==
- Services.appinfo.PROCESS_TYPE_DEFAULT) {
- throw new Error('PdfJs.init should only get called ' +
- 'in the parent process.');
- }
- PdfjsChromeUtils.init();
- if (!remote) {
- PdfjsContentUtils.init();
- }
- this.initPrefs();
- this.updateRegistration();
- },
-
- initPrefs: function initPrefs() {
- if (this._initialized) {
- return;
- }
- this._initialized = true;
-
- if (!getBoolPref(PREF_DISABLED, true)) {
- this._migrate();
- }
-
- // Listen for when pdf.js is completely disabled or a different pdf handler
- // is chosen.
- Services.prefs.addObserver(PREF_DISABLED, this, false);
- Services.prefs.addObserver(PREF_DISABLED_PLUGIN_TYPES, this, false);
- Services.obs.addObserver(this, TOPIC_PDFJS_HANDLER_CHANGED, false);
- Services.obs.addObserver(this, TOPIC_PLUGINS_LIST_UPDATED, false);
- Services.obs.addObserver(this, TOPIC_PLUGIN_INFO_UPDATED, false);
-
- initializeDefaultPreferences();
- },
-
- updateRegistration: function updateRegistration() {
- if (this.enabled) {
- this._ensureRegistered();
- } else {
- this._ensureUnregistered();
- }
- },
-
- uninit: function uninit() {
- if (this._initialized) {
- Services.prefs.removeObserver(PREF_DISABLED, this, false);
- Services.prefs.removeObserver(PREF_DISABLED_PLUGIN_TYPES, this, false);
- Services.obs.removeObserver(this, TOPIC_PDFJS_HANDLER_CHANGED, false);
- Services.obs.removeObserver(this, TOPIC_PLUGINS_LIST_UPDATED, false);
- Services.obs.removeObserver(this, TOPIC_PLUGIN_INFO_UPDATED, false);
- this._initialized = false;
- }
- this._ensureUnregistered();
- },
-
- _migrate: function migrate() {
- const VERSION = 2;
- var currentVersion = getIntPref(PREF_MIGRATION_VERSION, 0);
- if (currentVersion >= VERSION) {
- return;
- }
- // Make pdf.js the default pdf viewer on the first migration.
- if (currentVersion < 1) {
- this._becomeHandler();
- }
- if (currentVersion < 2) {
- // cleaning up of unused database preference (see #3994)
- Services.prefs.clearUserPref(PREF_PREFIX + '.database');
- }
- Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION);
- },
-
- _becomeHandler: function _becomeHandler() {
- let handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf');
- let prefs = Services.prefs;
- if (handlerInfo.preferredAction !== Ci.nsIHandlerInfo.handleInternally &&
- handlerInfo.preferredAction !== false) {
- // Store the previous settings of preferredAction and
- // alwaysAskBeforeHandling in case we need to revert them in a hotfix that
- // would turn pdf.js off.
- prefs.setIntPref(PREF_PREVIOUS_ACTION, handlerInfo.preferredAction);
- prefs.setBoolPref(PREF_PREVIOUS_ASK, handlerInfo.alwaysAskBeforeHandling);
- }
-
- let handlerService = Cc['@mozilla.org/uriloader/handler-service;1'].
- getService(Ci.nsIHandlerService);
-
- // Change and save mime handler settings.
- handlerInfo.alwaysAskBeforeHandling = false;
- handlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
- handlerService.store(handlerInfo);
-
- // Also disable any plugins for pdfs.
- var stringTypes = '';
- var types = [];
- if (prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
- stringTypes = prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES);
- }
- if (stringTypes !== '') {
- types = stringTypes.split(',');
- }
-
- if (types.indexOf(PDF_CONTENT_TYPE) === -1) {
- types.push(PDF_CONTENT_TYPE);
- }
- prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES, types.join(','));
-
- // Update the category manager in case the plugins are already loaded.
- let categoryManager = Cc['@mozilla.org/categorymanager;1'];
- categoryManager.getService(Ci.nsICategoryManager).
- deleteCategoryEntry('Gecko-Content-Viewers',
- PDF_CONTENT_TYPE,
- false);
- },
-
- // nsIObserver
- observe: function observe(aSubject, aTopic, aData) {
- this.updateRegistration();
- if (Services.appinfo.processType ===
- Services.appinfo.PROCESS_TYPE_DEFAULT) {
- let jsm = 'resource://pdf.js/PdfjsChromeUtils.jsm';
- let PdfjsChromeUtils = Components.utils.import(jsm, {}).PdfjsChromeUtils;
- PdfjsChromeUtils.notifyChildOfSettingsChange();
- }
- },
-
- /**
- * pdf.js is only enabled if it is both selected as the pdf viewer and if the
- * global switch enabling it is true.
- * @return {boolean} Whether or not it's enabled.
- */
- get enabled() {
- var disabled = getBoolPref(PREF_DISABLED, true);
- if (disabled) {
- return false;
- }
-
- // Check if the 'application/pdf' preview handler is configured properly.
- if (!isDefaultHandler()) {
- return false;
- }
-
- // Check if we have disabled plugin handling of 'application/pdf' in prefs
- if (Services.prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
- let disabledPluginTypes =
- Services.prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES).split(',');
- if (disabledPluginTypes.indexOf(PDF_CONTENT_TYPE) >= 0) {
- return true;
- }
- }
-
- // Check if there is an enabled pdf plugin.
- // Note: this check is performed last because getPluginTags() triggers
- // costly plugin list initialization (bug 881575)
- let tags = Cc['@mozilla.org/plugin/host;1'].
- getService(Ci.nsIPluginHost).
- getPluginTags();
- let enabledPluginFound = tags.some(function(tag) {
- if (tag.disabled) {
- return false;
- }
- let mimeTypes = tag.getMimeTypes();
- return mimeTypes.some(function(mimeType) {
- return mimeType === PDF_CONTENT_TYPE;
- });
- });
-
- // Use pdf.js if pdf plugin is not present or disabled
- return !enabledPluginFound;
- },
-
- _ensureRegistered: function _ensureRegistered() {
- if (this._registered) {
- return;
- }
- this._pdfStreamConverterFactory = new Factory();
- Cu.import('resource://pdf.js/PdfStreamConverter.jsm');
- this._pdfStreamConverterFactory.register(PdfStreamConverter);
-
- this._registered = true;
- },
-
- _ensureUnregistered: function _ensureUnregistered() {
- if (!this._registered) {
- return;
- }
- this._pdfStreamConverterFactory.unregister();
- Cu.unload('resource://pdf.js/PdfStreamConverter.jsm');
- delete this._pdfStreamConverterFactory;
-
- this._registered = false;
- }
-};
-
diff --git a/extensions/pdfjs/content/PdfJsNetwork.jsm b/extensions/pdfjs/content/PdfJsNetwork.jsm
deleted file mode 100644
index c3aefec..0000000
--- a/extensions/pdfjs/content/PdfJsNetwork.jsm
+++ /dev/null
@@ -1,257 +0,0 @@
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* globals Components, Services */
-
-'use strict';
-
-Components.utils.import('resource://gre/modules/Services.jsm');
-
-var EXPORTED_SYMBOLS = ['NetworkManager'];
-
-function log(aMsg) {
- var msg = 'network.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
- Services.console.logStringMessage(msg);
-}
-
-var NetworkManager = (function NetworkManagerClosure() {
-
- var OK_RESPONSE = 200;
- var PARTIAL_CONTENT_RESPONSE = 206;
-
- function NetworkManager(url, args) {
- this.url = url;
- args = args || {};
- this.isHttp = /^https?:/i.test(url);
- this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
- this.withCredentials = args.withCredentials || false;
- this.getXhr = args.getXhr ||
- function NetworkManager_getXhr() {
- return new XMLHttpRequest();
- };
-
- this.currXhrId = 0;
- this.pendingRequests = Object.create(null);
- this.loadedRequests = Object.create(null);
- }
-
- function getArrayBuffer(xhr) {
- var data = xhr.response;
- if (typeof data !== 'string') {
- return data;
- }
- var length = data.length;
- var array = new Uint8Array(length);
- for (var i = 0; i < length; i++) {
- array[i] = data.charCodeAt(i) & 0xFF;
- }
- return array.buffer;
- }
-
- NetworkManager.prototype = {
- requestRange: function NetworkManager_requestRange(begin, end, listeners) {
- var args = {
- begin: begin,
- end: end
- };
- for (var prop in listeners) {
- args[prop] = listeners[prop];
- }
- return this.request(args);
- },
-
- requestFull: function NetworkManager_requestFull(listeners) {
- return this.request(listeners);
- },
-
- request: function NetworkManager_request(args) {
- var xhr = this.getXhr();
- var xhrId = this.currXhrId++;
- var pendingRequest = this.pendingRequests[xhrId] = {
- xhr: xhr
- };
-
- xhr.open('GET', this.url);
- xhr.withCredentials = this.withCredentials;
- for (var property in this.httpHeaders) {
- var value = this.httpHeaders[property];
- if (typeof value === 'undefined') {
- continue;
- }
- xhr.setRequestHeader(property, value);
- }
- if (this.isHttp && 'begin' in args && 'end' in args) {
- var rangeStr = args.begin + '-' + (args.end - 1);
- xhr.setRequestHeader('Range', 'bytes=' + rangeStr);
- pendingRequest.expectedStatus = 206;
- } else {
- pendingRequest.expectedStatus = 200;
- }
-
- var useMozChunkedLoading = !!args.onProgressiveData;
- if (useMozChunkedLoading) {
- xhr.responseType = 'moz-chunked-arraybuffer';
- pendingRequest.onProgressiveData = args.onProgressiveData;
- pendingRequest.mozChunked = true;
- } else {
- xhr.responseType = 'arraybuffer';
- }
-
- if (args.onError) {
- xhr.onerror = function(evt) {
- args.onError(xhr.status);
- };
- }
- xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
- xhr.onprogress = this.onProgress.bind(this, xhrId);
-
- pendingRequest.onHeadersReceived = args.onHeadersReceived;
- pendingRequest.onDone = args.onDone;
- pendingRequest.onError = args.onError;
- pendingRequest.onProgress = args.onProgress;
-
- xhr.send(null);
-
- return xhrId;
- },
-
- onProgress: function NetworkManager_onProgress(xhrId, evt) {
- var pendingRequest = this.pendingRequests[xhrId];
- if (!pendingRequest) {
- // Maybe abortRequest was called...
- return;
- }
-
- if (pendingRequest.mozChunked) {
- var chunk = getArrayBuffer(pendingRequest.xhr);
- pendingRequest.onProgressiveData(chunk);
- }
-
- var onProgress = pendingRequest.onProgress;
- if (onProgress) {
- onProgress(evt);
- }
- },
-
- onStateChange: function NetworkManager_onStateChange(xhrId, evt) {
- var pendingRequest = this.pendingRequests[xhrId];
- if (!pendingRequest) {
- // Maybe abortRequest was called...
- return;
- }
-
- var xhr = pendingRequest.xhr;
- if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
- pendingRequest.onHeadersReceived();
- delete pendingRequest.onHeadersReceived;
- }
-
- if (xhr.readyState !== 4) {
- return;
- }
-
- if (!(xhrId in this.pendingRequests)) {
- // The XHR request might have been aborted in onHeadersReceived()
- // callback, in which case we should abort request
- return;
- }
-
- delete this.pendingRequests[xhrId];
-
- // success status == 0 can be on ftp, file and other protocols
- if (xhr.status === 0 && this.isHttp) {
- if (pendingRequest.onError) {
- pendingRequest.onError(xhr.status);
- }
- return;
- }
- var xhrStatus = xhr.status || OK_RESPONSE;
-
- // From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2:
- // "A server MAY ignore the Range header". This means it's possible to
- // get a 200 rather than a 206 response from a range request.
- var ok_response_on_range_request =
- xhrStatus === OK_RESPONSE &&
- pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
-
- if (!ok_response_on_range_request &&
- xhrStatus !== pendingRequest.expectedStatus) {
- if (pendingRequest.onError) {
- pendingRequest.onError(xhr.status);
- }
- return;
- }
-
- this.loadedRequests[xhrId] = true;
-
- var chunk = getArrayBuffer(xhr);
- if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
- var rangeHeader = xhr.getResponseHeader('Content-Range');
- var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
- var begin = parseInt(matches[1], 10);
- pendingRequest.onDone({
- begin: begin,
- chunk: chunk
- });
- } else if (pendingRequest.onProgressiveData) {
- pendingRequest.onDone(null);
- } else if (chunk) {
- pendingRequest.onDone({
- begin: 0,
- chunk: chunk
- });
- } else if (pendingRequest.onError) {
- pendingRequest.onError(xhr.status);
- }
- },
-
- hasPendingRequests: function NetworkManager_hasPendingRequests() {
- for (var xhrId in this.pendingRequests) {
- return true;
- }
- return false;
- },
-
- getRequestXhr: function NetworkManager_getXhr(xhrId) {
- return this.pendingRequests[xhrId].xhr;
- },
-
- isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) {
- return !!(this.pendingRequests[xhrId].onProgressiveData);
- },
-
- isPendingRequest: function NetworkManager_isPendingRequest(xhrId) {
- return xhrId in this.pendingRequests;
- },
-
- isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) {
- return xhrId in this.loadedRequests;
- },
-
- abortAllRequests: function NetworkManager_abortAllRequests() {
- for (var xhrId in this.pendingRequests) {
- this.abortRequest(xhrId | 0);
- }
- },
-
- abortRequest: function NetworkManager_abortRequest(xhrId) {
- var xhr = this.pendingRequests[xhrId].xhr;
- delete this.pendingRequests[xhrId];
- xhr.abort();
- }
- };
-
- return NetworkManager;
-})();
-
diff --git a/extensions/pdfjs/content/PdfJsTelemetry.jsm b/extensions/pdfjs/content/PdfJsTelemetry.jsm
deleted file mode 100644
index 275da9d..0000000
--- a/extensions/pdfjs/content/PdfJsTelemetry.jsm
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright 2013 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* jshint esnext:true, maxlen: 100 */
-/* globals Components, Services */
-
-'use strict';
-
-this.EXPORTED_SYMBOLS = ['PdfJsTelemetry'];
-
-const Cu = Components.utils;
-Cu.import('resource://gre/modules/Services.jsm');
-
-this.PdfJsTelemetry = {
- onViewerIsUsed: function () {
- let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_USED');
- histogram.add(true);
- },
- onFallback: function () {
- let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FALLBACK_SHOWN');
- histogram.add(true);
- },
- onDocumentSize: function (size) {
- let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_SIZE_KB');
- histogram.add(size / 1024);
- },
- onDocumentVersion: function (versionId) {
- let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_VERSION');
- histogram.add(versionId);
- },
- onDocumentGenerator: function (generatorId) {
- let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_GENERATOR');
- histogram.add(generatorId);
- },
- onEmbed: function (isObject) {
- let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_EMBED');
- histogram.add(isObject);
- },
- onFontType: function (fontTypeId) {
- let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FONT_TYPES');
- histogram.add(fontTypeId);
- },
- onForm: function (isAcroform) {
- let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FORM');
- histogram.add(isAcroform);
- },
- onPrint: function () {
- let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_PRINT');
- histogram.add(true);
- },
- onStreamType: function (streamTypeId) {
- let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_STREAM_TYPES');
- histogram.add(streamTypeId);
- },
- onTimeToView: function (ms) {
- let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_TIME_TO_VIEW_MS');
- histogram.add(ms);
- }
-};
diff --git a/extensions/pdfjs/content/PdfStreamConverter.jsm b/extensions/pdfjs/content/PdfStreamConverter.jsm
deleted file mode 100644
index 5e337bb..0000000
--- a/extensions/pdfjs/content/PdfStreamConverter.jsm
+++ /dev/null
@@ -1,1054 +0,0 @@
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* jshint esnext:true */
-/* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
- dump, NetworkManager, PdfJsTelemetry, PdfjsContentUtils */
-
-'use strict';
-
-var EXPORTED_SYMBOLS = ['PdfStreamConverter'];
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-const Cu = Components.utils;
-// True only if this is the version of pdf.js that is included with firefox.
-const MOZ_CENTRAL = JSON.parse('true');
-const PDFJS_EVENT_ID = 'pdf.js.message';
-const PDF_CONTENT_TYPE = 'application/pdf';
-const PREF_PREFIX = 'pdfjs';
-const PDF_VIEWER_ORIGIN = "resource://pdf.js";
-const PDF_VIEWER_WEB_PAGE = "resource://pdf.js/web/viewer.html";
-const MAX_NUMBER_OF_PREFS = 50;
-const MAX_STRING_PREF_LENGTH = 128;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://gre/modules/NetUtil.jsm');
-
-XPCOMUtils.defineLazyModuleGetter(this, 'NetworkManager',
- 'resource://pdf.js/PdfJsNetwork.jsm');
-
-XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils',
- 'resource://gre/modules/PrivateBrowsingUtils.jsm');
-
-XPCOMUtils.defineLazyModuleGetter(this, 'PdfJsTelemetry',
- 'resource://pdf.js/PdfJsTelemetry.jsm');
-
-XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsContentUtils',
- 'resource://pdf.js/PdfjsContentUtils.jsm');
-
-var Svc = {};
-XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
- '@mozilla.org/mime;1',
- 'nsIMIMEService');
-
-function getContainingBrowser(domWindow) {
- return domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell)
- .chromeEventHandler;
-}
-
-function getFindBar(domWindow) {
- if (PdfjsContentUtils.isRemote) {
- throw new Error('FindBar is not accessible from the content process.');
- }
- try {
- var browser = getContainingBrowser(domWindow);
- var tabbrowser = browser.getTabBrowser();
- var tab = tabbrowser.getTabForBrowser(browser);
- return tabbrowser.getFindBar(tab);
- } catch (e) {
- // Suppress errors for PDF files opened in the bookmark sidebar, see
- // https://bugzilla.mozilla.org/show_bug.cgi?id=1248959.
- return null;
- }
-}
-
-function getBoolPref(pref, def) {
- try {
- return Services.prefs.getBoolPref(pref);
- } catch (ex) {
- return def;
- }
-}
-
-function getIntPref(pref, def) {
- try {
- return Services.prefs.getIntPref(pref);
- } catch (ex) {
- return def;
- }
-}
-
-function getStringPref(pref, def) {
- try {
- return Services.prefs.getComplexValue(pref, Ci.nsISupportsString).data;
- } catch (ex) {
- return def;
- }
-}
-
-function log(aMsg) {
- if (!getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false)) {
- return;
- }
- var msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
- Services.console.logStringMessage(msg);
- dump(msg + '\n');
-}
-
-function getDOMWindow(aChannel, aPrincipal) {
- var requestor = aChannel.notificationCallbacks ?
- aChannel.notificationCallbacks :
- aChannel.loadGroup.notificationCallbacks;
- var win = requestor.getInterface(Components.interfaces.nsIDOMWindow);
- // Ensure the window wasn't navigated to something that is not PDF.js.
- if (!win.document.nodePrincipal.equals(aPrincipal)) {
- return null;
- }
- return win;
-}
-
-function getLocalizedStrings(path) {
- var stringBundle = Cc['@mozilla.org/intl/stringbundle;1'].
- getService(Ci.nsIStringBundleService).
- createBundle('chrome://pdf.js/locale/' + path);
-
- var map = {};
- var enumerator = stringBundle.getSimpleEnumeration();
- while (enumerator.hasMoreElements()) {
- var string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
- var key = string.key, property = 'textContent';
- var i = key.lastIndexOf('.');
- if (i >= 0) {
- property = key.substring(i + 1);
- key = key.substring(0, i);
- }
- if (!(key in map)) {
- map[key] = {};
- }
- map[key][property] = string.value;
- }
- return map;
-}
-function getLocalizedString(strings, id, property) {
- property = property || 'textContent';
- if (id in strings) {
- return strings[id][property];
- }
- return id;
-}
-
-function createNewChannel(uri, node) {
- return NetUtil.newChannel({
- uri: uri,
- loadUsingSystemPrincipal: true,
- });
-}
-
-function asyncOpenChannel(channel, listener, context) {
- return channel.asyncOpen2(listener);
-}
-
-function asyncFetchChannel(channel, callback) {
- return NetUtil.asyncFetch(channel, callback);
-}
-
-// PDF data storage
-function PdfDataListener(length) {
- this.length = length; // less than 0, if length is unknown
- this.buffer = null;
- this.loaded = 0;
-}
-
-PdfDataListener.prototype = {
- append: function PdfDataListener_append(chunk) {
- // In most of the cases we will pass data as we receive it, but at the
- // beginning of the loading we may accumulate some data.
- if (!this.buffer) {
- this.buffer = new Uint8Array(chunk);
- } else {
- var buffer = this.buffer;
- var newBuffer = new Uint8Array(buffer.length + chunk.length);
- newBuffer.set(buffer);
- newBuffer.set(chunk, buffer.length);
- this.buffer = newBuffer;
- }
- this.loaded += chunk.length;
- if (this.length >= 0 && this.length < this.loaded) {
- this.length = -1; // reset the length, server is giving incorrect one
- }
- this.onprogress(this.loaded, this.length >= 0 ? this.length : void(0));
- },
- readData: function PdfDataListener_readData() {
- var result = this.buffer;
- this.buffer = null;
- return result;
- },
- finish: function PdfDataListener_finish() {
- this.isDataReady = true;
- if (this.oncompleteCallback) {
- this.oncompleteCallback(this.readData());
- }
- },
- error: function PdfDataListener_error(errorCode) {
- this.errorCode = errorCode;
- if (this.oncompleteCallback) {
- this.oncompleteCallback(null, errorCode);
- }
- },
- onprogress: function() {},
- get oncomplete() {
- return this.oncompleteCallback;
- },
- set oncomplete(value) {
- this.oncompleteCallback = value;
- if (this.isDataReady) {
- value(this.readData());
- }
- if (this.errorCode) {
- value(null, this.errorCode);
- }
- }
-};
-
-// All the priviledged actions.
-function ChromeActions(domWindow, contentDispositionFilename) {
- this.domWindow = domWindow;
- this.contentDispositionFilename = contentDispositionFilename;
- this.telemetryState = {
- documentInfo: false,
- firstPageInfo: false,
- streamTypesUsed: [],
- fontTypesUsed: [],
- startAt: Date.now()
- };
-}
-
-ChromeActions.prototype = {
- isInPrivateBrowsing: function() {
- return PrivateBrowsingUtils.isContentWindowPrivate(this.domWindow);
- },
- download: function(data, sendResponse) {
- var self = this;
- var originalUrl = data.originalUrl;
- var blobUrl = data.blobUrl || originalUrl;
- // The data may not be downloaded so we need just retry getting the pdf with
- // the original url.
- var originalUri = NetUtil.newURI(originalUrl);
- var filename = data.filename;
- if (typeof filename !== 'string' ||
- (!/\.pdf$/i.test(filename) && !data.isAttachment)) {
- filename = 'document.pdf';
- }
- var blobUri = NetUtil.newURI(blobUrl);
- var extHelperAppSvc =
- Cc['@mozilla.org/uriloader/external-helper-app-service;1'].
- getService(Ci.nsIExternalHelperAppService);
-
- var docIsPrivate = this.isInPrivateBrowsing();
- var netChannel = createNewChannel(blobUri, this.domWindow.document);
- if ('nsIPrivateBrowsingChannel' in Ci &&
- netChannel instanceof Ci.nsIPrivateBrowsingChannel) {
- netChannel.setPrivate(docIsPrivate);
- }
- asyncFetchChannel(netChannel, function(aInputStream, aResult) {
- if (!Components.isSuccessCode(aResult)) {
- if (sendResponse) {
- sendResponse(true);
- }
- return;
- }
- // Create a nsIInputStreamChannel so we can set the url on the channel
- // so the filename will be correct.
- var channel = Cc['@mozilla.org/network/input-stream-channel;1'].
- createInstance(Ci.nsIInputStreamChannel);
- channel.QueryInterface(Ci.nsIChannel);
- try {
- // contentDisposition/contentDispositionFilename is readonly before FF18
- channel.contentDisposition = Ci.nsIChannel.DISPOSITION_ATTACHMENT;
- if (self.contentDispositionFilename && !data.isAttachment) {
- channel.contentDispositionFilename = self.contentDispositionFilename;
- } else {
- channel.contentDispositionFilename = filename;
- }
- } catch (e) {}
- channel.setURI(originalUri);
- channel.loadInfo = netChannel.loadInfo;
- channel.contentStream = aInputStream;
- if ('nsIPrivateBrowsingChannel' in Ci &&
- channel instanceof Ci.nsIPrivateBrowsingChannel) {
- channel.setPrivate(docIsPrivate);
- }
-
- var listener = {
- extListener: null,
- onStartRequest: function(aRequest, aContext) {
- var loadContext = self.domWindow
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsILoadContext);
- this.extListener = extHelperAppSvc.doContent(
- (data.isAttachment ? 'application/octet-stream' :
- 'application/pdf'),
- aRequest, loadContext, false);
- this.extListener.onStartRequest(aRequest, aContext);
- },
- onStopRequest: function(aRequest, aContext, aStatusCode) {
- if (this.extListener) {
- this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
- }
- // Notify the content code we're done downloading.
- if (sendResponse) {
- sendResponse(false);
- }
- },
- onDataAvailable: function(aRequest, aContext, aInputStream, aOffset,
- aCount) {
- this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
- aOffset, aCount);
- }
- };
-
- asyncOpenChannel(channel, listener, null);
- });
- },
- getLocale: function() {
- return getStringPref('general.useragent.locale', 'en-US');
- },
- getStrings: function(data) {
- try {
- // Lazy initialization of localizedStrings
- if (!('localizedStrings' in this)) {
- this.localizedStrings = getLocalizedStrings('viewer.properties');
- }
- var result = this.localizedStrings[data];
- return JSON.stringify(result || null);
- } catch (e) {
- log('Unable to retrieve localized strings: ' + e);
- return 'null';
- }
- },
- supportsIntegratedFind: function() {
- // Integrated find is only supported when we're not in a frame
- if (this.domWindow.frameElement !== null) {
- return false;
- }
-
- // ... and we are in a child process
- if (PdfjsContentUtils.isRemote) {
- return true;
- }
-
- // ... or when the new find events code exists.
- var findBar = getFindBar(this.domWindow);
- return !!findBar && ('updateControlState' in findBar);
- },
- supportsDocumentFonts: function() {
- var prefBrowser = getIntPref('browser.display.use_document_fonts', 1);
- var prefGfx = getBoolPref('gfx.downloadable_fonts.enabled', true);
- return (!!prefBrowser && prefGfx);
- },
- supportsDocumentColors: function() {
- return getIntPref('browser.display.document_color_use', 0) !== 2;
- },
- supportedMouseWheelZoomModifierKeys: function() {
- return {
- ctrlKey: getIntPref('mousewheel.with_control.action', 3) === 3,
- metaKey: getIntPref('mousewheel.with_meta.action', 1) === 3,
- };
- },
- reportTelemetry: function (data) {
- var probeInfo = JSON.parse(data);
- switch (probeInfo.type) {
- case 'documentInfo':
- if (!this.telemetryState.documentInfo) {
- PdfJsTelemetry.onDocumentVersion(probeInfo.version | 0);
- PdfJsTelemetry.onDocumentGenerator(probeInfo.generator | 0);
- if (probeInfo.formType) {
- PdfJsTelemetry.onForm(probeInfo.formType === 'acroform');
- }
- this.telemetryState.documentInfo = true;
- }
- break;
- case 'pageInfo':
- if (!this.telemetryState.firstPageInfo) {
- var duration = Date.now() - this.telemetryState.startAt;
- PdfJsTelemetry.onTimeToView(duration);
- this.telemetryState.firstPageInfo = true;
- }
- break;
- case 'documentStats':
- // documentStats can be called several times for one documents.
- // if stream/font types are reported, trying not to submit the same
- // enumeration value multiple times.
- var documentStats = probeInfo.stats;
- if (!documentStats || typeof documentStats !== 'object') {
- break;
- }
- var i, streamTypes = documentStats.streamTypes;
- if (Array.isArray(streamTypes)) {
- var STREAM_TYPE_ID_LIMIT = 20;
- for (i = 0; i < STREAM_TYPE_ID_LIMIT; i++) {
- if (streamTypes[i] &&
- !this.telemetryState.streamTypesUsed[i]) {
- PdfJsTelemetry.onStreamType(i);
- this.telemetryState.streamTypesUsed[i] = true;
- }
- }
- }
- var fontTypes = documentStats.fontTypes;
- if (Array.isArray(fontTypes)) {
- var FONT_TYPE_ID_LIMIT = 20;
- for (i = 0; i < FONT_TYPE_ID_LIMIT; i++) {
- if (fontTypes[i] &&
- !this.telemetryState.fontTypesUsed[i]) {
- PdfJsTelemetry.onFontType(i);
- this.telemetryState.fontTypesUsed[i] = true;
- }
- }
- }
- break;
- case 'print':
- PdfJsTelemetry.onPrint();
- break;
- }
- },
- fallback: function(args, sendResponse) {
- var featureId = args.featureId;
- var url = args.url;
-
- var self = this;
- var domWindow = this.domWindow;
- var strings = getLocalizedStrings('chrome.properties');
- var message;
- if (featureId === 'forms') {
- message = getLocalizedString(strings, 'unsupported_feature_forms');
- } else {
- message = getLocalizedString(strings, 'unsupported_feature');
- }
- PdfJsTelemetry.onFallback();
- PdfjsContentUtils.displayWarning(domWindow, message,
- getLocalizedString(strings, 'open_with_different_viewer'),
- getLocalizedString(strings, 'open_with_different_viewer', 'accessKey'));
-
- let winmm = domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDocShell)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIContentFrameMessageManager);
-
- winmm.addMessageListener('PDFJS:Child:fallbackDownload',
- function fallbackDownload(msg) {
- let data = msg.data;
- sendResponse(data.download);
-
- winmm.removeMessageListener('PDFJS:Child:fallbackDownload',
- fallbackDownload);
- });
- },
- updateFindControlState: function(data) {
- if (!this.supportsIntegratedFind()) {
- return;
- }
- // Verify what we're sending to the findbar.
- var result = data.result;
- var findPrevious = data.findPrevious;
- var findPreviousType = typeof findPrevious;
- if ((typeof result !== 'number' || result < 0 || result > 3) ||
- (findPreviousType !== 'undefined' && findPreviousType !== 'boolean')) {
- return;
- }
-
- var winmm = this.domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDocShell)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIContentFrameMessageManager);
-
- winmm.sendAsyncMessage('PDFJS:Parent:updateControlState', data);
- },
- setPreferences: function(prefs, sendResponse) {
- var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
- var numberOfPrefs = 0;
- var prefValue, prefName;
- for (var key in prefs) {
- if (++numberOfPrefs > MAX_NUMBER_OF_PREFS) {
- log('setPreferences - Exceeded the maximum number of preferences ' +
- 'that is allowed to be set at once.');
- break;
- } else if (!defaultBranch.getPrefType(key)) {
- continue;
- }
- prefValue = prefs[key];
- prefName = (PREF_PREFIX + '.' + key);
- switch (typeof prefValue) {
- case 'boolean':
- PdfjsContentUtils.setBoolPref(prefName, prefValue);
- break;
- case 'number':
- PdfjsContentUtils.setIntPref(prefName, prefValue);
- break;
- case 'string':
- if (prefValue.length > MAX_STRING_PREF_LENGTH) {
- log('setPreferences - Exceeded the maximum allowed length ' +
- 'for a string preference.');
- } else {
- PdfjsContentUtils.setStringPref(prefName, prefValue);
- }
- break;
- }
- }
- if (sendResponse) {
- sendResponse(true);
- }
- },
- getPreferences: function(prefs, sendResponse) {
- var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
- var currentPrefs = {}, numberOfPrefs = 0;
- var prefValue, prefName;
- for (var key in prefs) {
- if (++numberOfPrefs > MAX_NUMBER_OF_PREFS) {
- log('getPreferences - Exceeded the maximum number of preferences ' +
- 'that is allowed to be fetched at once.');
- break;
- } else if (!defaultBranch.getPrefType(key)) {
- continue;
- }
- prefValue = prefs[key];
- prefName = (PREF_PREFIX + '.' + key);
- switch (typeof prefValue) {
- case 'boolean':
- currentPrefs[key] = getBoolPref(prefName, prefValue);
- break;
- case 'number':
- currentPrefs[key] = getIntPref(prefName, prefValue);
- break;
- case 'string':
- currentPrefs[key] = getStringPref(prefName, prefValue);
- break;
- }
- }
- if (sendResponse) {
- sendResponse(JSON.stringify(currentPrefs));
- } else {
- return JSON.stringify(currentPrefs);
- }
- }
-};
-
-var RangedChromeActions = (function RangedChromeActionsClosure() {
- /**
- * This is for range requests
- */
- function RangedChromeActions(
- domWindow, contentDispositionFilename, originalRequest,
- rangeEnabled, streamingEnabled, dataListener) {
-
- ChromeActions.call(this, domWindow, contentDispositionFilename);
- this.dataListener = dataListener;
- this.originalRequest = originalRequest;
- this.rangeEnabled = rangeEnabled;
- this.streamingEnabled = streamingEnabled;
-
- this.pdfUrl = originalRequest.URI.spec;
- this.contentLength = originalRequest.contentLength;
-
- // Pass all the headers from the original request through
- var httpHeaderVisitor = {
- headers: {},
- visitHeader: function(aHeader, aValue) {
- if (aHeader === 'Range') {
- // When loading the PDF from cache, firefox seems to set the Range
- // request header to fetch only the unfetched portions of the file
- // (e.g. 'Range: bytes=1024-'). However, we want to set this header
- // manually to fetch the PDF in chunks.
- return;
- }
- this.headers[aHeader] = aValue;
- }
- };
- if (originalRequest.visitRequestHeaders) {
- originalRequest.visitRequestHeaders(httpHeaderVisitor);
- }
-
- var self = this;
- var xhr_onreadystatechange = function xhr_onreadystatechange() {
- if (this.readyState === 1) { // LOADING
- var netChannel = this.channel;
- if ('nsIPrivateBrowsingChannel' in Ci &&
- netChannel instanceof Ci.nsIPrivateBrowsingChannel) {
- var docIsPrivate = self.isInPrivateBrowsing();
- netChannel.setPrivate(docIsPrivate);
- }
- }
- };
- var getXhr = function getXhr() {
- const XMLHttpRequest = Components.Constructor(
- '@mozilla.org/xmlextras/xmlhttprequest;1');
- var xhr = new XMLHttpRequest();
- xhr.addEventListener('readystatechange', xhr_onreadystatechange);
- return xhr;
- };
-
- this.networkManager = new NetworkManager(this.pdfUrl, {
- httpHeaders: httpHeaderVisitor.headers,
- getXhr: getXhr
- });
-
- // If we are in range request mode, this means we manually issued xhr
- // requests, which we need to abort when we leave the page
- domWindow.addEventListener('unload', function unload(e) {
- domWindow.removeEventListener(e.type, unload);
- self.abortLoading();
- });
- }
-
- RangedChromeActions.prototype = Object.create(ChromeActions.prototype);
- var proto = RangedChromeActions.prototype;
- proto.constructor = RangedChromeActions;
-
- proto.initPassiveLoading = function RangedChromeActions_initPassiveLoading() {
- var self = this;
- var data;
- if (!this.streamingEnabled) {
- this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
- this.originalRequest = null;
- data = this.dataListener.readData();
- this.dataListener = null;
- } else {
- data = this.dataListener.readData();
-
- this.dataListener.onprogress = function (loaded, total) {
- self.domWindow.postMessage({
- pdfjsLoadAction: 'progressiveRead',
- loaded: loaded,
- total: total,
- chunk: self.dataListener.readData()
- }, PDF_VIEWER_ORIGIN);
- };
- this.dataListener.oncomplete = function () {
- self.dataListener = null;
- };
- }
-
- this.domWindow.postMessage({
- pdfjsLoadAction: 'supportsRangedLoading',
- rangeEnabled: this.rangeEnabled,
- streamingEnabled: this.streamingEnabled,
- pdfUrl: this.pdfUrl,
- length: this.contentLength,
- data: data
- }, PDF_VIEWER_ORIGIN);
-
- return true;
- };
-
- proto.requestDataRange = function RangedChromeActions_requestDataRange(args) {
- if (!this.rangeEnabled) {
- return;
- }
-
- var begin = args.begin;
- var end = args.end;
- var domWindow = this.domWindow;
- // TODO(mack): Support error handler. We're not currently not handling
- // errors from chrome code for non-range requests, so this doesn't
- // seem high-pri
- this.networkManager.requestRange(begin, end, {
- onDone: function RangedChromeActions_onDone(args) {
- domWindow.postMessage({
- pdfjsLoadAction: 'range',
- begin: args.begin,
- chunk: args.chunk
- }, PDF_VIEWER_ORIGIN);
- },
- onProgress: function RangedChromeActions_onProgress(evt) {
- domWindow.postMessage({
- pdfjsLoadAction: 'rangeProgress',
- loaded: evt.loaded,
- }, PDF_VIEWER_ORIGIN);
- }
- });
- };
-
- proto.abortLoading = function RangedChromeActions_abortLoading() {
- this.networkManager.abortAllRequests();
- if (this.originalRequest) {
- this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
- this.originalRequest = null;
- }
- this.dataListener = null;
- };
-
- return RangedChromeActions;
-})();
-
-var StandardChromeActions = (function StandardChromeActionsClosure() {
-
- /**
- * This is for a single network stream
- */
- function StandardChromeActions(domWindow, contentDispositionFilename,
- originalRequest, dataListener) {
-
- ChromeActions.call(this, domWindow, contentDispositionFilename);
- this.originalRequest = originalRequest;
- this.dataListener = dataListener;
- }
-
- StandardChromeActions.prototype = Object.create(ChromeActions.prototype);
- var proto = StandardChromeActions.prototype;
- proto.constructor = StandardChromeActions;
-
- proto.initPassiveLoading =
- function StandardChromeActions_initPassiveLoading() {
-
- if (!this.dataListener) {
- return false;
- }
-
- var self = this;
-
- this.dataListener.onprogress = function ChromeActions_dataListenerProgress(
- loaded, total) {
- self.domWindow.postMessage({
- pdfjsLoadAction: 'progress',
- loaded: loaded,
- total: total
- }, PDF_VIEWER_ORIGIN);
- };
-
- this.dataListener.oncomplete =
- function StandardChromeActions_dataListenerComplete(data, errorCode) {
- self.domWindow.postMessage({
- pdfjsLoadAction: 'complete',
- data: data,
- errorCode: errorCode
- }, PDF_VIEWER_ORIGIN);
-
- self.dataListener = null;
- self.originalRequest = null;
- };
-
- return true;
- };
-
- proto.abortLoading = function StandardChromeActions_abortLoading() {
- if (this.originalRequest) {
- this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
- this.originalRequest = null;
- }
- this.dataListener = null;
- };
-
- return StandardChromeActions;
-})();
-
-// Event listener to trigger chrome privileged code.
-function RequestListener(actions) {
- this.actions = actions;
-}
-// Receive an event and synchronously or asynchronously responds.
-RequestListener.prototype.receive = function(event) {
- var message = event.target;
- var doc = message.ownerDocument;
- var action = event.detail.action;
- var data = event.detail.data;
- var sync = event.detail.sync;
- var actions = this.actions;
- if (!(action in actions)) {
- log('Unknown action: ' + action);
- return;
- }
- var response;
- if (sync) {
- response = actions[action].call(this.actions, data);
- event.detail.response = Cu.cloneInto(response, doc.defaultView);
- } else {
- if (!event.detail.responseExpected) {
- doc.documentElement.removeChild(message);
- response = null;
- } else {
- response = function sendResponse(response) {
- try {
- var listener = doc.createEvent('CustomEvent');
- let detail = Cu.cloneInto({ response: response }, doc.defaultView);
- listener.initCustomEvent('pdf.js.response', true, false, detail);
- return message.dispatchEvent(listener);
- } catch (e) {
- // doc is no longer accessible because the requestor is already
- // gone. unloaded content cannot receive the response anyway.
- return false;
- }
- };
- }
- actions[action].call(this.actions, data, response);
- }
-};
-
-// Forwards events from the eventElement to the contentWindow only if the
-// content window matches the currently selected browser window.
-function FindEventManager(contentWindow) {
- this.contentWindow = contentWindow;
- this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDocShell)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIContentFrameMessageManager);
-}
-
-FindEventManager.prototype.bind = function() {
- var unload = function(e) {
- this.unbind();
- this.contentWindow.removeEventListener(e.type, unload);
- }.bind(this);
- this.contentWindow.addEventListener('unload', unload);
-
- // We cannot directly attach listeners to for the find events
- // since the FindBar is in the parent process. Instead we're
- // asking the PdfjsChromeUtils to do it for us and forward
- // all the find events to us.
- this.winmm.sendAsyncMessage('PDFJS:Parent:addEventListener');
- this.winmm.addMessageListener('PDFJS:Child:handleEvent', this);
-};
-
-FindEventManager.prototype.receiveMessage = function(msg) {
- var detail = msg.data.detail;
- var type = msg.data.type;
- var contentWindow = this.contentWindow;
-
- detail = Cu.cloneInto(detail, contentWindow);
- var forward = contentWindow.document.createEvent('CustomEvent');
- forward.initCustomEvent(type, true, true, detail);
- contentWindow.dispatchEvent(forward);
-};
-
-FindEventManager.prototype.unbind = function() {
- this.winmm.sendAsyncMessage('PDFJS:Parent:removeEventListener');
-};
-
-function PdfStreamConverter() {
-}
-
-PdfStreamConverter.prototype = {
-
- // properties required for XPCOM registration:
- classID: Components.ID('{d0c5195d-e798-49d4-b1d3-9324328b2291}'),
- classDescription: 'pdf.js Component',
- contractID: '@mozilla.org/streamconv;1?from=application/pdf&to=*/*',
-
- classID2: Components.ID('{d0c5195d-e798-49d4-b1d3-9324328b2292}'),
- contractID2: '@mozilla.org/streamconv;1?from=application/pdf&to=text/html',
-
- QueryInterface: XPCOMUtils.generateQI([
- Ci.nsISupports,
- Ci.nsIStreamConverter,
- Ci.nsIStreamListener,
- Ci.nsIRequestObserver
- ]),
-
- /*
- * This component works as such:
- * 1. asyncConvertData stores the listener
- * 2. onStartRequest creates a new channel, streams the viewer
- * 3. If range requests are supported:
- * 3.1. Leave the request open until the viewer is ready to switch to
- * range requests.
- *
- * If range rquests are not supported:
- * 3.1. Read the stream as it's loaded in onDataAvailable to send
- * to the viewer
- *
- * The convert function just returns the stream, it's just the synchronous
- * version of asyncConvertData.
- */
-
- // nsIStreamConverter::convert
- convert: function(aFromStream, aFromType, aToType, aCtxt) {
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
- },
-
- // nsIStreamConverter::asyncConvertData
- asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
- // Store the listener passed to us
- this.listener = aListener;
- },
-
- // nsIStreamListener::onDataAvailable
- onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
- if (!this.dataListener) {
- return;
- }
-
- var binaryStream = this.binaryStream;
- binaryStream.setInputStream(aInputStream);
- var chunk = binaryStream.readByteArray(aCount);
- this.dataListener.append(chunk);
- },
-
- // nsIRequestObserver::onStartRequest
- onStartRequest: function(aRequest, aContext) {
- // Setup the request so we can use it below.
- var isHttpRequest = false;
- try {
- aRequest.QueryInterface(Ci.nsIHttpChannel);
- isHttpRequest = true;
- } catch (e) {}
-
- var rangeRequest = false;
- var streamRequest = false;
- if (isHttpRequest) {
- var contentEncoding = 'identity';
- try {
- contentEncoding = aRequest.getResponseHeader('Content-Encoding');
- } catch (e) {}
-
- var acceptRanges;
- try {
- acceptRanges = aRequest.getResponseHeader('Accept-Ranges');
- } catch (e) {}
-
- var hash = aRequest.URI.ref;
- var isPDFBugEnabled = getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false);
- rangeRequest = contentEncoding === 'identity' &&
- acceptRanges === 'bytes' &&
- aRequest.contentLength >= 0 &&
- !getBoolPref(PREF_PREFIX + '.disableRange', false) &&
- (!isPDFBugEnabled ||
- hash.toLowerCase().indexOf('disablerange=true') < 0);
- streamRequest = contentEncoding === 'identity' &&
- aRequest.contentLength >= 0 &&
- !getBoolPref(PREF_PREFIX + '.disableStream', false) &&
- (!isPDFBugEnabled ||
- hash.toLowerCase().indexOf('disablestream=true') < 0);
- }
-
- aRequest.QueryInterface(Ci.nsIChannel);
-
- aRequest.QueryInterface(Ci.nsIWritablePropertyBag);
-
- var contentDispositionFilename;
- try {
- contentDispositionFilename = aRequest.contentDispositionFilename;
- } catch (e) {}
-
- // Change the content type so we don't get stuck in a loop.
- aRequest.setProperty('contentType', aRequest.contentType);
- aRequest.contentType = 'text/html';
- if (isHttpRequest) {
- // We trust PDF viewer, using no CSP
- aRequest.setResponseHeader('Content-Security-Policy', '', false);
- aRequest.setResponseHeader('Content-Security-Policy-Report-Only', '',
- false);
- // The viewer does not need to handle HTTP Refresh header.
- aRequest.setResponseHeader('Refresh', '', false);
- }
-
- PdfJsTelemetry.onViewerIsUsed();
- PdfJsTelemetry.onDocumentSize(aRequest.contentLength);
-
- // Creating storage for PDF data
- var contentLength = aRequest.contentLength;
- this.dataListener = new PdfDataListener(contentLength);
- this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
- .createInstance(Ci.nsIBinaryInputStream);
-
- // Create a new channel that is viewer loaded as a resource.
- var channel = createNewChannel(PDF_VIEWER_WEB_PAGE, null);
-
- var listener = this.listener;
- var dataListener = this.dataListener;
- // Proxy all the request observer calls, when it gets to onStopRequest
- // we can get the dom window. We also intentionally pass on the original
- // request(aRequest) below so we don't overwrite the original channel and
- // trigger an assertion.
- var proxy = {
- onStartRequest: function(request, context) {
- listener.onStartRequest(aRequest, aContext);
- },
- onDataAvailable: function(request, context, inputStream, offset, count) {
- listener.onDataAvailable(aRequest, aContext, inputStream,
- offset, count);
- },
- onStopRequest(request, context, statusCode) {
- var domWindow = getDOMWindow(channel, resourcePrincipal);
- if (!Components.isSuccessCode(statusCode) || !domWindow) {
- // The request may have been aborted and the document may have been
- // replaced with something that is not PDF.js, abort attaching.
- listener.onStopRequest(aRequest, context, statusCode);
- return;
- }
- var actions;
- if (rangeRequest || streamRequest) {
- actions = new RangedChromeActions(
- domWindow, contentDispositionFilename, aRequest,
- rangeRequest, streamRequest, dataListener);
- } else {
- actions = new StandardChromeActions(
- domWindow, contentDispositionFilename, aRequest, dataListener);
- }
- var requestListener = new RequestListener(actions);
- domWindow.document.addEventListener(PDFJS_EVENT_ID, function(event) {
- requestListener.receive(event);
- }, false, true);
- if (actions.supportsIntegratedFind()) {
- var findEventManager = new FindEventManager(domWindow);
- findEventManager.bind();
- }
- listener.onStopRequest(aRequest, aContext, statusCode);
-
- if (domWindow.frameElement) {
- var isObjectEmbed = domWindow.frameElement.tagName !== 'IFRAME' ||
- domWindow.frameElement.className === 'previewPluginContentFrame';
- PdfJsTelemetry.onEmbed(isObjectEmbed);
- }
- }
- };
-
- // Keep the URL the same so the browser sees it as the same.
- channel.originalURI = aRequest.URI;
- channel.loadGroup = aRequest.loadGroup;
- channel.loadInfo.originAttributes = aRequest.loadInfo.originAttributes;
-
- // We can use the resource principal when data is fetched by the chrome,
- // e.g. useful for NoScript. Make make sure we reuse the origin attributes
- // from the request channel to keep isolation consistent.
- var ssm = Cc['@mozilla.org/scriptsecuritymanager;1']
- .getService(Ci.nsIScriptSecurityManager);
- var uri = NetUtil.newURI(PDF_VIEWER_WEB_PAGE, null, null);
- var resourcePrincipal;
- resourcePrincipal =
- ssm.createCodebasePrincipal(uri, aRequest.loadInfo.originAttributes);
- aRequest.owner = resourcePrincipal;
- asyncOpenChannel(channel, proxy, aContext);
- },
-
- // nsIRequestObserver::onStopRequest
- onStopRequest: function(aRequest, aContext, aStatusCode) {
- if (!this.dataListener) {
- // Do nothing
- return;
- }
-
- if (Components.isSuccessCode(aStatusCode)) {
- this.dataListener.finish();
- } else {
- this.dataListener.error(aStatusCode);
- }
- delete this.dataListener;
- delete this.binaryStream;
- }
-};
-
diff --git a/extensions/pdfjs/content/PdfjsChromeUtils.jsm b/extensions/pdfjs/content/PdfjsChromeUtils.jsm
deleted file mode 100644
index 7a082b6..0000000
--- a/extensions/pdfjs/content/PdfjsChromeUtils.jsm
+++ /dev/null
@@ -1,357 +0,0 @@
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* jshint esnext:true */
-/* globals Components, Services, XPCOMUtils */
-
-'use strict';
-
-var EXPORTED_SYMBOLS = ['PdfjsChromeUtils'];
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-const Cu = Components.utils;
-
-const PREF_PREFIX = 'pdfjs';
-const PDF_CONTENT_TYPE = 'application/pdf';
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-
-var Svc = {};
-XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
- '@mozilla.org/mime;1',
- 'nsIMIMEService');
-
-var DEFAULT_PREFERENCES =
-{
- "showPreviousViewOnLoad": true,
- "defaultZoomValue": "",
- "sidebarViewOnLoad": 0,
- "enableHandToolOnLoad": false,
- "enableWebGL": false,
- "pdfBugEnabled": false,
- "disableRange": false,
- "disableStream": false,
- "disableAutoFetch": false,
- "disableFontFace": false,
- "disableTextLayer": false,
- "useOnlyCssZoom": false,
- "externalLinkTarget": 0,
- "enhanceTextSelection": false,
- "renderInteractiveForms": false,
- "disablePageLabels": false
-}
-
-
-var PdfjsChromeUtils = {
- // For security purposes when running remote, we restrict preferences
- // content can access.
- _allowedPrefNames: Object.keys(DEFAULT_PREFERENCES),
- _ppmm: null,
- _mmg: null,
-
- /*
- * Public API
- */
-
- init: function () {
- this._browsers = new WeakSet();
- if (!this._ppmm) {
- // global parent process message manager (PPMM)
- this._ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1'].
- getService(Ci.nsIMessageBroadcaster);
- this._ppmm.addMessageListener('PDFJS:Parent:clearUserPref', this);
- this._ppmm.addMessageListener('PDFJS:Parent:setIntPref', this);
- this._ppmm.addMessageListener('PDFJS:Parent:setBoolPref', this);
- this._ppmm.addMessageListener('PDFJS:Parent:setCharPref', this);
- this._ppmm.addMessageListener('PDFJS:Parent:setStringPref', this);
- this._ppmm.addMessageListener('PDFJS:Parent:isDefaultHandlerApp', this);
-
- // global dom message manager (MMg)
- this._mmg = Cc['@mozilla.org/globalmessagemanager;1'].
- getService(Ci.nsIMessageListenerManager);
- this._mmg.addMessageListener('PDFJS:Parent:displayWarning', this);
-
- this._mmg.addMessageListener('PDFJS:Parent:addEventListener', this);
- this._mmg.addMessageListener('PDFJS:Parent:removeEventListener', this);
- this._mmg.addMessageListener('PDFJS:Parent:updateControlState', this);
-
- // observer to handle shutdown
- Services.obs.addObserver(this, 'quit-application', false);
- }
- },
-
- uninit: function () {
- if (this._ppmm) {
- this._ppmm.removeMessageListener('PDFJS:Parent:clearUserPref', this);
- this._ppmm.removeMessageListener('PDFJS:Parent:setIntPref', this);
- this._ppmm.removeMessageListener('PDFJS:Parent:setBoolPref', this);
- this._ppmm.removeMessageListener('PDFJS:Parent:setCharPref', this);
- this._ppmm.removeMessageListener('PDFJS:Parent:setStringPref', this);
- this._ppmm.removeMessageListener('PDFJS:Parent:isDefaultHandlerApp',
- this);
-
- this._mmg.removeMessageListener('PDFJS:Parent:displayWarning', this);
-
- this._mmg.removeMessageListener('PDFJS:Parent:addEventListener', this);
- this._mmg.removeMessageListener('PDFJS:Parent:removeEventListener', this);
- this._mmg.removeMessageListener('PDFJS:Parent:updateControlState', this);
-
- Services.obs.removeObserver(this, 'quit-application', false);
-
- this._mmg = null;
- this._ppmm = null;
- }
- },
-
- /*
- * Called by the main module when preference changes are picked up
- * in the parent process. Observers don't propagate so we need to
- * instruct the child to refresh its configuration and (possibly)
- * the module's registration.
- */
- notifyChildOfSettingsChange: function () {
- if (Services.appinfo.processType ===
- Services.appinfo.PROCESS_TYPE_DEFAULT && this._ppmm) {
- // XXX kinda bad, we want to get the parent process mm associated
- // with the content process. _ppmm is currently the global process
- // manager, which means this is going to fire to every child process
- // we have open. Unfortunately I can't find a way to get at that
- // process specific mm from js.
- this._ppmm.broadcastAsyncMessage('PDFJS:Child:refreshSettings', {});
- }
- },
-
- /*
- * Events
- */
-
- observe: function(aSubject, aTopic, aData) {
- if (aTopic === 'quit-application') {
- this.uninit();
- }
- },
-
- receiveMessage: function (aMsg) {
- switch (aMsg.name) {
- case 'PDFJS:Parent:clearUserPref':
- this._clearUserPref(aMsg.data.name);
- break;
- case 'PDFJS:Parent:setIntPref':
- this._setIntPref(aMsg.data.name, aMsg.data.value);
- break;
- case 'PDFJS:Parent:setBoolPref':
- this._setBoolPref(aMsg.data.name, aMsg.data.value);
- break;
- case 'PDFJS:Parent:setCharPref':
- this._setCharPref(aMsg.data.name, aMsg.data.value);
- break;
- case 'PDFJS:Parent:setStringPref':
- this._setStringPref(aMsg.data.name, aMsg.data.value);
- break;
- case 'PDFJS:Parent:isDefaultHandlerApp':
- return this.isDefaultHandlerApp();
- case 'PDFJS:Parent:displayWarning':
- this._displayWarning(aMsg);
- break;
-
-
- case 'PDFJS:Parent:updateControlState':
- return this._updateControlState(aMsg);
- case 'PDFJS:Parent:addEventListener':
- return this._addEventListener(aMsg);
- case 'PDFJS:Parent:removeEventListener':
- return this._removeEventListener(aMsg);
- }
- },
-
- /*
- * Internal
- */
-
- _findbarFromMessage: function(aMsg) {
- let browser = aMsg.target;
- let tabbrowser = browser.getTabBrowser();
- let tab = tabbrowser.getTabForBrowser(browser);
- return tabbrowser.getFindBar(tab);
- },
-
- _updateControlState: function (aMsg) {
- let data = aMsg.data;
- this._findbarFromMessage(aMsg)
- .updateControlState(data.result, data.findPrevious);
- },
-
- handleEvent: function(aEvent) {
- // To avoid forwarding the message as a CPOW, create a structured cloneable
- // version of the event for both performance, and ease of usage, reasons.
- let type = aEvent.type;
- let detail = {
- query: aEvent.detail.query,
- caseSensitive: aEvent.detail.caseSensitive,
- highlightAll: aEvent.detail.highlightAll,
- findPrevious: aEvent.detail.findPrevious
- };
-
- let browser = aEvent.currentTarget.browser;
- if (!this._browsers.has(browser)) {
- throw new Error('FindEventManager was not bound ' +
- 'for the current browser.');
- }
- // Only forward the events if the current browser is a registered browser.
- let mm = browser.messageManager;
- mm.sendAsyncMessage('PDFJS:Child:handleEvent',
- { type: type, detail: detail });
- aEvent.preventDefault();
- },
-
- _types: ['find',
- 'findagain',
- 'findhighlightallchange',
- 'findcasesensitivitychange'],
-
- _addEventListener: function (aMsg) {
- let browser = aMsg.target;
- if (this._browsers.has(browser)) {
- throw new Error('FindEventManager was bound 2nd time ' +
- 'without unbinding it first.');
- }
-
- // Since this jsm is global, we need to store all the browsers
- // we have to forward the messages for.
- this._browsers.add(browser);
-
- // And we need to start listening to find events.
- for (var i = 0; i < this._types.length; i++) {
- var type = this._types[i];
- this._findbarFromMessage(aMsg)
- .addEventListener(type, this, true);
- }
- },
-
- _removeEventListener: function (aMsg) {
- let browser = aMsg.target;
- if (!this._browsers.has(browser)) {
- throw new Error('FindEventManager was unbound without binding it first.');
- }
-
- this._browsers.delete(browser);
-
- // No reason to listen to find events any longer.
- for (var i = 0; i < this._types.length; i++) {
- var type = this._types[i];
- this._findbarFromMessage(aMsg)
- .removeEventListener(type, this, true);
- }
- },
-
- _ensurePreferenceAllowed: function (aPrefName) {
- let unPrefixedName = aPrefName.split(PREF_PREFIX + '.');
- if (unPrefixedName[0] !== '' ||
- this._allowedPrefNames.indexOf(unPrefixedName[1]) === -1) {
- let msg = '"' + aPrefName + '" ' +
- 'can\'t be accessed from content. See PdfjsChromeUtils.';
- throw new Error(msg);
- }
- },
-
- _clearUserPref: function (aPrefName) {
- this._ensurePreferenceAllowed(aPrefName);
- Services.prefs.clearUserPref(aPrefName);
- },
-
- _setIntPref: function (aPrefName, aPrefValue) {
- this._ensurePreferenceAllowed(aPrefName);
- Services.prefs.setIntPref(aPrefName, aPrefValue);
- },
-
- _setBoolPref: function (aPrefName, aPrefValue) {
- this._ensurePreferenceAllowed(aPrefName);
- Services.prefs.setBoolPref(aPrefName, aPrefValue);
- },
-
- _setCharPref: function (aPrefName, aPrefValue) {
- this._ensurePreferenceAllowed(aPrefName);
- Services.prefs.setCharPref(aPrefName, aPrefValue);
- },
-
- _setStringPref: function (aPrefName, aPrefValue) {
- this._ensurePreferenceAllowed(aPrefName);
- let str = Cc['@mozilla.org/supports-string;1']
- .createInstance(Ci.nsISupportsString);
- str.data = aPrefValue;
- Services.prefs.setComplexValue(aPrefName, Ci.nsISupportsString, str);
- },
-
- /*
- * Svc.mime doesn't have profile information in the child, so
- * we bounce this pdfjs enabled configuration check over to the
- * parent.
- */
- isDefaultHandlerApp: function () {
- var handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf');
- return (!handlerInfo.alwaysAskBeforeHandling &&
- handlerInfo.preferredAction === Ci.nsIHandlerInfo.handleInternally);
- },
-
- /*
- * Display a notification warning when the renderer isn't sure
- * a pdf displayed correctly.
- */
- _displayWarning: function (aMsg) {
- let data = aMsg.data;
- let browser = aMsg.target;
-
- let tabbrowser = browser.getTabBrowser();
- let notificationBox = tabbrowser.getNotificationBox(browser);
-
- // Flag so we don't send the message twice, since if the user clicks
- // "open with different viewer" both the button callback and
- // eventCallback will be called.
- let messageSent = false;
- function sendMessage(download) {
- let mm = browser.messageManager;
- mm.sendAsyncMessage('PDFJS:Child:fallbackDownload',
- { download: download });
- }
- let buttons = [{
- label: data.label,
- accessKey: data.accessKey,
- callback: function() {
- messageSent = true;
- sendMessage(true);
- }
- }];
- notificationBox.appendNotification(data.message, 'pdfjs-fallback', null,
- notificationBox.PRIORITY_INFO_LOW,
- buttons,
- function eventsCallback(eventType) {
- // Currently there is only one event "removed" but if there are any other
- // added in the future we still only care about removed at the moment.
- if (eventType !== 'removed') {
- return;
- }
- // Don't send a response again if we already responded when the button was
- // clicked.
- if (messageSent) {
- return;
- }
- sendMessage(false);
- });
- }
-};
-
-
diff --git a/extensions/pdfjs/content/PdfjsContentUtils.jsm b/extensions/pdfjs/content/PdfjsContentUtils.jsm
deleted file mode 100644
index 3dec5f3..0000000
--- a/extensions/pdfjs/content/PdfjsContentUtils.jsm
+++ /dev/null
@@ -1,150 +0,0 @@
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* jshint esnext:true */
-/* globals Components, Services, XPCOMUtils */
-
-'use strict';
-
-var EXPORTED_SYMBOLS = ['PdfjsContentUtils'];
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-const Cu = Components.utils;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-
-var PdfjsContentUtils = {
- _mm: null,
-
- /*
- * Public API
- */
-
- get isRemote() {
- return (Services.appinfo.processType ===
- Services.appinfo.PROCESS_TYPE_CONTENT);
- },
-
- init: function () {
- // child *process* mm, or when loaded into the parent for in-content
- // support the psuedo child process mm 'child PPMM'.
- if (!this._mm) {
- this._mm = Cc['@mozilla.org/childprocessmessagemanager;1'].
- getService(Ci.nsISyncMessageSender);
- this._mm.addMessageListener('PDFJS:Child:refreshSettings', this);
- Services.obs.addObserver(this, 'quit-application', false);
- }
- },
-
- uninit: function () {
- if (this._mm) {
- this._mm.removeMessageListener('PDFJS:Child:refreshSettings', this);
- Services.obs.removeObserver(this, 'quit-application');
- }
- this._mm = null;
- },
-
- /*
- * prefs utilities - the child does not have write access to prefs.
- * note, the pref names here are cross-checked against a list of
- * approved pdfjs prefs in chrome utils.
- */
-
- clearUserPref: function (aPrefName) {
- this._mm.sendSyncMessage('PDFJS:Parent:clearUserPref', {
- name: aPrefName
- });
- },
-
- setIntPref: function (aPrefName, aPrefValue) {
- this._mm.sendSyncMessage('PDFJS:Parent:setIntPref', {
- name: aPrefName,
- value: aPrefValue
- });
- },
-
- setBoolPref: function (aPrefName, aPrefValue) {
- this._mm.sendSyncMessage('PDFJS:Parent:setBoolPref', {
- name: aPrefName,
- value: aPrefValue
- });
- },
-
- setCharPref: function (aPrefName, aPrefValue) {
- this._mm.sendSyncMessage('PDFJS:Parent:setCharPref', {
- name: aPrefName,
- value: aPrefValue
- });
- },
-
- setStringPref: function (aPrefName, aPrefValue) {
- this._mm.sendSyncMessage('PDFJS:Parent:setStringPref', {
- name: aPrefName,
- value: aPrefValue
- });
- },
-
- /*
- * Forwards default app query to the parent where we check various
- * handler app settings only available in the parent process.
- */
- isDefaultHandlerApp: function () {
- return this._mm.sendSyncMessage('PDFJS:Parent:isDefaultHandlerApp')[0];
- },
-
- /*
- * Request the display of a notification warning in the associated window
- * when the renderer isn't sure a pdf displayed correctly.
- */
- displayWarning: function (aWindow, aMessage, aLabel, accessKey) {
- // the child's dom frame mm associated with the window.
- let winmm = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDocShell)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIContentFrameMessageManager);
- winmm.sendAsyncMessage('PDFJS:Parent:displayWarning', {
- message: aMessage,
- label: aLabel,
- accessKey: accessKey
- });
- },
-
- /*
- * Events
- */
-
- observe: function(aSubject, aTopic, aData) {
- if (aTopic === 'quit-application') {
- this.uninit();
- }
- },
-
- receiveMessage: function (aMsg) {
- switch (aMsg.name) {
- case 'PDFJS:Child:refreshSettings':
- // Only react to this if we are remote.
- if (Services.appinfo.processType ===
- Services.appinfo.PROCESS_TYPE_CONTENT) {
- let jsm = 'resource://pdf.js/PdfJs.jsm';
- let pdfjs = Components.utils.import(jsm, {}).PdfJs;
- pdfjs.updateRegistration();
- }
- break;
- }
- }
-};
-
diff --git a/extensions/pdfjs/content/build/pdf.js b/extensions/pdfjs/content/build/pdf.js
deleted file mode 100644
index 98a3bd3..0000000
--- a/extensions/pdfjs/content/build/pdf.js
+++ /dev/null
@@ -1,8387 +0,0 @@
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-(function (root, factory) {
- 'use strict';
- if (typeof define === 'function' && define.amd) {
- define('pdfjs-dist/build/pdf', ['exports'], factory);
- } else if (typeof exports !== 'undefined') {
- factory(exports);
- } else {
- factory(root['pdfjsDistBuildPdf'] = {});
- }
-}(this, function (exports) {
- // Use strict in our context only - users might not want it
- 'use strict';
- var pdfjsVersion = '1.6.315';
- var pdfjsBuild = 'a139c75';
- var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : null;
- var pdfjsLibs = {};
- (function pdfjsWrapper() {
- (function (root, factory) {
- factory(root.pdfjsSharedUtil = {});
- }(this, function (exports) {
- var globalScope = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this;
- var FONT_IDENTITY_MATRIX = [
- 0.001,
- 0,
- 0,
- 0.001,
- 0,
- 0
- ];
- var TextRenderingMode = {
- FILL: 0,
- STROKE: 1,
- FILL_STROKE: 2,
- INVISIBLE: 3,
- FILL_ADD_TO_PATH: 4,
- STROKE_ADD_TO_PATH: 5,
- FILL_STROKE_ADD_TO_PATH: 6,
- ADD_TO_PATH: 7,
- FILL_STROKE_MASK: 3,
- ADD_TO_PATH_FLAG: 4
- };
- var ImageKind = {
- GRAYSCALE_1BPP: 1,
- RGB_24BPP: 2,
- RGBA_32BPP: 3
- };
- var AnnotationType = {
- TEXT: 1,
- LINK: 2,
- FREETEXT: 3,
- LINE: 4,
- SQUARE: 5,
- CIRCLE: 6,
- POLYGON: 7,
- POLYLINE: 8,
- HIGHLIGHT: 9,
- UNDERLINE: 10,
- SQUIGGLY: 11,
- STRIKEOUT: 12,
- STAMP: 13,
- CARET: 14,
- INK: 15,
- POPUP: 16,
- FILEATTACHMENT: 17,
- SOUND: 18,
- MOVIE: 19,
- WIDGET: 20,
- SCREEN: 21,
- PRINTERMARK: 22,
- TRAPNET: 23,
- WATERMARK: 24,
- THREED: 25,
- REDACT: 26
- };
- var AnnotationFlag = {
- INVISIBLE: 0x01,
- HIDDEN: 0x02,
- PRINT: 0x04,
- NOZOOM: 0x08,
- NOROTATE: 0x10,
- NOVIEW: 0x20,
- READONLY: 0x40,
- LOCKED: 0x80,
- TOGGLENOVIEW: 0x100,
- LOCKEDCONTENTS: 0x200
- };
- var AnnotationFieldFlag = {
- READONLY: 0x0000001,
- REQUIRED: 0x0000002,
- NOEXPORT: 0x0000004,
- MULTILINE: 0x0001000,
- PASSWORD: 0x0002000,
- NOTOGGLETOOFF: 0x0004000,
- RADIO: 0x0008000,
- PUSHBUTTON: 0x0010000,
- COMBO: 0x0020000,
- EDIT: 0x0040000,
- SORT: 0x0080000,
- FILESELECT: 0x0100000,
- MULTISELECT: 0x0200000,
- DONOTSPELLCHECK: 0x0400000,
- DONOTSCROLL: 0x0800000,
- COMB: 0x1000000,
- RICHTEXT: 0x2000000,
- RADIOSINUNISON: 0x2000000,
- COMMITONSELCHANGE: 0x4000000
- };
- var AnnotationBorderStyleType = {
- SOLID: 1,
- DASHED: 2,
- BEVELED: 3,
- INSET: 4,
- UNDERLINE: 5
- };
- var StreamType = {
- UNKNOWN: 0,
- FLATE: 1,
- LZW: 2,
- DCT: 3,
- JPX: 4,
- JBIG: 5,
- A85: 6,
- AHX: 7,
- CCF: 8,
- RL: 9
- };
- var FontType = {
- UNKNOWN: 0,
- TYPE1: 1,
- TYPE1C: 2,
- CIDFONTTYPE0: 3,
- CIDFONTTYPE0C: 4,
- TRUETYPE: 5,
- CIDFONTTYPE2: 6,
- TYPE3: 7,
- OPENTYPE: 8,
- TYPE0: 9,
- MMTYPE1: 10
- };
- var VERBOSITY_LEVELS = {
- errors: 0,
- warnings: 1,
- infos: 5
- };
- // All the possible operations for an operator list.
- var OPS = {
- // Intentionally start from 1 so it is easy to spot bad operators that will be
- // 0's.
- dependency: 1,
- setLineWidth: 2,
- setLineCap: 3,
- setLineJoin: 4,
- setMiterLimit: 5,
- setDash: 6,
- setRenderingIntent: 7,
- setFlatness: 8,
- setGState: 9,
- save: 10,
- restore: 11,
- transform: 12,
- moveTo: 13,
- lineTo: 14,
- curveTo: 15,
- curveTo2: 16,
- curveTo3: 17,
- closePath: 18,
- rectangle: 19,
- stroke: 20,
- closeStroke: 21,
- fill: 22,
- eoFill: 23,
- fillStroke: 24,
- eoFillStroke: 25,
- closeFillStroke: 26,
- closeEOFillStroke: 27,
- endPath: 28,
- clip: 29,
- eoClip: 30,
- beginText: 31,
- endText: 32,
- setCharSpacing: 33,
- setWordSpacing: 34,
- setHScale: 35,
- setLeading: 36,
- setFont: 37,
- setTextRenderingMode: 38,
- setTextRise: 39,
- moveText: 40,
- setLeadingMoveText: 41,
- setTextMatrix: 42,
- nextLine: 43,
- showText: 44,
- showSpacedText: 45,
- nextLineShowText: 46,
- nextLineSetSpacingShowText: 47,
- setCharWidth: 48,
- setCharWidthAndBounds: 49,
- setStrokeColorSpace: 50,
- setFillColorSpace: 51,
- setStrokeColor: 52,
- setStrokeColorN: 53,
- setFillColor: 54,
- setFillColorN: 55,
- setStrokeGray: 56,
- setFillGray: 57,
- setStrokeRGBColor: 58,
- setFillRGBColor: 59,
- setStrokeCMYKColor: 60,
- setFillCMYKColor: 61,
- shadingFill: 62,
- beginInlineImage: 63,
- beginImageData: 64,
- endInlineImage: 65,
- paintXObject: 66,
- markPoint: 67,
- markPointProps: 68,
- beginMarkedContent: 69,
- beginMarkedContentProps: 70,
- endMarkedContent: 71,
- beginCompat: 72,
- endCompat: 73,
- paintFormXObjectBegin: 74,
- paintFormXObjectEnd: 75,
- beginGroup: 76,
- endGroup: 77,
- beginAnnotations: 78,
- endAnnotations: 79,
- beginAnnotation: 80,
- endAnnotation: 81,
- paintJpegXObject: 82,
- paintImageMaskXObject: 83,
- paintImageMaskXObjectGroup: 84,
- paintImageXObject: 85,
- paintInlineImageXObject: 86,
- paintInlineImageXObjectGroup: 87,
- paintImageXObjectRepeat: 88,
- paintImageMaskXObjectRepeat: 89,
- paintSolidColorImageMask: 90,
- constructPath: 91
- };
- var verbosity = VERBOSITY_LEVELS.warnings;
- function setVerbosityLevel(level) {
- verbosity = level;
- }
- function getVerbosityLevel() {
- return verbosity;
- }
- // A notice for devs. These are good for things that are helpful to devs, such
- // as warning that Workers were disabled, which is important to devs but not
- // end users.
- function info(msg) {
- if (verbosity >= VERBOSITY_LEVELS.infos) {
- console.log('Info: ' + msg);
- }
- }
- // Non-fatal warnings.
- function warn(msg) {
- if (verbosity >= VERBOSITY_LEVELS.warnings) {
- console.log('Warning: ' + msg);
- }
- }
- // Deprecated API function -- display regardless of the PDFJS.verbosity setting.
- function deprecated(details) {
- console.log('Deprecated API usage: ' + details);
- }
- // Fatal errors that should trigger the fallback UI and halt execution by
- // throwing an exception.
- function error(msg) {
- if (verbosity >= VERBOSITY_LEVELS.errors) {
- console.log('Error: ' + msg);
- console.log(backtrace());
- }
- throw new Error(msg);
- }
- function backtrace() {
- try {
- throw new Error();
- } catch (e) {
- return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
- }
- }
- function assert(cond, msg) {
- if (!cond) {
- error(msg);
- }
- }
- var UNSUPPORTED_FEATURES = {
- unknown: 'unknown',
- forms: 'forms',
- javaScript: 'javaScript',
- smask: 'smask',
- shadingPattern: 'shadingPattern',
- font: 'font'
- };
- // Checks if URLs have the same origin. For non-HTTP based URLs, returns false.
- function isSameOrigin(baseUrl, otherUrl) {
- try {
- var base = new URL(baseUrl);
- if (!base.origin || base.origin === 'null') {
- return false;
- }
- } // non-HTTP url
- catch (e) {
- return false;
- }
- var other = new URL(otherUrl, base);
- return base.origin === other.origin;
- }
- // Checks if URLs use one of the whitelisted protocols, e.g. to avoid XSS.
- function isValidProtocol(url) {
- if (!url) {
- return false;
- }
- switch (url.protocol) {
- case 'http:':
- case 'https:':
- case 'ftp:':
- case 'mailto:':
- case 'tel:':
- return true;
- default:
- return false;
- }
- }
- /**
- * Attempts to create a valid absolute URL (utilizing `isValidProtocol`).
- * @param {URL|string} url - An absolute, or relative, URL.
- * @param {URL|string} baseUrl - An absolute URL.
- * @returns Either a valid {URL}, or `null` otherwise.
- */
- function createValidAbsoluteUrl(url, baseUrl) {
- if (!url) {
- return null;
- }
- try {
- var absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url);
- if (isValidProtocol(absoluteUrl)) {
- return absoluteUrl;
- }
- } catch (ex) {
- }
- return null;
- }
- function shadow(obj, prop, value) {
- Object.defineProperty(obj, prop, {
- value: value,
- enumerable: true,
- configurable: true,
- writable: false
- });
- return value;
- }
- function getLookupTableFactory(initializer) {
- var lookup;
- return function () {
- if (initializer) {
- lookup = Object.create(null);
- initializer(lookup);
- initializer = null;
- }
- return lookup;
- };
- }
- var PasswordResponses = {
- NEED_PASSWORD: 1,
- INCORRECT_PASSWORD: 2
- };
- var PasswordException = function PasswordExceptionClosure() {
- function PasswordException(msg, code) {
- this.name = 'PasswordException';
- this.message = msg;
- this.code = code;
- }
- PasswordException.prototype = new Error();
- PasswordException.constructor = PasswordException;
- return PasswordException;
- }();
- var UnknownErrorException = function UnknownErrorExceptionClosure() {
- function UnknownErrorException(msg, details) {
- this.name = 'UnknownErrorException';
- this.message = msg;
- this.details = details;
- }
- UnknownErrorException.prototype = new Error();
- UnknownErrorException.constructor = UnknownErrorException;
- return UnknownErrorException;
- }();
- var InvalidPDFException = function InvalidPDFExceptionClosure() {
- function InvalidPDFException(msg) {
- this.name = 'InvalidPDFException';
- this.message = msg;
- }
- InvalidPDFException.prototype = new Error();
- InvalidPDFException.constructor = InvalidPDFException;
- return InvalidPDFException;
- }();
- var MissingPDFException = function MissingPDFExceptionClosure() {
- function MissingPDFException(msg) {
- this.name = 'MissingPDFException';
- this.message = msg;
- }
- MissingPDFException.prototype = new Error();
- MissingPDFException.constructor = MissingPDFException;
- return MissingPDFException;
- }();
- var UnexpectedResponseException = function UnexpectedResponseExceptionClosure() {
- function UnexpectedResponseException(msg, status) {
- this.name = 'UnexpectedResponseException';
- this.message = msg;
- this.status = status;
- }
- UnexpectedResponseException.prototype = new Error();
- UnexpectedResponseException.constructor = UnexpectedResponseException;
- return UnexpectedResponseException;
- }();
- var NotImplementedException = function NotImplementedExceptionClosure() {
- function NotImplementedException(msg) {
- this.message = msg;
- }
- NotImplementedException.prototype = new Error();
- NotImplementedException.prototype.name = 'NotImplementedException';
- NotImplementedException.constructor = NotImplementedException;
- return NotImplementedException;
- }();
- var MissingDataException = function MissingDataExceptionClosure() {
- function MissingDataException(begin, end) {
- this.begin = begin;
- this.end = end;
- this.message = 'Missing data [' + begin + ', ' + end + ')';
- }
- MissingDataException.prototype = new Error();
- MissingDataException.prototype.name = 'MissingDataException';
- MissingDataException.constructor = MissingDataException;
- return MissingDataException;
- }();
- var XRefParseException = function XRefParseExceptionClosure() {
- function XRefParseException(msg) {
- this.message = msg;
- }
- XRefParseException.prototype = new Error();
- XRefParseException.prototype.name = 'XRefParseException';
- XRefParseException.constructor = XRefParseException;
- return XRefParseException;
- }();
- var NullCharactersRegExp = /\x00/g;
- function removeNullCharacters(str) {
- if (typeof str !== 'string') {
- warn('The argument for removeNullCharacters must be a string.');
- return str;
- }
- return str.replace(NullCharactersRegExp, '');
- }
- function bytesToString(bytes) {
- assert(bytes !== null && typeof bytes === 'object' && bytes.length !== undefined, 'Invalid argument for bytesToString');
- var length = bytes.length;
- var MAX_ARGUMENT_COUNT = 8192;
- if (length < MAX_ARGUMENT_COUNT) {
- return String.fromCharCode.apply(null, bytes);
- }
- var strBuf = [];
- for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
- var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
- var chunk = bytes.subarray(i, chunkEnd);
- strBuf.push(String.fromCharCode.apply(null, chunk));
- }
- return strBuf.join('');
- }
- function stringToBytes(str) {
- assert(typeof str === 'string', 'Invalid argument for stringToBytes');
- var length = str.length;
- var bytes = new Uint8Array(length);
- for (var i = 0; i < length; ++i) {
- bytes[i] = str.charCodeAt(i) & 0xFF;
- }
- return bytes;
- }
- /**
- * Gets length of the array (Array, Uint8Array, or string) in bytes.
- * @param {Array|Uint8Array|string} arr
- * @returns {number}
- */
- function arrayByteLength(arr) {
- if (arr.length !== undefined) {
- return arr.length;
- }
- assert(arr.byteLength !== undefined);
- return arr.byteLength;
- }
- /**
- * Combines array items (arrays) into single Uint8Array object.
- * @param {Array} arr - the array of the arrays (Array, Uint8Array, or string).
- * @returns {Uint8Array}
- */
- function arraysToBytes(arr) {
- // Shortcut: if first and only item is Uint8Array, return it.
- if (arr.length === 1 && arr[0] instanceof Uint8Array) {
- return arr[0];
- }
- var resultLength = 0;
- var i, ii = arr.length;
- var item, itemLength;
- for (i = 0; i < ii; i++) {
- item = arr[i];
- itemLength = arrayByteLength(item);
- resultLength += itemLength;
- }
- var pos = 0;
- var data = new Uint8Array(resultLength);
- for (i = 0; i < ii; i++) {
- item = arr[i];
- if (!(item instanceof Uint8Array)) {
- if (typeof item === 'string') {
- item = stringToBytes(item);
- } else {
- item = new Uint8Array(item);
- }
- }
- itemLength = item.byteLength;
- data.set(item, pos);
- pos += itemLength;
- }
- return data;
- }
- function string32(value) {
- return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);
- }
- function log2(x) {
- var n = 1, i = 0;
- while (x > n) {
- n <<= 1;
- i++;
- }
- return i;
- }
- function readInt8(data, start) {
- return data[start] << 24 >> 24;
- }
- function readUint16(data, offset) {
- return data[offset] << 8 | data[offset + 1];
- }
- function readUint32(data, offset) {
- return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0;
- }
- // Lazy test the endianness of the platform
- // NOTE: This will be 'true' for simulated TypedArrays
- function isLittleEndian() {
- var buffer8 = new Uint8Array(2);
- buffer8[0] = 1;
- var buffer16 = new Uint16Array(buffer8.buffer);
- return buffer16[0] === 1;
- }
- // Checks if it's possible to eval JS expressions.
- function isEvalSupported() {
- try {
- new Function('');
- return true;
- } catch (e) {
- return false;
- }
- }
- var IDENTITY_MATRIX = [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0
- ];
- var Util = function UtilClosure() {
- function Util() {
- }
- var rgbBuf = [
- 'rgb(',
- 0,
- ',',
- 0,
- ',',
- 0,
- ')'
- ];
- // makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids
- // creating many intermediate strings.
- Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
- rgbBuf[1] = r;
- rgbBuf[3] = g;
- rgbBuf[5] = b;
- return rgbBuf.join('');
- };
- // Concatenates two transformation matrices together and returns the result.
- Util.transform = function Util_transform(m1, m2) {
- return [
- m1[0] * m2[0] + m1[2] * m2[1],
- m1[1] * m2[0] + m1[3] * m2[1],
- m1[0] * m2[2] + m1[2] * m2[3],
- m1[1] * m2[2] + m1[3] * m2[3],
- m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
- m1[1] * m2[4] + m1[3] * m2[5] + m1[5]
- ];
- };
- // For 2d affine transforms
- Util.applyTransform = function Util_applyTransform(p, m) {
- var xt = p[0] * m[0] + p[1] * m[2] + m[4];
- var yt = p[0] * m[1] + p[1] * m[3] + m[5];
- return [
- xt,
- yt
- ];
- };
- Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
- var d = m[0] * m[3] - m[1] * m[2];
- var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
- var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
- return [
- xt,
- yt
- ];
- };
- // Applies the transform to the rectangle and finds the minimum axially
- // aligned bounding box.
- Util.getAxialAlignedBoundingBox = function Util_getAxialAlignedBoundingBox(r, m) {
- var p1 = Util.applyTransform(r, m);
- var p2 = Util.applyTransform(r.slice(2, 4), m);
- var p3 = Util.applyTransform([
- r[0],
- r[3]
- ], m);
- var p4 = Util.applyTransform([
- r[2],
- r[1]
- ], m);
- return [
- Math.min(p1[0], p2[0], p3[0], p4[0]),
- Math.min(p1[1], p2[1], p3[1], p4[1]),
- Math.max(p1[0], p2[0], p3[0], p4[0]),
- Math.max(p1[1], p2[1], p3[1], p4[1])
- ];
- };
- Util.inverseTransform = function Util_inverseTransform(m) {
- var d = m[0] * m[3] - m[1] * m[2];
- return [
- m[3] / d,
- -m[1] / d,
- -m[2] / d,
- m[0] / d,
- (m[2] * m[5] - m[4] * m[3]) / d,
- (m[4] * m[1] - m[5] * m[0]) / d
- ];
- };
- // Apply a generic 3d matrix M on a 3-vector v:
- // | a b c | | X |
- // | d e f | x | Y |
- // | g h i | | Z |
- // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
- // with v as [X,Y,Z]
- Util.apply3dTransform = function Util_apply3dTransform(m, v) {
- return [
- m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
- m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
- m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
- ];
- };
- // This calculation uses Singular Value Decomposition.
- // The SVD can be represented with formula A = USV. We are interested in the
- // matrix S here because it represents the scale values.
- Util.singularValueDecompose2dScale = function Util_singularValueDecompose2dScale(m) {
- var transpose = [
- m[0],
- m[2],
- m[1],
- m[3]
- ];
- // Multiply matrix m with its transpose.
- var a = m[0] * transpose[0] + m[1] * transpose[2];
- var b = m[0] * transpose[1] + m[1] * transpose[3];
- var c = m[2] * transpose[0] + m[3] * transpose[2];
- var d = m[2] * transpose[1] + m[3] * transpose[3];
- // Solve the second degree polynomial to get roots.
- var first = (a + d) / 2;
- var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
- var sx = first + second || 1;
- var sy = first - second || 1;
- // Scale values are the square roots of the eigenvalues.
- return [
- Math.sqrt(sx),
- Math.sqrt(sy)
- ];
- };
- // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
- // For coordinate systems whose origin lies in the bottom-left, this
- // means normalization to (BL,TR) ordering. For systems with origin in the
- // top-left, this means (TL,BR) ordering.
- Util.normalizeRect = function Util_normalizeRect(rect) {
- var r = rect.slice(0);
- // clone rect
- if (rect[0] > rect[2]) {
- r[0] = rect[2];
- r[2] = rect[0];
- }
- if (rect[1] > rect[3]) {
- r[1] = rect[3];
- r[3] = rect[1];
- }
- return r;
- };
- // Returns a rectangle [x1, y1, x2, y2] corresponding to the
- // intersection of rect1 and rect2. If no intersection, returns 'false'
- // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
- Util.intersect = function Util_intersect(rect1, rect2) {
- function compare(a, b) {
- return a - b;
- }
- // Order points along the axes
- var orderedX = [
- rect1[0],
- rect1[2],
- rect2[0],
- rect2[2]
- ].sort(compare), orderedY = [
- rect1[1],
- rect1[3],
- rect2[1],
- rect2[3]
- ].sort(compare), result = [];
- rect1 = Util.normalizeRect(rect1);
- rect2 = Util.normalizeRect(rect2);
- // X: first and second points belong to different rectangles?
- if (orderedX[0] === rect1[0] && orderedX[1] === rect2[0] || orderedX[0] === rect2[0] && orderedX[1] === rect1[0]) {
- // Intersection must be between second and third points
- result[0] = orderedX[1];
- result[2] = orderedX[2];
- } else {
- return false;
- }
- // Y: first and second points belong to different rectangles?
- if (orderedY[0] === rect1[1] && orderedY[1] === rect2[1] || orderedY[0] === rect2[1] && orderedY[1] === rect1[1]) {
- // Intersection must be between second and third points
- result[1] = orderedY[1];
- result[3] = orderedY[2];
- } else {
- return false;
- }
- return result;
- };
- Util.sign = function Util_sign(num) {
- return num < 0 ? -1 : 1;
- };
- var ROMAN_NUMBER_MAP = [
- '',
- 'C',
- 'CC',
- 'CCC',
- 'CD',
- 'D',
- 'DC',
- 'DCC',
- 'DCCC',
- 'CM',
- '',
- 'X',
- 'XX',
- 'XXX',
- 'XL',
- 'L',
- 'LX',
- 'LXX',
- 'LXXX',
- 'XC',
- '',
- 'I',
- 'II',
- 'III',
- 'IV',
- 'V',
- 'VI',
- 'VII',
- 'VIII',
- 'IX'
- ];
- /**
- * Converts positive integers to (upper case) Roman numerals.
- * @param {integer} number - The number that should be converted.
- * @param {boolean} lowerCase - Indicates if the result should be converted
- * to lower case letters. The default is false.
- * @return {string} The resulting Roman number.
- */
- Util.toRoman = function Util_toRoman(number, lowerCase) {
- assert(isInt(number) && number > 0, 'The number should be a positive integer.');
- var pos, romanBuf = [];
- // Thousands
- while (number >= 1000) {
- number -= 1000;
- romanBuf.push('M');
- }
- // Hundreds
- pos = number / 100 | 0;
- number %= 100;
- romanBuf.push(ROMAN_NUMBER_MAP[pos]);
- // Tens
- pos = number / 10 | 0;
- number %= 10;
- romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
- // Ones
- romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
- var romanStr = romanBuf.join('');
- return lowerCase ? romanStr.toLowerCase() : romanStr;
- };
- Util.appendToArray = function Util_appendToArray(arr1, arr2) {
- Array.prototype.push.apply(arr1, arr2);
- };
- Util.prependToArray = function Util_prependToArray(arr1, arr2) {
- Array.prototype.unshift.apply(arr1, arr2);
- };
- Util.extendObj = function extendObj(obj1, obj2) {
- for (var key in obj2) {
- obj1[key] = obj2[key];
- }
- };
- Util.getInheritableProperty = function Util_getInheritableProperty(dict, name, getArray) {
- while (dict && !dict.has(name)) {
- dict = dict.get('Parent');
- }
- if (!dict) {
- return null;
- }
- return getArray ? dict.getArray(name) : dict.get(name);
- };
- Util.inherit = function Util_inherit(sub, base, prototype) {
- sub.prototype = Object.create(base.prototype);
- sub.prototype.constructor = sub;
- for (var prop in prototype) {
- sub.prototype[prop] = prototype[prop];
- }
- };
- Util.loadScript = function Util_loadScript(src, callback) {
- var script = document.createElement('script');
- var loaded = false;
- script.setAttribute('src', src);
- if (callback) {
- script.onload = function () {
- if (!loaded) {
- callback();
- }
- loaded = true;
- };
- }
- document.getElementsByTagName('head')[0].appendChild(script);
- };
- return Util;
- }();
- /**
- * PDF page viewport created based on scale, rotation and offset.
- * @class
- * @alias PageViewport
- */
- var PageViewport = function PageViewportClosure() {
- /**
- * @constructor
- * @private
- * @param viewBox {Array} xMin, yMin, xMax and yMax coordinates.
- * @param scale {number} scale of the viewport.
- * @param rotation {number} rotations of the viewport in degrees.
- * @param offsetX {number} offset X
- * @param offsetY {number} offset Y
- * @param dontFlip {boolean} if true, axis Y will not be flipped.
- */
- function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) {
- this.viewBox = viewBox;
- this.scale = scale;
- this.rotation = rotation;
- this.offsetX = offsetX;
- this.offsetY = offsetY;
- // creating transform to convert pdf coordinate system to the normal
- // canvas like coordinates taking in account scale and rotation
- var centerX = (viewBox[2] + viewBox[0]) / 2;
- var centerY = (viewBox[3] + viewBox[1]) / 2;
- var rotateA, rotateB, rotateC, rotateD;
- rotation = rotation % 360;
- rotation = rotation < 0 ? rotation + 360 : rotation;
- switch (rotation) {
- case 180:
- rotateA = -1;
- rotateB = 0;
- rotateC = 0;
- rotateD = 1;
- break;
- case 90:
- rotateA = 0;
- rotateB = 1;
- rotateC = 1;
- rotateD = 0;
- break;
- case 270:
- rotateA = 0;
- rotateB = -1;
- rotateC = -1;
- rotateD = 0;
- break;
- //case 0:
- default:
- rotateA = 1;
- rotateB = 0;
- rotateC = 0;
- rotateD = -1;
- break;
- }
- if (dontFlip) {
- rotateC = -rotateC;
- rotateD = -rotateD;
- }
- var offsetCanvasX, offsetCanvasY;
- var width, height;
- if (rotateA === 0) {
- offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
- offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
- width = Math.abs(viewBox[3] - viewBox[1]) * scale;
- height = Math.abs(viewBox[2] - viewBox[0]) * scale;
- } else {
- offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
- offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
- width = Math.abs(viewBox[2] - viewBox[0]) * scale;
- height = Math.abs(viewBox[3] - viewBox[1]) * scale;
- }
- // creating transform for the following operations:
- // translate(-centerX, -centerY), rotate and flip vertically,
- // scale, and translate(offsetCanvasX, offsetCanvasY)
- this.transform = [
- rotateA * scale,
- rotateB * scale,
- rotateC * scale,
- rotateD * scale,
- offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
- offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
- ];
- this.width = width;
- this.height = height;
- this.fontScale = scale;
- }
- PageViewport.prototype = /** @lends PageViewport.prototype */
- {
- /**
- * Clones viewport with additional properties.
- * @param args {Object} (optional) If specified, may contain the 'scale' or
- * 'rotation' properties to override the corresponding properties in
- * the cloned viewport.
- * @returns {PageViewport} Cloned viewport.
- */
- clone: function PageViewPort_clone(args) {
- args = args || {};
- var scale = 'scale' in args ? args.scale : this.scale;
- var rotation = 'rotation' in args ? args.rotation : this.rotation;
- return new PageViewport(this.viewBox.slice(), scale, rotation, this.offsetX, this.offsetY, args.dontFlip);
- },
- /**
- * Converts PDF point to the viewport coordinates. For examples, useful for
- * converting PDF location into canvas pixel coordinates.
- * @param x {number} X coordinate.
- * @param y {number} Y coordinate.
- * @returns {Object} Object that contains 'x' and 'y' properties of the
- * point in the viewport coordinate space.
- * @see {@link convertToPdfPoint}
- * @see {@link convertToViewportRectangle}
- */
- convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
- return Util.applyTransform([
- x,
- y
- ], this.transform);
- },
- /**
- * Converts PDF rectangle to the viewport coordinates.
- * @param rect {Array} xMin, yMin, xMax and yMax coordinates.
- * @returns {Array} Contains corresponding coordinates of the rectangle
- * in the viewport coordinate space.
- * @see {@link convertToViewportPoint}
- */
- convertToViewportRectangle: function PageViewport_convertToViewportRectangle(rect) {
- var tl = Util.applyTransform([
- rect[0],
- rect[1]
- ], this.transform);
- var br = Util.applyTransform([
- rect[2],
- rect[3]
- ], this.transform);
- return [
- tl[0],
- tl[1],
- br[0],
- br[1]
- ];
- },
- /**
- * Converts viewport coordinates to the PDF location. For examples, useful
- * for converting canvas pixel location into PDF one.
- * @param x {number} X coordinate.
- * @param y {number} Y coordinate.
- * @returns {Object} Object that contains 'x' and 'y' properties of the
- * point in the PDF coordinate space.
- * @see {@link convertToViewportPoint}
- */
- convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
- return Util.applyInverseTransform([
- x,
- y
- ], this.transform);
- }
- };
- return PageViewport;
- }();
- var PDFStringTranslateTable = [
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0x2D8,
- 0x2C7,
- 0x2C6,
- 0x2D9,
- 0x2DD,
- 0x2DB,
- 0x2DA,
- 0x2DC,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0x2022,
- 0x2020,
- 0x2021,
- 0x2026,
- 0x2014,
- 0x2013,
- 0x192,
- 0x2044,
- 0x2039,
- 0x203A,
- 0x2212,
- 0x2030,
- 0x201E,
- 0x201C,
- 0x201D,
- 0x2018,
- 0x2019,
- 0x201A,
- 0x2122,
- 0xFB01,
- 0xFB02,
- 0x141,
- 0x152,
- 0x160,
- 0x178,
- 0x17D,
- 0x131,
- 0x142,
- 0x153,
- 0x161,
- 0x17E,
- 0,
- 0x20AC
- ];
- function stringToPDFString(str) {
- var i, n = str.length, strBuf = [];
- if (str[0] === '\xFE' && str[1] === '\xFF') {
- // UTF16BE BOM
- for (i = 2; i < n; i += 2) {
- strBuf.push(String.fromCharCode(str.charCodeAt(i) << 8 | str.charCodeAt(i + 1)));
- }
- } else {
- for (i = 0; i < n; ++i) {
- var code = PDFStringTranslateTable[str.charCodeAt(i)];
- strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
- }
- }
- return strBuf.join('');
- }
- function stringToUTF8String(str) {
- return decodeURIComponent(escape(str));
- }
- function utf8StringToString(str) {
- return unescape(encodeURIComponent(str));
- }
- function isEmptyObj(obj) {
- for (var key in obj) {
- return false;
- }
- return true;
- }
- function isBool(v) {
- return typeof v === 'boolean';
- }
- function isInt(v) {
- return typeof v === 'number' && (v | 0) === v;
- }
- function isNum(v) {
- return typeof v === 'number';
- }
- function isString(v) {
- return typeof v === 'string';
- }
- function isArray(v) {
- return v instanceof Array;
- }
- function isArrayBuffer(v) {
- return typeof v === 'object' && v !== null && v.byteLength !== undefined;
- }
- // Checks if ch is one of the following characters: SPACE, TAB, CR or LF.
- function isSpace(ch) {
- return ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A;
- }
- /**
- * Promise Capability object.
- *
- * @typedef {Object} PromiseCapability
- * @property {Promise} promise - A promise object.
- * @property {function} resolve - Fulfills the promise.
- * @property {function} reject - Rejects the promise.
- */
- /**
- * Creates a promise capability object.
- * @alias createPromiseCapability
- *
- * @return {PromiseCapability} A capability object contains:
- * - a Promise, resolve and reject methods.
- */
- function createPromiseCapability() {
- var capability = {};
- capability.promise = new Promise(function (resolve, reject) {
- capability.resolve = resolve;
- capability.reject = reject;
- });
- return capability;
- }
- /**
- * Polyfill for Promises:
- * The following promise implementation tries to generally implement the
- * Promise/A+ spec. Some notable differences from other promise libraries are:
- * - There currently isn't a separate deferred and promise object.
- * - Unhandled rejections eventually show an error if they aren't handled.
- *
- * Based off of the work in:
- * https://bugzilla.mozilla.org/show_bug.cgi?id=810490
- */
- (function PromiseClosure() {
- if (globalScope.Promise) {
- // Promises existing in the DOM/Worker, checking presence of all/resolve
- if (typeof globalScope.Promise.all !== 'function') {
- globalScope.Promise.all = function (iterable) {
- var count = 0, results = [], resolve, reject;
- var promise = new globalScope.Promise(function (resolve_, reject_) {
- resolve = resolve_;
- reject = reject_;
- });
- iterable.forEach(function (p, i) {
- count++;
- p.then(function (result) {
- results[i] = result;
- count--;
- if (count === 0) {
- resolve(results);
- }
- }, reject);
- });
- if (count === 0) {
- resolve(results);
- }
- return promise;
- };
- }
- if (typeof globalScope.Promise.resolve !== 'function') {
- globalScope.Promise.resolve = function (value) {
- return new globalScope.Promise(function (resolve) {
- resolve(value);
- });
- };
- }
- if (typeof globalScope.Promise.reject !== 'function') {
- globalScope.Promise.reject = function (reason) {
- return new globalScope.Promise(function (resolve, reject) {
- reject(reason);
- });
- };
- }
- if (typeof globalScope.Promise.prototype.catch !== 'function') {
- globalScope.Promise.prototype.catch = function (onReject) {
- return globalScope.Promise.prototype.then(undefined, onReject);
- };
- }
- return;
- }
- throw new Error('DOM Promise is not present');
- }());
- var StatTimer = function StatTimerClosure() {
- function rpad(str, pad, length) {
- while (str.length < length) {
- str += pad;
- }
- return str;
- }
- function StatTimer() {
- this.started = Object.create(null);
- this.times = [];
- this.enabled = true;
- }
- StatTimer.prototype = {
- time: function StatTimer_time(name) {
- if (!this.enabled) {
- return;
- }
- if (name in this.started) {
- warn('Timer is already running for ' + name);
- }
- this.started[name] = Date.now();
- },
- timeEnd: function StatTimer_timeEnd(name) {
- if (!this.enabled) {
- return;
- }
- if (!(name in this.started)) {
- warn('Timer has not been started for ' + name);
- }
- this.times.push({
- 'name': name,
- 'start': this.started[name],
- 'end': Date.now()
- });
- // Remove timer from started so it can be called again.
- delete this.started[name];
- },
- toString: function StatTimer_toString() {
- var i, ii;
- var times = this.times;
- var out = '';
- // Find the longest name for padding purposes.
- var longest = 0;
- for (i = 0, ii = times.length; i < ii; ++i) {
- var name = times[i]['name'];
- if (name.length > longest) {
- longest = name.length;
- }
- }
- for (i = 0, ii = times.length; i < ii; ++i) {
- var span = times[i];
- var duration = span.end - span.start;
- out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
- }
- return out;
- }
- };
- return StatTimer;
- }();
- var createBlob = function createBlob(data, contentType) {
- if (typeof Blob !== 'undefined') {
- return new Blob([data], { type: contentType });
- }
- warn('The "Blob" constructor is not supported.');
- };
- var createObjectURL = function createObjectURLClosure() {
- // Blob/createObjectURL is not available, falling back to data schema.
- var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
- return function createObjectURL(data, contentType, forceDataSchema) {
- if (!forceDataSchema && typeof URL !== 'undefined' && URL.createObjectURL) {
- var blob = createBlob(data, contentType);
- return URL.createObjectURL(blob);
- }
- var buffer = 'data:' + contentType + ';base64,';
- for (var i = 0, ii = data.length; i < ii; i += 3) {
- var b1 = data[i] & 0xFF;
- var b2 = data[i + 1] & 0xFF;
- var b3 = data[i + 2] & 0xFF;
- var d1 = b1 >> 2, d2 = (b1 & 3) << 4 | b2 >> 4;
- var d3 = i + 1 < ii ? (b2 & 0xF) << 2 | b3 >> 6 : 64;
- var d4 = i + 2 < ii ? b3 & 0x3F : 64;
- buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
- }
- return buffer;
- };
- }();
- function MessageHandler(sourceName, targetName, comObj) {
- this.sourceName = sourceName;
- this.targetName = targetName;
- this.comObj = comObj;
- this.callbackIndex = 1;
- this.postMessageTransfers = true;
- var callbacksCapabilities = this.callbacksCapabilities = Object.create(null);
- var ah = this.actionHandler = Object.create(null);
- this._onComObjOnMessage = function messageHandlerComObjOnMessage(event) {
- var data = event.data;
- if (data.targetName !== this.sourceName) {
- return;
- }
- if (data.isReply) {
- var callbackId = data.callbackId;
- if (data.callbackId in callbacksCapabilities) {
- var callback = callbacksCapabilities[callbackId];
- delete callbacksCapabilities[callbackId];
- if ('error' in data) {
- callback.reject(data.error);
- } else {
- callback.resolve(data.data);
- }
- } else {
- error('Cannot resolve callback ' + callbackId);
- }
- } else if (data.action in ah) {
- var action = ah[data.action];
- if (data.callbackId) {
- var sourceName = this.sourceName;
- var targetName = data.sourceName;
- Promise.resolve().then(function () {
- return action[0].call(action[1], data.data);
- }).then(function (result) {
- comObj.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- isReply: true,
- callbackId: data.callbackId,
- data: result
- });
- }, function (reason) {
- if (reason instanceof Error) {
- // Serialize error to avoid "DataCloneError"
- reason = reason + '';
- }
- comObj.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- isReply: true,
- callbackId: data.callbackId,
- error: reason
- });
- });
- } else {
- action[0].call(action[1], data.data);
- }
- } else {
- error('Unknown action from worker: ' + data.action);
- }
- }.bind(this);
- comObj.addEventListener('message', this._onComObjOnMessage);
- }
- MessageHandler.prototype = {
- on: function messageHandlerOn(actionName, handler, scope) {
- var ah = this.actionHandler;
- if (ah[actionName]) {
- error('There is already an actionName called "' + actionName + '"');
- }
- ah[actionName] = [
- handler,
- scope
- ];
- },
- /**
- * Sends a message to the comObj to invoke the action with the supplied data.
- * @param {String} actionName Action to call.
- * @param {JSON} data JSON data to send.
- * @param {Array} [transfers] Optional list of transfers/ArrayBuffers
- */
- send: function messageHandlerSend(actionName, data, transfers) {
- var message = {
- sourceName: this.sourceName,
- targetName: this.targetName,
- action: actionName,
- data: data
- };
- this.postMessage(message, transfers);
- },
- /**
- * Sends a message to the comObj to invoke the action with the supplied data.
- * Expects that other side will callback with the response.
- * @param {String} actionName Action to call.
- * @param {JSON} data JSON data to send.
- * @param {Array} [transfers] Optional list of transfers/ArrayBuffers.
- * @returns {Promise} Promise to be resolved with response data.
- */
- sendWithPromise: function messageHandlerSendWithPromise(actionName, data, transfers) {
- var callbackId = this.callbackIndex++;
- var message = {
- sourceName: this.sourceName,
- targetName: this.targetName,
- action: actionName,
- data: data,
- callbackId: callbackId
- };
- var capability = createPromiseCapability();
- this.callbacksCapabilities[callbackId] = capability;
- try {
- this.postMessage(message, transfers);
- } catch (e) {
- capability.reject(e);
- }
- return capability.promise;
- },
- /**
- * Sends raw message to the comObj.
- * @private
- * @param message {Object} Raw message.
- * @param transfers List of transfers/ArrayBuffers, or undefined.
- */
- postMessage: function (message, transfers) {
- if (transfers && this.postMessageTransfers) {
- this.comObj.postMessage(message, transfers);
- } else {
- this.comObj.postMessage(message);
- }
- },
- destroy: function () {
- this.comObj.removeEventListener('message', this._onComObjOnMessage);
- }
- };
- function loadJpegStream(id, imageUrl, objs) {
- var img = new Image();
- img.onload = function loadJpegStream_onloadClosure() {
- objs.resolve(id, img);
- };
- img.onerror = function loadJpegStream_onerrorClosure() {
- objs.resolve(id, null);
- warn('Error during JPEG image loading');
- };
- img.src = imageUrl;
- }
- exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX;
- exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
- exports.OPS = OPS;
- exports.VERBOSITY_LEVELS = VERBOSITY_LEVELS;
- exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
- exports.AnnotationBorderStyleType = AnnotationBorderStyleType;
- exports.AnnotationFieldFlag = AnnotationFieldFlag;
- exports.AnnotationFlag = AnnotationFlag;
- exports.AnnotationType = AnnotationType;
- exports.FontType = FontType;
- exports.ImageKind = ImageKind;
- exports.InvalidPDFException = InvalidPDFException;
- exports.MessageHandler = MessageHandler;
- exports.MissingDataException = MissingDataException;
- exports.MissingPDFException = MissingPDFException;
- exports.NotImplementedException = NotImplementedException;
- exports.PageViewport = PageViewport;
- exports.PasswordException = PasswordException;
- exports.PasswordResponses = PasswordResponses;
- exports.StatTimer = StatTimer;
- exports.StreamType = StreamType;
- exports.TextRenderingMode = TextRenderingMode;
- exports.UnexpectedResponseException = UnexpectedResponseException;
- exports.UnknownErrorException = UnknownErrorException;
- exports.Util = Util;
- exports.XRefParseException = XRefParseException;
- exports.arrayByteLength = arrayByteLength;
- exports.arraysToBytes = arraysToBytes;
- exports.assert = assert;
- exports.bytesToString = bytesToString;
- exports.createBlob = createBlob;
- exports.createPromiseCapability = createPromiseCapability;
- exports.createObjectURL = createObjectURL;
- exports.deprecated = deprecated;
- exports.error = error;
- exports.getLookupTableFactory = getLookupTableFactory;
- exports.getVerbosityLevel = getVerbosityLevel;
- exports.globalScope = globalScope;
- exports.info = info;
- exports.isArray = isArray;
- exports.isArrayBuffer = isArrayBuffer;
- exports.isBool = isBool;
- exports.isEmptyObj = isEmptyObj;
- exports.isInt = isInt;
- exports.isNum = isNum;
- exports.isString = isString;
- exports.isSpace = isSpace;
- exports.isSameOrigin = isSameOrigin;
- exports.createValidAbsoluteUrl = createValidAbsoluteUrl;
- exports.isLittleEndian = isLittleEndian;
- exports.isEvalSupported = isEvalSupported;
- exports.loadJpegStream = loadJpegStream;
- exports.log2 = log2;
- exports.readInt8 = readInt8;
- exports.readUint16 = readUint16;
- exports.readUint32 = readUint32;
- exports.removeNullCharacters = removeNullCharacters;
- exports.setVerbosityLevel = setVerbosityLevel;
- exports.shadow = shadow;
- exports.string32 = string32;
- exports.stringToBytes = stringToBytes;
- exports.stringToPDFString = stringToPDFString;
- exports.stringToUTF8String = stringToUTF8String;
- exports.utf8StringToString = utf8StringToString;
- exports.warn = warn;
- }));
- (function (root, factory) {
- factory(root.pdfjsDisplayDOMUtils = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- var removeNullCharacters = sharedUtil.removeNullCharacters;
- var warn = sharedUtil.warn;
- var deprecated = sharedUtil.deprecated;
- var createValidAbsoluteUrl = sharedUtil.createValidAbsoluteUrl;
- /**
- * Optimised CSS custom property getter/setter.
- * @class
- */
- var CustomStyle = function CustomStyleClosure() {
- // As noted on: http://www.zachstronaut.com/posts/2009/02/17/
- // animate-css-transforms-firefox-webkit.html
- // in some versions of IE9 it is critical that ms appear in this list
- // before Moz
- var prefixes = [
- 'ms',
- 'Moz',
- 'Webkit',
- 'O'
- ];
- var _cache = Object.create(null);
- function CustomStyle() {
- }
- CustomStyle.getProp = function get(propName, element) {
- // check cache only when no element is given
- if (arguments.length === 1 && typeof _cache[propName] === 'string') {
- return _cache[propName];
- }
- element = element || document.documentElement;
- var style = element.style, prefixed, uPropName;
- // test standard property first
- if (typeof style[propName] === 'string') {
- return _cache[propName] = propName;
- }
- // capitalize
- uPropName = propName.charAt(0).toUpperCase() + propName.slice(1);
- // test vendor specific properties
- for (var i = 0, l = prefixes.length; i < l; i++) {
- prefixed = prefixes[i] + uPropName;
- if (typeof style[prefixed] === 'string') {
- return _cache[propName] = prefixed;
- }
- }
- //if all fails then set to undefined
- return _cache[propName] = 'undefined';
- };
- CustomStyle.setProp = function set(propName, element, str) {
- var prop = this.getProp(propName);
- if (prop !== 'undefined') {
- element.style[prop] = str;
- }
- };
- return CustomStyle;
- }();
- var hasCanvasTypedArrays;
- hasCanvasTypedArrays = function () {
- return true;
- };
- var LinkTarget = {
- NONE: 0,
- // Default value.
- SELF: 1,
- BLANK: 2,
- PARENT: 3,
- TOP: 4
- };
- var LinkTargetStringMap = [
- '',
- '_self',
- '_blank',
- '_parent',
- '_top'
- ];
- /**
- * @typedef ExternalLinkParameters
- * @typedef {Object} ExternalLinkParameters
- * @property {string} url - An absolute URL.
- * @property {LinkTarget} target - The link target.
- * @property {string} rel - The link relationship.
- */
- /**
- * Adds various attributes (href, title, target, rel) to hyperlinks.
- * @param {HTMLLinkElement} link - The link element.
- * @param {ExternalLinkParameters} params
- */
- function addLinkAttributes(link, params) {
- var url = params && params.url;
- link.href = link.title = url ? removeNullCharacters(url) : '';
- if (url) {
- var target = params.target;
- if (typeof target === 'undefined') {
- target = getDefaultSetting('externalLinkTarget');
- }
- link.target = LinkTargetStringMap[target];
- var rel = params.rel;
- if (typeof rel === 'undefined') {
- rel = getDefaultSetting('externalLinkRel');
- }
- link.rel = rel;
- }
- }
- // Gets the file name from a given URL.
- function getFilenameFromUrl(url) {
- var anchor = url.indexOf('#');
- var query = url.indexOf('?');
- var end = Math.min(anchor > 0 ? anchor : url.length, query > 0 ? query : url.length);
- return url.substring(url.lastIndexOf('/', end) + 1, end);
- }
- function getDefaultSetting(id) {
- // The list of the settings and their default is maintained for backward
- // compatibility and shall not be extended or modified. See also global.js.
- var globalSettings = sharedUtil.globalScope.PDFJS;
- switch (id) {
- case 'pdfBug':
- return globalSettings ? globalSettings.pdfBug : false;
- case 'disableAutoFetch':
- return globalSettings ? globalSettings.disableAutoFetch : false;
- case 'disableStream':
- return globalSettings ? globalSettings.disableStream : false;
- case 'disableRange':
- return globalSettings ? globalSettings.disableRange : false;
- case 'disableFontFace':
- return globalSettings ? globalSettings.disableFontFace : false;
- case 'disableCreateObjectURL':
- return globalSettings ? globalSettings.disableCreateObjectURL : false;
- case 'disableWebGL':
- return globalSettings ? globalSettings.disableWebGL : true;
- case 'cMapUrl':
- return globalSettings ? globalSettings.cMapUrl : null;
- case 'cMapPacked':
- return globalSettings ? globalSettings.cMapPacked : false;
- case 'postMessageTransfers':
- return globalSettings ? globalSettings.postMessageTransfers : true;
- case 'workerSrc':
- return globalSettings ? globalSettings.workerSrc : null;
- case 'disableWorker':
- return globalSettings ? globalSettings.disableWorker : false;
- case 'maxImageSize':
- return globalSettings ? globalSettings.maxImageSize : -1;
- case 'imageResourcesPath':
- return globalSettings ? globalSettings.imageResourcesPath : '';
- case 'isEvalSupported':
- return globalSettings ? globalSettings.isEvalSupported : true;
- case 'externalLinkTarget':
- if (!globalSettings) {
- return LinkTarget.NONE;
- }
- switch (globalSettings.externalLinkTarget) {
- case LinkTarget.NONE:
- case LinkTarget.SELF:
- case LinkTarget.BLANK:
- case LinkTarget.PARENT:
- case LinkTarget.TOP:
- return globalSettings.externalLinkTarget;
- }
- warn('PDFJS.externalLinkTarget is invalid: ' + globalSettings.externalLinkTarget);
- // Reset the external link target, to suppress further warnings.
- globalSettings.externalLinkTarget = LinkTarget.NONE;
- return LinkTarget.NONE;
- case 'externalLinkRel':
- return globalSettings ? globalSettings.externalLinkRel : 'noreferrer';
- case 'enableStats':
- return !!(globalSettings && globalSettings.enableStats);
- default:
- throw new Error('Unknown default setting: ' + id);
- }
- }
- function isExternalLinkTargetSet() {
- var externalLinkTarget = getDefaultSetting('externalLinkTarget');
- switch (externalLinkTarget) {
- case LinkTarget.NONE:
- return false;
- case LinkTarget.SELF:
- case LinkTarget.BLANK:
- case LinkTarget.PARENT:
- case LinkTarget.TOP:
- return true;
- }
- }
- function isValidUrl(url, allowRelative) {
- deprecated('isValidUrl(), please use createValidAbsoluteUrl() instead.');
- var baseUrl = allowRelative ? 'http://example.com' : null;
- return createValidAbsoluteUrl(url, baseUrl) !== null;
- }
- exports.CustomStyle = CustomStyle;
- exports.addLinkAttributes = addLinkAttributes;
- exports.isExternalLinkTargetSet = isExternalLinkTargetSet;
- exports.isValidUrl = isValidUrl;
- exports.getFilenameFromUrl = getFilenameFromUrl;
- exports.LinkTarget = LinkTarget;
- exports.hasCanvasTypedArrays = hasCanvasTypedArrays;
- exports.getDefaultSetting = getDefaultSetting;
- }));
- (function (root, factory) {
- factory(root.pdfjsDisplayFontLoader = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- var assert = sharedUtil.assert;
- var bytesToString = sharedUtil.bytesToString;
- var string32 = sharedUtil.string32;
- var shadow = sharedUtil.shadow;
- var warn = sharedUtil.warn;
- function FontLoader(docId) {
- this.docId = docId;
- this.styleElement = null;
- }
- FontLoader.prototype = {
- insertRule: function fontLoaderInsertRule(rule) {
- var styleElement = this.styleElement;
- if (!styleElement) {
- styleElement = this.styleElement = document.createElement('style');
- styleElement.id = 'PDFJS_FONT_STYLE_TAG_' + this.docId;
- document.documentElement.getElementsByTagName('head')[0].appendChild(styleElement);
- }
- var styleSheet = styleElement.sheet;
- styleSheet.insertRule(rule, styleSheet.cssRules.length);
- },
- clear: function fontLoaderClear() {
- var styleElement = this.styleElement;
- if (styleElement) {
- styleElement.parentNode.removeChild(styleElement);
- styleElement = this.styleElement = null;
- }
- }
- };
- FontLoader.prototype.bind = function fontLoaderBind(fonts, callback) {
- for (var i = 0, ii = fonts.length; i < ii; i++) {
- var font = fonts[i];
- if (font.attached) {
- continue;
- }
- font.attached = true;
- var rule = font.createFontFaceRule();
- if (rule) {
- this.insertRule(rule);
- }
- }
- setTimeout(callback);
- };
- var IsEvalSupportedCached = {
- get value() {
- return shadow(this, 'value', sharedUtil.isEvalSupported());
- }
- };
- var FontFaceObject = function FontFaceObjectClosure() {
- function FontFaceObject(translatedData, options) {
- this.compiledGlyphs = Object.create(null);
- // importing translated data
- for (var i in translatedData) {
- this[i] = translatedData[i];
- }
- this.options = options;
- }
- FontFaceObject.prototype = {
- createNativeFontFace: function FontFaceObject_createNativeFontFace() {
- throw new Error('Not implemented: createNativeFontFace');
- },
- createFontFaceRule: function FontFaceObject_createFontFaceRule() {
- if (!this.data) {
- return null;
- }
- if (this.options.disableFontFace) {
- this.disableFontFace = true;
- return null;
- }
- var data = bytesToString(new Uint8Array(this.data));
- var fontName = this.loadedName;
- // Add the font-face rule to the document
- var url = 'url(data:' + this.mimetype + ';base64,' + btoa(data) + ');';
- var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}';
- if (this.options.fontRegistry) {
- this.options.fontRegistry.registerFont(this, url);
- }
- return rule;
- },
- getPathGenerator: function FontFaceObject_getPathGenerator(objs, character) {
- if (!(character in this.compiledGlyphs)) {
- var cmds = objs.get(this.loadedName + '_path_' + character);
- var current, i, len;
- // If we can, compile cmds into JS for MAXIMUM SPEED
- if (this.options.isEvalSupported && IsEvalSupportedCached.value) {
- var args, js = '';
- for (i = 0, len = cmds.length; i < len; i++) {
- current = cmds[i];
- if (current.args !== undefined) {
- args = current.args.join(',');
- } else {
- args = '';
- }
- js += 'c.' + current.cmd + '(' + args + ');\n';
- }
- this.compiledGlyphs[character] = new Function('c', 'size', js);
- } else {
- // But fall back on using Function.prototype.apply() if we're
- // blocked from using eval() for whatever reason (like CSP policies)
- this.compiledGlyphs[character] = function (c, size) {
- for (i = 0, len = cmds.length; i < len; i++) {
- current = cmds[i];
- if (current.cmd === 'scale') {
- current.args = [
- size,
- -size
- ];
- }
- c[current.cmd].apply(c, current.args);
- }
- };
- }
- }
- return this.compiledGlyphs[character];
- }
- };
- return FontFaceObject;
- }();
- exports.FontFaceObject = FontFaceObject;
- exports.FontLoader = FontLoader;
- }));
- (function (root, factory) {
- factory(root.pdfjsDisplayMetadata = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- var error = sharedUtil.error;
- function fixMetadata(meta) {
- return meta.replace(/>\\376\\377([^<]+)/g, function (all, codes) {
- var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g, function (code, d1, d2, d3) {
- return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
- });
- var chars = '';
- for (var i = 0; i < bytes.length; i += 2) {
- var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
- chars += code >= 32 && code < 127 && code !== 60 && code !== 62 && code !== 38 && false ? String.fromCharCode(code) : '&#x' + (0x10000 + code).toString(16).substring(1) + ';';
- }
- return '>' + chars;
- });
- }
- function Metadata(meta) {
- if (typeof meta === 'string') {
- // Ghostscript produces invalid metadata
- meta = fixMetadata(meta);
- var parser = new DOMParser();
- meta = parser.parseFromString(meta, 'application/xml');
- } else if (!(meta instanceof Document)) {
- error('Metadata: Invalid metadata object');
- }
- this.metaDocument = meta;
- this.metadata = Object.create(null);
- this.parse();
- }
- Metadata.prototype = {
- parse: function Metadata_parse() {
- var doc = this.metaDocument;
- var rdf = doc.documentElement;
- if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
- // Wrapped in <xmpmeta>
- rdf = rdf.firstChild;
- while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
- rdf = rdf.nextSibling;
- }
- }
- var nodeName = rdf ? rdf.nodeName.toLowerCase() : null;
- if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes()) {
- return;
- }
- var children = rdf.childNodes, desc, entry, name, i, ii, length, iLength;
- for (i = 0, length = children.length; i < length; i++) {
- desc = children[i];
- if (desc.nodeName.toLowerCase() !== 'rdf:description') {
- continue;
- }
- for (ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
- if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text') {
- entry = desc.childNodes[ii];
- name = entry.nodeName.toLowerCase();
- this.metadata[name] = entry.textContent.trim();
- }
- }
- }
- },
- get: function Metadata_get(name) {
- return this.metadata[name] || null;
- },
- has: function Metadata_has(name) {
- return typeof this.metadata[name] !== 'undefined';
- }
- };
- exports.Metadata = Metadata;
- }));
- (function (root, factory) {
- factory(root.pdfjsDisplaySVG = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- }));
- (function (root, factory) {
- factory(root.pdfjsDisplayAnnotationLayer = {}, root.pdfjsSharedUtil, root.pdfjsDisplayDOMUtils);
- }(this, function (exports, sharedUtil, displayDOMUtils) {
- var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType;
- var AnnotationType = sharedUtil.AnnotationType;
- var Util = sharedUtil.Util;
- var addLinkAttributes = displayDOMUtils.addLinkAttributes;
- var LinkTarget = displayDOMUtils.LinkTarget;
- var getFilenameFromUrl = displayDOMUtils.getFilenameFromUrl;
- var warn = sharedUtil.warn;
- var CustomStyle = displayDOMUtils.CustomStyle;
- var getDefaultSetting = displayDOMUtils.getDefaultSetting;
- /**
- * @typedef {Object} AnnotationElementParameters
- * @property {Object} data
- * @property {HTMLDivElement} layer
- * @property {PDFPage} page
- * @property {PageViewport} viewport
- * @property {IPDFLinkService} linkService
- * @property {DownloadManager} downloadManager
- * @property {string} imageResourcesPath
- * @property {boolean} renderInteractiveForms
- */
- /**
- * @class
- * @alias AnnotationElementFactory
- */
- function AnnotationElementFactory() {
- }
- AnnotationElementFactory.prototype = /** @lends AnnotationElementFactory.prototype */
- {
- /**
- * @param {AnnotationElementParameters} parameters
- * @returns {AnnotationElement}
- */
- create: function AnnotationElementFactory_create(parameters) {
- var subtype = parameters.data.annotationType;
- switch (subtype) {
- case AnnotationType.LINK:
- return new LinkAnnotationElement(parameters);
- case AnnotationType.TEXT:
- return new TextAnnotationElement(parameters);
- case AnnotationType.WIDGET:
- var fieldType = parameters.data.fieldType;
- switch (fieldType) {
- case 'Tx':
- return new TextWidgetAnnotationElement(parameters);
- case 'Ch':
- return new ChoiceWidgetAnnotationElement(parameters);
- }
- return new WidgetAnnotationElement(parameters);
- case AnnotationType.POPUP:
- return new PopupAnnotationElement(parameters);
- case AnnotationType.HIGHLIGHT:
- return new HighlightAnnotationElement(parameters);
- case AnnotationType.UNDERLINE:
- return new UnderlineAnnotationElement(parameters);
- case AnnotationType.SQUIGGLY:
- return new SquigglyAnnotationElement(parameters);
- case AnnotationType.STRIKEOUT:
- return new StrikeOutAnnotationElement(parameters);
- case AnnotationType.FILEATTACHMENT:
- return new FileAttachmentAnnotationElement(parameters);
- default:
- return new AnnotationElement(parameters);
- }
- }
- };
- /**
- * @class
- * @alias AnnotationElement
- */
- var AnnotationElement = function AnnotationElementClosure() {
- function AnnotationElement(parameters, isRenderable) {
- this.isRenderable = isRenderable || false;
- this.data = parameters.data;
- this.layer = parameters.layer;
- this.page = parameters.page;
- this.viewport = parameters.viewport;
- this.linkService = parameters.linkService;
- this.downloadManager = parameters.downloadManager;
- this.imageResourcesPath = parameters.imageResourcesPath;
- this.renderInteractiveForms = parameters.renderInteractiveForms;
- if (isRenderable) {
- this.container = this._createContainer();
- }
- }
- AnnotationElement.prototype = /** @lends AnnotationElement.prototype */
- {
- /**
- * Create an empty container for the annotation's HTML element.
- *
- * @private
- * @memberof AnnotationElement
- * @returns {HTMLSectionElement}
- */
- _createContainer: function AnnotationElement_createContainer() {
- var data = this.data, page = this.page, viewport = this.viewport;
- var container = document.createElement('section');
- var width = data.rect[2] - data.rect[0];
- var height = data.rect[3] - data.rect[1];
- container.setAttribute('data-annotation-id', data.id);
- // Do *not* modify `data.rect`, since that will corrupt the annotation
- // position on subsequent calls to `_createContainer` (see issue 6804).
- var rect = Util.normalizeRect([
- data.rect[0],
- page.view[3] - data.rect[1] + page.view[1],
- data.rect[2],
- page.view[3] - data.rect[3] + page.view[1]
- ]);
- CustomStyle.setProp('transform', container, 'matrix(' + viewport.transform.join(',') + ')');
- CustomStyle.setProp('transformOrigin', container, -rect[0] + 'px ' + -rect[1] + 'px');
- if (data.borderStyle.width > 0) {
- container.style.borderWidth = data.borderStyle.width + 'px';
- if (data.borderStyle.style !== AnnotationBorderStyleType.UNDERLINE) {
- // Underline styles only have a bottom border, so we do not need
- // to adjust for all borders. This yields a similar result as
- // Adobe Acrobat/Reader.
- width = width - 2 * data.borderStyle.width;
- height = height - 2 * data.borderStyle.width;
- }
- var horizontalRadius = data.borderStyle.horizontalCornerRadius;
- var verticalRadius = data.borderStyle.verticalCornerRadius;
- if (horizontalRadius > 0 || verticalRadius > 0) {
- var radius = horizontalRadius + 'px / ' + verticalRadius + 'px';
- CustomStyle.setProp('borderRadius', container, radius);
- }
- switch (data.borderStyle.style) {
- case AnnotationBorderStyleType.SOLID:
- container.style.borderStyle = 'solid';
- break;
- case AnnotationBorderStyleType.DASHED:
- container.style.borderStyle = 'dashed';
- break;
- case AnnotationBorderStyleType.BEVELED:
- warn('Unimplemented border style: beveled');
- break;
- case AnnotationBorderStyleType.INSET:
- warn('Unimplemented border style: inset');
- break;
- case AnnotationBorderStyleType.UNDERLINE:
- container.style.borderBottomStyle = 'solid';
- break;
- default:
- break;
- }
- if (data.color) {
- container.style.borderColor = Util.makeCssRgb(data.color[0] | 0, data.color[1] | 0, data.color[2] | 0);
- } else {
- // Transparent (invisible) border, so do not draw it at all.
- container.style.borderWidth = 0;
- }
- }
- container.style.left = rect[0] + 'px';
- container.style.top = rect[1] + 'px';
- container.style.width = width + 'px';
- container.style.height = height + 'px';
- return container;
- },
- /**
- * Create a popup for the annotation's HTML element. This is used for
- * annotations that do not have a Popup entry in the dictionary, but
- * are of a type that works with popups (such as Highlight annotations).
- *
- * @private
- * @param {HTMLSectionElement} container
- * @param {HTMLDivElement|HTMLImageElement|null} trigger
- * @param {Object} data
- * @memberof AnnotationElement
- */
- _createPopup: function AnnotationElement_createPopup(container, trigger, data) {
- // If no trigger element is specified, create it.
- if (!trigger) {
- trigger = document.createElement('div');
- trigger.style.height = container.style.height;
- trigger.style.width = container.style.width;
- container.appendChild(trigger);
- }
- var popupElement = new PopupElement({
- container: container,
- trigger: trigger,
- color: data.color,
- title: data.title,
- contents: data.contents,
- hideWrapper: true
- });
- var popup = popupElement.render();
- // Position the popup next to the annotation's container.
- popup.style.left = container.style.width;
- container.appendChild(popup);
- },
- /**
- * Render the annotation's HTML element in the empty container.
- *
- * @public
- * @memberof AnnotationElement
- */
- render: function AnnotationElement_render() {
- throw new Error('Abstract method AnnotationElement.render called');
- }
- };
- return AnnotationElement;
- }();
- /**
- * @class
- * @alias LinkAnnotationElement
- */
- var LinkAnnotationElement = function LinkAnnotationElementClosure() {
- function LinkAnnotationElement(parameters) {
- AnnotationElement.call(this, parameters, true);
- }
- Util.inherit(LinkAnnotationElement, AnnotationElement, {
- /**
- * Render the link annotation's HTML element in the empty container.
- *
- * @public
- * @memberof LinkAnnotationElement
- * @returns {HTMLSectionElement}
- */
- render: function LinkAnnotationElement_render() {
- this.container.className = 'linkAnnotation';
- var link = document.createElement('a');
- addLinkAttributes(link, {
- url: this.data.url,
- target: this.data.newWindow ? LinkTarget.BLANK : undefined
- });
- if (!this.data.url) {
- if (this.data.action) {
- this._bindNamedAction(link, this.data.action);
- } else {
- this._bindLink(link, this.data.dest);
- }
- }
- this.container.appendChild(link);
- return this.container;
- },
- /**
- * Bind internal links to the link element.
- *
- * @private
- * @param {Object} link
- * @param {Object} destination
- * @memberof LinkAnnotationElement
- */
- _bindLink: function LinkAnnotationElement_bindLink(link, destination) {
- var self = this;
- link.href = this.linkService.getDestinationHash(destination);
- link.onclick = function () {
- if (destination) {
- self.linkService.navigateTo(destination);
- }
- return false;
- };
- if (destination) {
- link.className = 'internalLink';
- }
- },
- /**
- * Bind named actions to the link element.
- *
- * @private
- * @param {Object} link
- * @param {Object} action
- * @memberof LinkAnnotationElement
- */
- _bindNamedAction: function LinkAnnotationElement_bindNamedAction(link, action) {
- var self = this;
- link.href = this.linkService.getAnchorUrl('');
- link.onclick = function () {
- self.linkService.executeNamedAction(action);
- return false;
- };
- link.className = 'internalLink';
- }
- });
- return LinkAnnotationElement;
- }();
- /**
- * @class
- * @alias TextAnnotationElement
- */
- var TextAnnotationElement = function TextAnnotationElementClosure() {
- function TextAnnotationElement(parameters) {
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- AnnotationElement.call(this, parameters, isRenderable);
- }
- Util.inherit(TextAnnotationElement, AnnotationElement, {
- /**
- * Render the text annotation's HTML element in the empty container.
- *
- * @public
- * @memberof TextAnnotationElement
- * @returns {HTMLSectionElement}
- */
- render: function TextAnnotationElement_render() {
- this.container.className = 'textAnnotation';
- var image = document.createElement('img');
- image.style.height = this.container.style.height;
- image.style.width = this.container.style.width;
- image.src = this.imageResourcesPath + 'annotation-' + this.data.name.toLowerCase() + '.svg';
- image.alt = '[{{type}} Annotation]';
- image.dataset.l10nId = 'text_annotation_type';
- image.dataset.l10nArgs = JSON.stringify({ type: this.data.name });
- if (!this.data.hasPopup) {
- this._createPopup(this.container, image, this.data);
- }
- this.container.appendChild(image);
- return this.container;
- }
- });
- return TextAnnotationElement;
- }();
- /**
- * @class
- * @alias WidgetAnnotationElement
- */
- var WidgetAnnotationElement = function WidgetAnnotationElementClosure() {
- function WidgetAnnotationElement(parameters, isRenderable) {
- AnnotationElement.call(this, parameters, isRenderable);
- }
- Util.inherit(WidgetAnnotationElement, AnnotationElement, {
- /**
- * Render the widget annotation's HTML element in the empty container.
- *
- * @public
- * @memberof WidgetAnnotationElement
- * @returns {HTMLSectionElement}
- */
- render: function WidgetAnnotationElement_render() {
- // Show only the container for unsupported field types.
- return this.container;
- }
- });
- return WidgetAnnotationElement;
- }();
- /**
- * @class
- * @alias TextWidgetAnnotationElement
- */
- var TextWidgetAnnotationElement = function TextWidgetAnnotationElementClosure() {
- var TEXT_ALIGNMENT = [
- 'left',
- 'center',
- 'right'
- ];
- function TextWidgetAnnotationElement(parameters) {
- var isRenderable = parameters.renderInteractiveForms || !parameters.data.hasAppearance && !!parameters.data.fieldValue;
- WidgetAnnotationElement.call(this, parameters, isRenderable);
- }
- Util.inherit(TextWidgetAnnotationElement, WidgetAnnotationElement, {
- /**
- * Render the text widget annotation's HTML element in the empty container.
- *
- * @public
- * @memberof TextWidgetAnnotationElement
- * @returns {HTMLSectionElement}
- */
- render: function TextWidgetAnnotationElement_render() {
- this.container.className = 'textWidgetAnnotation';
- var element = null;
- if (this.renderInteractiveForms) {
- // NOTE: We cannot set the values using `element.value` below, since it
- // prevents the AnnotationLayer rasterizer in `test/driver.js`
- // from parsing the elements correctly for the reference tests.
- if (this.data.multiLine) {
- element = document.createElement('textarea');
- element.textContent = this.data.fieldValue;
- } else {
- element = document.createElement('input');
- element.type = 'text';
- element.setAttribute('value', this.data.fieldValue);
- }
- element.disabled = this.data.readOnly;
- if (this.data.maxLen !== null) {
- element.maxLength = this.data.maxLen;
- }
- if (this.data.comb) {
- var fieldWidth = this.data.rect[2] - this.data.rect[0];
- var combWidth = fieldWidth / this.data.maxLen;
- element.classList.add('comb');
- element.style.letterSpacing = 'calc(' + combWidth + 'px - 1ch)';
- }
- } else {
- element = document.createElement('div');
- element.textContent = this.data.fieldValue;
- element.style.verticalAlign = 'middle';
- element.style.display = 'table-cell';
- var font = null;
- if (this.data.fontRefName) {
- font = this.page.commonObjs.getData(this.data.fontRefName);
- }
- this._setTextStyle(element, font);
- }
- if (this.data.textAlignment !== null) {
- element.style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment];
- }
- this.container.appendChild(element);
- return this.container;
- },
- /**
- * Apply text styles to the text in the element.
- *
- * @private
- * @param {HTMLDivElement} element
- * @param {Object} font
- * @memberof TextWidgetAnnotationElement
- */
- _setTextStyle: function TextWidgetAnnotationElement_setTextStyle(element, font) {
- // TODO: This duplicates some of the logic in CanvasGraphics.setFont().
- var style = element.style;
- style.fontSize = this.data.fontSize + 'px';
- style.direction = this.data.fontDirection < 0 ? 'rtl' : 'ltr';
- if (!font) {
- return;
- }
- style.fontWeight = font.black ? font.bold ? '900' : 'bold' : font.bold ? 'bold' : 'normal';
- style.fontStyle = font.italic ? 'italic' : 'normal';
- // Use a reasonable default font if the font doesn't specify a fallback.
- var fontFamily = font.loadedName ? '"' + font.loadedName + '", ' : '';
- var fallbackName = font.fallbackName || 'Helvetica, sans-serif';
- style.fontFamily = fontFamily + fallbackName;
- }
- });
- return TextWidgetAnnotationElement;
- }();
- /**
- * @class
- * @alias ChoiceWidgetAnnotationElement
- */
- var ChoiceWidgetAnnotationElement = function ChoiceWidgetAnnotationElementClosure() {
- function ChoiceWidgetAnnotationElement(parameters) {
- WidgetAnnotationElement.call(this, parameters, parameters.renderInteractiveForms);
- }
- Util.inherit(ChoiceWidgetAnnotationElement, WidgetAnnotationElement, {
- /**
- * Render the choice widget annotation's HTML element in the empty
- * container.
- *
- * @public
- * @memberof ChoiceWidgetAnnotationElement
- * @returns {HTMLSectionElement}
- */
- render: function ChoiceWidgetAnnotationElement_render() {
- this.container.className = 'choiceWidgetAnnotation';
- var selectElement = document.createElement('select');
- selectElement.disabled = this.data.readOnly;
- if (!this.data.combo) {
- // List boxes have a size and (optionally) multiple selection.
- selectElement.size = this.data.options.length;
- if (this.data.multiSelect) {
- selectElement.multiple = true;
- }
- }
- // Insert the options into the choice field.
- for (var i = 0, ii = this.data.options.length; i < ii; i++) {
- var option = this.data.options[i];
- var optionElement = document.createElement('option');
- optionElement.textContent = option.displayValue;
- optionElement.value = option.exportValue;
- if (this.data.fieldValue.indexOf(option.displayValue) >= 0) {
- optionElement.setAttribute('selected', true);
- }
- selectElement.appendChild(optionElement);
- }
- this.container.appendChild(selectElement);
- return this.container;
- }
- });
- return ChoiceWidgetAnnotationElement;
- }();
- /**
- * @class
- * @alias PopupAnnotationElement
- */
- var PopupAnnotationElement = function PopupAnnotationElementClosure() {
- function PopupAnnotationElement(parameters) {
- var isRenderable = !!(parameters.data.title || parameters.data.contents);
- AnnotationElement.call(this, parameters, isRenderable);
- }
- Util.inherit(PopupAnnotationElement, AnnotationElement, {
- /**
- * Render the popup annotation's HTML element in the empty container.
- *
- * @public
- * @memberof PopupAnnotationElement
- * @returns {HTMLSectionElement}
- */
- render: function PopupAnnotationElement_render() {
- this.container.className = 'popupAnnotation';
- var selector = '[data-annotation-id="' + this.data.parentId + '"]';
- var parentElement = this.layer.querySelector(selector);
- if (!parentElement) {
- return this.container;
- }
- var popup = new PopupElement({
- container: this.container,
- trigger: parentElement,
- color: this.data.color,
- title: this.data.title,
- contents: this.data.contents
- });
- // Position the popup next to the parent annotation's container.
- // PDF viewers ignore a popup annotation's rectangle.
- var parentLeft = parseFloat(parentElement.style.left);
- var parentWidth = parseFloat(parentElement.style.width);
- CustomStyle.setProp('transformOrigin', this.container, -(parentLeft + parentWidth) + 'px -' + parentElement.style.top);
- this.container.style.left = parentLeft + parentWidth + 'px';
- this.container.appendChild(popup.render());
- return this.container;
- }
- });
- return PopupAnnotationElement;
- }();
- /**
- * @class
- * @alias PopupElement
- */
- var PopupElement = function PopupElementClosure() {
- var BACKGROUND_ENLIGHT = 0.7;
- function PopupElement(parameters) {
- this.container = parameters.container;
- this.trigger = parameters.trigger;
- this.color = parameters.color;
- this.title = parameters.title;
- this.contents = parameters.contents;
- this.hideWrapper = parameters.hideWrapper || false;
- this.pinned = false;
- }
- PopupElement.prototype = /** @lends PopupElement.prototype */
- {
- /**
- * Render the popup's HTML element.
- *
- * @public
- * @memberof PopupElement
- * @returns {HTMLSectionElement}
- */
- render: function PopupElement_render() {
- var wrapper = document.createElement('div');
- wrapper.className = 'popupWrapper';
- // For Popup annotations we hide the entire section because it contains
- // only the popup. However, for Text annotations without a separate Popup
- // annotation, we cannot hide the entire container as the image would
- // disappear too. In that special case, hiding the wrapper suffices.
- this.hideElement = this.hideWrapper ? wrapper : this.container;
- this.hideElement.setAttribute('hidden', true);
- var popup = document.createElement('div');
- popup.className = 'popup';
- var color = this.color;
- if (color) {
- // Enlighten the color.
- var r = BACKGROUND_ENLIGHT * (255 - color[0]) + color[0];
- var g = BACKGROUND_ENLIGHT * (255 - color[1]) + color[1];
- var b = BACKGROUND_ENLIGHT * (255 - color[2]) + color[2];
- popup.style.backgroundColor = Util.makeCssRgb(r | 0, g | 0, b | 0);
- }
- var contents = this._formatContents(this.contents);
- var title = document.createElement('h1');
- title.textContent = this.title;
- // Attach the event listeners to the trigger element.
- this.trigger.addEventListener('click', this._toggle.bind(this));
- this.trigger.addEventListener('mouseover', this._show.bind(this, false));
- this.trigger.addEventListener('mouseout', this._hide.bind(this, false));
- popup.addEventListener('click', this._hide.bind(this, true));
- popup.appendChild(title);
- popup.appendChild(contents);
- wrapper.appendChild(popup);
- return wrapper;
- },
- /**
- * Format the contents of the popup by adding newlines where necessary.
- *
- * @private
- * @param {string} contents
- * @memberof PopupElement
- * @returns {HTMLParagraphElement}
- */
- _formatContents: function PopupElement_formatContents(contents) {
- var p = document.createElement('p');
- var lines = contents.split(/(?:\r\n?|\n)/);
- for (var i = 0, ii = lines.length; i < ii; ++i) {
- var line = lines[i];
- p.appendChild(document.createTextNode(line));
- if (i < ii - 1) {
- p.appendChild(document.createElement('br'));
- }
- }
- return p;
- },
- /**
- * Toggle the visibility of the popup.
- *
- * @private
- * @memberof PopupElement
- */
- _toggle: function PopupElement_toggle() {
- if (this.pinned) {
- this._hide(true);
- } else {
- this._show(true);
- }
- },
- /**
- * Show the popup.
- *
- * @private
- * @param {boolean} pin
- * @memberof PopupElement
- */
- _show: function PopupElement_show(pin) {
- if (pin) {
- this.pinned = true;
- }
- if (this.hideElement.hasAttribute('hidden')) {
- this.hideElement.removeAttribute('hidden');
- this.container.style.zIndex += 1;
- }
- },
- /**
- * Hide the popup.
- *
- * @private
- * @param {boolean} unpin
- * @memberof PopupElement
- */
- _hide: function PopupElement_hide(unpin) {
- if (unpin) {
- this.pinned = false;
- }
- if (!this.hideElement.hasAttribute('hidden') && !this.pinned) {
- this.hideElement.setAttribute('hidden', true);
- this.container.style.zIndex -= 1;
- }
- }
- };
- return PopupElement;
- }();
- /**
- * @class
- * @alias HighlightAnnotationElement
- */
- var HighlightAnnotationElement = function HighlightAnnotationElementClosure() {
- function HighlightAnnotationElement(parameters) {
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- AnnotationElement.call(this, parameters, isRenderable);
- }
- Util.inherit(HighlightAnnotationElement, AnnotationElement, {
- /**
- * Render the highlight annotation's HTML element in the empty container.
- *
- * @public
- * @memberof HighlightAnnotationElement
- * @returns {HTMLSectionElement}
- */
- render: function HighlightAnnotationElement_render() {
- this.container.className = 'highlightAnnotation';
- if (!this.data.hasPopup) {
- this._createPopup(this.container, null, this.data);
- }
- return this.container;
- }
- });
- return HighlightAnnotationElement;
- }();
- /**
- * @class
- * @alias UnderlineAnnotationElement
- */
- var UnderlineAnnotationElement = function UnderlineAnnotationElementClosure() {
- function UnderlineAnnotationElement(parameters) {
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- AnnotationElement.call(this, parameters, isRenderable);
- }
- Util.inherit(UnderlineAnnotationElement, AnnotationElement, {
- /**
- * Render the underline annotation's HTML element in the empty container.
- *
- * @public
- * @memberof UnderlineAnnotationElement
- * @returns {HTMLSectionElement}
- */
- render: function UnderlineAnnotationElement_render() {
- this.container.className = 'underlineAnnotation';
- if (!this.data.hasPopup) {
- this._createPopup(this.container, null, this.data);
- }
- return this.container;
- }
- });
- return UnderlineAnnotationElement;
- }();
- /**
- * @class
- * @alias SquigglyAnnotationElement
- */
- var SquigglyAnnotationElement = function SquigglyAnnotationElementClosure() {
- function SquigglyAnnotationElement(parameters) {
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- AnnotationElement.call(this, parameters, isRenderable);
- }
- Util.inherit(SquigglyAnnotationElement, AnnotationElement, {
- /**
- * Render the squiggly annotation's HTML element in the empty container.
- *
- * @public
- * @memberof SquigglyAnnotationElement
- * @returns {HTMLSectionElement}
- */
- render: function SquigglyAnnotationElement_render() {
- this.container.className = 'squigglyAnnotation';
- if (!this.data.hasPopup) {
- this._createPopup(this.container, null, this.data);
- }
- return this.container;
- }
- });
- return SquigglyAnnotationElement;
- }();
- /**
- * @class
- * @alias StrikeOutAnnotationElement
- */
- var StrikeOutAnnotationElement = function StrikeOutAnnotationElementClosure() {
- function StrikeOutAnnotationElement(parameters) {
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- AnnotationElement.call(this, parameters, isRenderable);
- }
- Util.inherit(StrikeOutAnnotationElement, AnnotationElement, {
- /**
- * Render the strikeout annotation's HTML element in the empty container.
- *
- * @public
- * @memberof StrikeOutAnnotationElement
- * @returns {HTMLSectionElement}
- */
- render: function StrikeOutAnnotationElement_render() {
- this.container.className = 'strikeoutAnnotation';
- if (!this.data.hasPopup) {
- this._createPopup(this.container, null, this.data);
- }
- return this.container;
- }
- });
- return StrikeOutAnnotationElement;
- }();
- /**
- * @class
- * @alias FileAttachmentAnnotationElement
- */
- var FileAttachmentAnnotationElement = function FileAttachmentAnnotationElementClosure() {
- function FileAttachmentAnnotationElement(parameters) {
- AnnotationElement.call(this, parameters, true);
- this.filename = getFilenameFromUrl(parameters.data.file.filename);
- this.content = parameters.data.file.content;
- }
- Util.inherit(FileAttachmentAnnotationElement, AnnotationElement, {
- /**
- * Render the file attachment annotation's HTML element in the empty
- * container.
- *
- * @public
- * @memberof FileAttachmentAnnotationElement
- * @returns {HTMLSectionElement}
- */
- render: function FileAttachmentAnnotationElement_render() {
- this.container.className = 'fileAttachmentAnnotation';
- var trigger = document.createElement('div');
- trigger.style.height = this.container.style.height;
- trigger.style.width = this.container.style.width;
- trigger.addEventListener('dblclick', this._download.bind(this));
- if (!this.data.hasPopup && (this.data.title || this.data.contents)) {
- this._createPopup(this.container, trigger, this.data);
- }
- this.container.appendChild(trigger);
- return this.container;
- },
- /**
- * Download the file attachment associated with this annotation.
- *
- * @private
- * @memberof FileAttachmentAnnotationElement
- */
- _download: function FileAttachmentAnnotationElement_download() {
- if (!this.downloadManager) {
- warn('Download cannot be started due to unavailable download manager');
- return;
- }
- this.downloadManager.downloadData(this.content, this.filename, '');
- }
- });
- return FileAttachmentAnnotationElement;
- }();
- /**
- * @typedef {Object} AnnotationLayerParameters
- * @property {PageViewport} viewport
- * @property {HTMLDivElement} div
- * @property {Array} annotations
- * @property {PDFPage} page
- * @property {IPDFLinkService} linkService
- * @property {string} imageResourcesPath
- * @property {boolean} renderInteractiveForms
- */
- /**
- * @class
- * @alias AnnotationLayer
- */
- var AnnotationLayer = function AnnotationLayerClosure() {
- return {
- /**
- * Render a new annotation layer with all annotation elements.
- *
- * @public
- * @param {AnnotationLayerParameters} parameters
- * @memberof AnnotationLayer
- */
- render: function AnnotationLayer_render(parameters) {
- var annotationElementFactory = new AnnotationElementFactory();
- for (var i = 0, ii = parameters.annotations.length; i < ii; i++) {
- var data = parameters.annotations[i];
- if (!data) {
- continue;
- }
- var properties = {
- data: data,
- layer: parameters.div,
- page: parameters.page,
- viewport: parameters.viewport,
- linkService: parameters.linkService,
- downloadManager: parameters.downloadManager,
- imageResourcesPath: parameters.imageResourcesPath || getDefaultSetting('imageResourcesPath'),
- renderInteractiveForms: parameters.renderInteractiveForms || false
- };
- var element = annotationElementFactory.create(properties);
- if (element.isRenderable) {
- parameters.div.appendChild(element.render());
- }
- }
- },
- /**
- * Update the annotation elements on existing annotation layer.
- *
- * @public
- * @param {AnnotationLayerParameters} parameters
- * @memberof AnnotationLayer
- */
- update: function AnnotationLayer_update(parameters) {
- for (var i = 0, ii = parameters.annotations.length; i < ii; i++) {
- var data = parameters.annotations[i];
- var element = parameters.div.querySelector('[data-annotation-id="' + data.id + '"]');
- if (element) {
- CustomStyle.setProp('transform', element, 'matrix(' + parameters.viewport.transform.join(',') + ')');
- }
- }
- parameters.div.removeAttribute('hidden');
- }
- };
- }();
- exports.AnnotationLayer = AnnotationLayer;
- }));
- (function (root, factory) {
- factory(root.pdfjsDisplayTextLayer = {}, root.pdfjsSharedUtil, root.pdfjsDisplayDOMUtils);
- }(this, function (exports, sharedUtil, displayDOMUtils) {
- var Util = sharedUtil.Util;
- var createPromiseCapability = sharedUtil.createPromiseCapability;
- var CustomStyle = displayDOMUtils.CustomStyle;
- var getDefaultSetting = displayDOMUtils.getDefaultSetting;
- /**
- * Text layer render parameters.
- *
- * @typedef {Object} TextLayerRenderParameters
- * @property {TextContent} textContent - Text content to render (the object is
- * returned by the page's getTextContent() method).
- * @property {HTMLElement} container - HTML element that will contain text runs.
- * @property {PageViewport} viewport - The target viewport to properly
- * layout the text runs.
- * @property {Array} textDivs - (optional) HTML elements that are correspond
- * the text items of the textContent input. This is output and shall be
- * initially be set to empty array.
- * @property {number} timeout - (optional) Delay in milliseconds before
- * rendering of the text runs occurs.
- * @property {boolean} enhanceTextSelection - (optional) Whether to turn on the
- * text selection enhancement.
- */
- var renderTextLayer = function renderTextLayerClosure() {
- var MAX_TEXT_DIVS_TO_RENDER = 100000;
- var NonWhitespaceRegexp = /\S/;
- function isAllWhitespace(str) {
- return !NonWhitespaceRegexp.test(str);
- }
- // Text layers may contain many thousand div's, and using `styleBuf` avoids
- // creating many intermediate strings when building their 'style' properties.
- var styleBuf = [
- 'left: ',
- 0,
- 'px; top: ',
- 0,
- 'px; font-size: ',
- 0,
- 'px; font-family: ',
- '',
- ';'
- ];
- function appendText(task, geom, styles) {
- // Initialize all used properties to keep the caches monomorphic.
- var textDiv = document.createElement('div');
- var textDivProperties = {
- style: null,
- angle: 0,
- canvasWidth: 0,
- isWhitespace: false,
- originalTransform: null,
- paddingBottom: 0,
- paddingLeft: 0,
- paddingRight: 0,
- paddingTop: 0,
- scale: 1
- };
- task._textDivs.push(textDiv);
- if (isAllWhitespace(geom.str)) {
- textDivProperties.isWhitespace = true;
- task._textDivProperties.set(textDiv, textDivProperties);
- return;
- }
- var tx = Util.transform(task._viewport.transform, geom.transform);
- var angle = Math.atan2(tx[1], tx[0]);
- var style = styles[geom.fontName];
- if (style.vertical) {
- angle += Math.PI / 2;
- }
- var fontHeight = Math.sqrt(tx[2] * tx[2] + tx[3] * tx[3]);
- var fontAscent = fontHeight;
- if (style.ascent) {
- fontAscent = style.ascent * fontAscent;
- } else if (style.descent) {
- fontAscent = (1 + style.descent) * fontAscent;
- }
- var left;
- var top;
- if (angle === 0) {
- left = tx[4];
- top = tx[5] - fontAscent;
- } else {
- left = tx[4] + fontAscent * Math.sin(angle);
- top = tx[5] - fontAscent * Math.cos(angle);
- }
- styleBuf[1] = left;
- styleBuf[3] = top;
- styleBuf[5] = fontHeight;
- styleBuf[7] = style.fontFamily;
- textDivProperties.style = styleBuf.join('');
- textDiv.setAttribute('style', textDivProperties.style);
- textDiv.textContent = geom.str;
- // |fontName| is only used by the Font Inspector. This test will succeed
- // when e.g. the Font Inspector is off but the Stepper is on, but it's
- // not worth the effort to do a more accurate test. We only use `dataset`
- // here to make the font name available for the debugger.
- if (getDefaultSetting('pdfBug')) {
- textDiv.dataset.fontName = geom.fontName;
- }
- if (angle !== 0) {
- textDivProperties.angle = angle * (180 / Math.PI);
- }
- // We don't bother scaling single-char text divs, because it has very
- // little effect on text highlighting. This makes scrolling on docs with
- // lots of such divs a lot faster.
- if (geom.str.length > 1) {
- if (style.vertical) {
- textDivProperties.canvasWidth = geom.height * task._viewport.scale;
- } else {
- textDivProperties.canvasWidth = geom.width * task._viewport.scale;
- }
- }
- task._textDivProperties.set(textDiv, textDivProperties);
- if (task._enhanceTextSelection) {
- var angleCos = 1, angleSin = 0;
- if (angle !== 0) {
- angleCos = Math.cos(angle);
- angleSin = Math.sin(angle);
- }
- var divWidth = (style.vertical ? geom.height : geom.width) * task._viewport.scale;
- var divHeight = fontHeight;
- var m, b;
- if (angle !== 0) {
- m = [
- angleCos,
- angleSin,
- -angleSin,
- angleCos,
- left,
- top
- ];
- b = Util.getAxialAlignedBoundingBox([
- 0,
- 0,
- divWidth,
- divHeight
- ], m);
- } else {
- b = [
- left,
- top,
- left + divWidth,
- top + divHeight
- ];
- }
- task._bounds.push({
- left: b[0],
- top: b[1],
- right: b[2],
- bottom: b[3],
- div: textDiv,
- size: [
- divWidth,
- divHeight
- ],
- m: m
- });
- }
- }
- function render(task) {
- if (task._canceled) {
- return;
- }
- var textLayerFrag = task._container;
- var textDivs = task._textDivs;
- var capability = task._capability;
- var textDivsLength = textDivs.length;
- // No point in rendering many divs as it would make the browser
- // unusable even after the divs are rendered.
- if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {
- task._renderingDone = true;
- capability.resolve();
- return;
- }
- var canvas = document.createElement('canvas');
- canvas.mozOpaque = true;
- var ctx = canvas.getContext('2d', { alpha: false });
- var lastFontSize;
- var lastFontFamily;
- for (var i = 0; i < textDivsLength; i++) {
- var textDiv = textDivs[i];
- var textDivProperties = task._textDivProperties.get(textDiv);
- if (textDivProperties.isWhitespace) {
- continue;
- }
- var fontSize = textDiv.style.fontSize;
- var fontFamily = textDiv.style.fontFamily;
- // Only build font string and set to context if different from last.
- if (fontSize !== lastFontSize || fontFamily !== lastFontFamily) {
- ctx.font = fontSize + ' ' + fontFamily;
- lastFontSize = fontSize;
- lastFontFamily = fontFamily;
- }
- var width = ctx.measureText(textDiv.textContent).width;
- textLayerFrag.appendChild(textDiv);
- var transform = '';
- if (textDivProperties.canvasWidth !== 0 && width > 0) {
- textDivProperties.scale = textDivProperties.canvasWidth / width;
- transform = 'scaleX(' + textDivProperties.scale + ')';
- }
- if (textDivProperties.angle !== 0) {
- transform = 'rotate(' + textDivProperties.angle + 'deg) ' + transform;
- }
- if (transform !== '') {
- textDivProperties.originalTransform = transform;
- CustomStyle.setProp('transform', textDiv, transform);
- }
- task._textDivProperties.set(textDiv, textDivProperties);
- }
- task._renderingDone = true;
- capability.resolve();
- }
- function expand(task) {
- var bounds = task._bounds;
- var viewport = task._viewport;
- var expanded = expandBounds(viewport.width, viewport.height, bounds);
- for (var i = 0; i < expanded.length; i++) {
- var div = bounds[i].div;
- var divProperties = task._textDivProperties.get(div);
- if (divProperties.angle === 0) {
- divProperties.paddingLeft = bounds[i].left - expanded[i].left;
- divProperties.paddingTop = bounds[i].top - expanded[i].top;
- divProperties.paddingRight = expanded[i].right - bounds[i].right;
- divProperties.paddingBottom = expanded[i].bottom - bounds[i].bottom;
- task._textDivProperties.set(div, divProperties);
- continue;
- }
- // Box is rotated -- trying to find padding so rotated div will not
- // exceed its expanded bounds.
- var e = expanded[i], b = bounds[i];
- var m = b.m, c = m[0], s = m[1];
- // Finding intersections with expanded box.
- var points = [
- [
- 0,
- 0
- ],
- [
- 0,
- b.size[1]
- ],
- [
- b.size[0],
- 0
- ],
- b.size
- ];
- var ts = new Float64Array(64);
- points.forEach(function (p, i) {
- var t = Util.applyTransform(p, m);
- ts[i + 0] = c && (e.left - t[0]) / c;
- ts[i + 4] = s && (e.top - t[1]) / s;
- ts[i + 8] = c && (e.right - t[0]) / c;
- ts[i + 12] = s && (e.bottom - t[1]) / s;
- ts[i + 16] = s && (e.left - t[0]) / -s;
- ts[i + 20] = c && (e.top - t[1]) / c;
- ts[i + 24] = s && (e.right - t[0]) / -s;
- ts[i + 28] = c && (e.bottom - t[1]) / c;
- ts[i + 32] = c && (e.left - t[0]) / -c;
- ts[i + 36] = s && (e.top - t[1]) / -s;
- ts[i + 40] = c && (e.right - t[0]) / -c;
- ts[i + 44] = s && (e.bottom - t[1]) / -s;
- ts[i + 48] = s && (e.left - t[0]) / s;
- ts[i + 52] = c && (e.top - t[1]) / -c;
- ts[i + 56] = s && (e.right - t[0]) / s;
- ts[i + 60] = c && (e.bottom - t[1]) / -c;
- });
- var findPositiveMin = function (ts, offset, count) {
- var result = 0;
- for (var i = 0; i < count; i++) {
- var t = ts[offset++];
- if (t > 0) {
- result = result ? Math.min(t, result) : t;
- }
- }
- return result;
- };
- // Not based on math, but to simplify calculations, using cos and sin
- // absolute values to not exceed the box (it can but insignificantly).
- var boxScale = 1 + Math.min(Math.abs(c), Math.abs(s));
- divProperties.paddingLeft = findPositiveMin(ts, 32, 16) / boxScale;
- divProperties.paddingTop = findPositiveMin(ts, 48, 16) / boxScale;
- divProperties.paddingRight = findPositiveMin(ts, 0, 16) / boxScale;
- divProperties.paddingBottom = findPositiveMin(ts, 16, 16) / boxScale;
- task._textDivProperties.set(div, divProperties);
- }
- }
- function expandBounds(width, height, boxes) {
- var bounds = boxes.map(function (box, i) {
- return {
- x1: box.left,
- y1: box.top,
- x2: box.right,
- y2: box.bottom,
- index: i,
- x1New: undefined,
- x2New: undefined
- };
- });
- expandBoundsLTR(width, bounds);
- var expanded = new Array(boxes.length);
- bounds.forEach(function (b) {
- var i = b.index;
- expanded[i] = {
- left: b.x1New,
- top: 0,
- right: b.x2New,
- bottom: 0
- };
- });
- // Rotating on 90 degrees and extending extended boxes. Reusing the bounds
- // array and objects.
- boxes.map(function (box, i) {
- var e = expanded[i], b = bounds[i];
- b.x1 = box.top;
- b.y1 = width - e.right;
- b.x2 = box.bottom;
- b.y2 = width - e.left;
- b.index = i;
- b.x1New = undefined;
- b.x2New = undefined;
- });
- expandBoundsLTR(height, bounds);
- bounds.forEach(function (b) {
- var i = b.index;
- expanded[i].top = b.x1New;
- expanded[i].bottom = b.x2New;
- });
- return expanded;
- }
- function expandBoundsLTR(width, bounds) {
- // Sorting by x1 coordinate and walk by the bounds in the same order.
- bounds.sort(function (a, b) {
- return a.x1 - b.x1 || a.index - b.index;
- });
- // First we see on the horizon is a fake boundary.
- var fakeBoundary = {
- x1: -Infinity,
- y1: -Infinity,
- x2: 0,
- y2: Infinity,
- index: -1,
- x1New: 0,
- x2New: 0
- };
- var horizon = [{
- start: -Infinity,
- end: Infinity,
- boundary: fakeBoundary
- }];
- bounds.forEach(function (boundary) {
- // Searching for the affected part of horizon.
- // TODO red-black tree or simple binary search
- var i = 0;
- while (i < horizon.length && horizon[i].end <= boundary.y1) {
- i++;
- }
- var j = horizon.length - 1;
- while (j >= 0 && horizon[j].start >= boundary.y2) {
- j--;
- }
- var horizonPart, affectedBoundary;
- var q, k, maxXNew = -Infinity;
- for (q = i; q <= j; q++) {
- horizonPart = horizon[q];
- affectedBoundary = horizonPart.boundary;
- var xNew;
- if (affectedBoundary.x2 > boundary.x1) {
- // In the middle of the previous element, new x shall be at the
- // boundary start. Extending if further if the affected bondary
- // placed on top of the current one.
- xNew = affectedBoundary.index > boundary.index ? affectedBoundary.x1New : boundary.x1;
- } else if (affectedBoundary.x2New === undefined) {
- // We have some space in between, new x in middle will be a fair
- // choice.
- xNew = (affectedBoundary.x2 + boundary.x1) / 2;
- } else {
- // Affected boundary has x2new set, using it as new x.
- xNew = affectedBoundary.x2New;
- }
- if (xNew > maxXNew) {
- maxXNew = xNew;
- }
- }
- // Set new x1 for current boundary.
- boundary.x1New = maxXNew;
- // Adjusts new x2 for the affected boundaries.
- for (q = i; q <= j; q++) {
- horizonPart = horizon[q];
- affectedBoundary = horizonPart.boundary;
- if (affectedBoundary.x2New === undefined) {
- // Was not set yet, choosing new x if possible.
- if (affectedBoundary.x2 > boundary.x1) {
- // Current and affected boundaries intersect. If affected boundary
- // is placed on top of the current, shrinking the affected.
- if (affectedBoundary.index > boundary.index) {
- affectedBoundary.x2New = affectedBoundary.x2;
- }
- } else {
- affectedBoundary.x2New = maxXNew;
- }
- } else if (affectedBoundary.x2New > maxXNew) {
- // Affected boundary is touching new x, pushing it back.
- affectedBoundary.x2New = Math.max(maxXNew, affectedBoundary.x2);
- }
- }
- // Fixing the horizon.
- var changedHorizon = [], lastBoundary = null;
- for (q = i; q <= j; q++) {
- horizonPart = horizon[q];
- affectedBoundary = horizonPart.boundary;
- // Checking which boundary will be visible.
- var useBoundary = affectedBoundary.x2 > boundary.x2 ? affectedBoundary : boundary;
- if (lastBoundary === useBoundary) {
- // Merging with previous.
- changedHorizon[changedHorizon.length - 1].end = horizonPart.end;
- } else {
- changedHorizon.push({
- start: horizonPart.start,
- end: horizonPart.end,
- boundary: useBoundary
- });
- lastBoundary = useBoundary;
- }
- }
- if (horizon[i].start < boundary.y1) {
- changedHorizon[0].start = boundary.y1;
- changedHorizon.unshift({
- start: horizon[i].start,
- end: boundary.y1,
- boundary: horizon[i].boundary
- });
- }
- if (boundary.y2 < horizon[j].end) {
- changedHorizon[changedHorizon.length - 1].end = boundary.y2;
- changedHorizon.push({
- start: boundary.y2,
- end: horizon[j].end,
- boundary: horizon[j].boundary
- });
- }
- // Set x2 new of boundary that is no longer visible (see overlapping case
- // above).
- // TODO more efficient, e.g. via reference counting.
- for (q = i; q <= j; q++) {
- horizonPart = horizon[q];
- affectedBoundary = horizonPart.boundary;
- if (affectedBoundary.x2New !== undefined) {
- continue;
- }
- var used = false;
- for (k = i - 1; !used && k >= 0 && horizon[k].start >= affectedBoundary.y1; k--) {
- used = horizon[k].boundary === affectedBoundary;
- }
- for (k = j + 1; !used && k < horizon.length && horizon[k].end <= affectedBoundary.y2; k++) {
- used = horizon[k].boundary === affectedBoundary;
- }
- for (k = 0; !used && k < changedHorizon.length; k++) {
- used = changedHorizon[k].boundary === affectedBoundary;
- }
- if (!used) {
- affectedBoundary.x2New = maxXNew;
- }
- }
- Array.prototype.splice.apply(horizon, [
- i,
- j - i + 1
- ].concat(changedHorizon));
- });
- // Set new x2 for all unset boundaries.
- horizon.forEach(function (horizonPart) {
- var affectedBoundary = horizonPart.boundary;
- if (affectedBoundary.x2New === undefined) {
- affectedBoundary.x2New = Math.max(width, affectedBoundary.x2);
- }
- });
- }
- /**
- * Text layer rendering task.
- *
- * @param {TextContent} textContent
- * @param {HTMLElement} container
- * @param {PageViewport} viewport
- * @param {Array} textDivs
- * @param {boolean} enhanceTextSelection
- * @private
- */
- function TextLayerRenderTask(textContent, container, viewport, textDivs, enhanceTextSelection) {
- this._textContent = textContent;
- this._container = container;
- this._viewport = viewport;
- this._textDivs = textDivs || [];
- this._textDivProperties = new WeakMap();
- this._renderingDone = false;
- this._canceled = false;
- this._capability = createPromiseCapability();
- this._renderTimer = null;
- this._bounds = [];
- this._enhanceTextSelection = !!enhanceTextSelection;
- }
- TextLayerRenderTask.prototype = {
- get promise() {
- return this._capability.promise;
- },
- cancel: function TextLayer_cancel() {
- this._canceled = true;
- if (this._renderTimer !== null) {
- clearTimeout(this._renderTimer);
- this._renderTimer = null;
- }
- this._capability.reject('canceled');
- },
- _render: function TextLayer_render(timeout) {
- var textItems = this._textContent.items;
- var textStyles = this._textContent.styles;
- for (var i = 0, len = textItems.length; i < len; i++) {
- appendText(this, textItems[i], textStyles);
- }
- if (!timeout) {
- // Render right away
- render(this);
- } else {
- // Schedule
- var self = this;
- this._renderTimer = setTimeout(function () {
- render(self);
- self._renderTimer = null;
- }, timeout);
- }
- },
- expandTextDivs: function TextLayer_expandTextDivs(expandDivs) {
- if (!this._enhanceTextSelection || !this._renderingDone) {
- return;
- }
- if (this._bounds !== null) {
- expand(this);
- this._bounds = null;
- }
- for (var i = 0, ii = this._textDivs.length; i < ii; i++) {
- var div = this._textDivs[i];
- var divProperties = this._textDivProperties.get(div);
- if (divProperties.isWhitespace) {
- continue;
- }
- if (expandDivs) {
- var transform = '', padding = '';
- if (divProperties.scale !== 1) {
- transform = 'scaleX(' + divProperties.scale + ')';
- }
- if (divProperties.angle !== 0) {
- transform = 'rotate(' + divProperties.angle + 'deg) ' + transform;
- }
- if (divProperties.paddingLeft !== 0) {
- padding += ' padding-left: ' + divProperties.paddingLeft / divProperties.scale + 'px;';
- transform += ' translateX(' + -divProperties.paddingLeft / divProperties.scale + 'px)';
- }
- if (divProperties.paddingTop !== 0) {
- padding += ' padding-top: ' + divProperties.paddingTop + 'px;';
- transform += ' translateY(' + -divProperties.paddingTop + 'px)';
- }
- if (divProperties.paddingRight !== 0) {
- padding += ' padding-right: ' + divProperties.paddingRight / divProperties.scale + 'px;';
- }
- if (divProperties.paddingBottom !== 0) {
- padding += ' padding-bottom: ' + divProperties.paddingBottom + 'px;';
- }
- if (padding !== '') {
- div.setAttribute('style', divProperties.style + padding);
- }
- if (transform !== '') {
- CustomStyle.setProp('transform', div, transform);
- }
- } else {
- div.style.padding = 0;
- CustomStyle.setProp('transform', div, divProperties.originalTransform || '');
- }
- }
- }
- };
- /**
- * Starts rendering of the text layer.
- *
- * @param {TextLayerRenderParameters} renderParameters
- * @returns {TextLayerRenderTask}
- */
- function renderTextLayer(renderParameters) {
- var task = new TextLayerRenderTask(renderParameters.textContent, renderParameters.container, renderParameters.viewport, renderParameters.textDivs, renderParameters.enhanceTextSelection);
- task._render(renderParameters.timeout);
- return task;
- }
- return renderTextLayer;
- }();
- exports.renderTextLayer = renderTextLayer;
- }));
- (function (root, factory) {
- factory(root.pdfjsDisplayWebGL = {}, root.pdfjsSharedUtil, root.pdfjsDisplayDOMUtils);
- }(this, function (exports, sharedUtil, displayDOMUtils) {
- var shadow = sharedUtil.shadow;
- var getDefaultSetting = displayDOMUtils.getDefaultSetting;
- var WebGLUtils = function WebGLUtilsClosure() {
- function loadShader(gl, code, shaderType) {
- var shader = gl.createShader(shaderType);
- gl.shaderSource(shader, code);
- gl.compileShader(shader);
- var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
- if (!compiled) {
- var errorMsg = gl.getShaderInfoLog(shader);
- throw new Error('Error during shader compilation: ' + errorMsg);
- }
- return shader;
- }
- function createVertexShader(gl, code) {
- return loadShader(gl, code, gl.VERTEX_SHADER);
- }
- function createFragmentShader(gl, code) {
- return loadShader(gl, code, gl.FRAGMENT_SHADER);
- }
- function createProgram(gl, shaders) {
- var program = gl.createProgram();
- for (var i = 0, ii = shaders.length; i < ii; ++i) {
- gl.attachShader(program, shaders[i]);
- }
- gl.linkProgram(program);
- var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
- if (!linked) {
- var errorMsg = gl.getProgramInfoLog(program);
- throw new Error('Error during program linking: ' + errorMsg);
- }
- return program;
- }
- function createTexture(gl, image, textureId) {
- gl.activeTexture(textureId);
- var texture = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture);
- // Set the parameters so we can render any size image.
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
- // Upload the image into the texture.
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
- return texture;
- }
- var currentGL, currentCanvas;
- function generateGL() {
- if (currentGL) {
- return;
- }
- currentCanvas = document.createElement('canvas');
- currentGL = currentCanvas.getContext('webgl', { premultipliedalpha: false });
- }
- var smaskVertexShaderCode = '\
- attribute vec2 a_position; \
- attribute vec2 a_texCoord; \
- \
- uniform vec2 u_resolution; \
- \
- varying vec2 v_texCoord; \
- \
- void main() { \
- vec2 clipSpace = (a_position / u_resolution) * 2.0 - 1.0; \
- gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
- \
- v_texCoord = a_texCoord; \
- } ';
- var smaskFragmentShaderCode = '\
- precision mediump float; \
- \
- uniform vec4 u_backdrop; \
- uniform int u_subtype; \
- uniform sampler2D u_image; \
- uniform sampler2D u_mask; \
- \
- varying vec2 v_texCoord; \
- \
- void main() { \
- vec4 imageColor = texture2D(u_image, v_texCoord); \
- vec4 maskColor = texture2D(u_mask, v_texCoord); \
- if (u_backdrop.a > 0.0) { \
- maskColor.rgb = maskColor.rgb * maskColor.a + \
- u_backdrop.rgb * (1.0 - maskColor.a); \
- } \
- float lum; \
- if (u_subtype == 0) { \
- lum = maskColor.a; \
- } else { \
- lum = maskColor.r * 0.3 + maskColor.g * 0.59 + \
- maskColor.b * 0.11; \
- } \
- imageColor.a *= lum; \
- imageColor.rgb *= imageColor.a; \
- gl_FragColor = imageColor; \
- } ';
- var smaskCache = null;
- function initSmaskGL() {
- var canvas, gl;
- generateGL();
- canvas = currentCanvas;
- currentCanvas = null;
- gl = currentGL;
- currentGL = null;
- // setup a GLSL program
- var vertexShader = createVertexShader(gl, smaskVertexShaderCode);
- var fragmentShader = createFragmentShader(gl, smaskFragmentShaderCode);
- var program = createProgram(gl, [
- vertexShader,
- fragmentShader
- ]);
- gl.useProgram(program);
- var cache = {};
- cache.gl = gl;
- cache.canvas = canvas;
- cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
- cache.positionLocation = gl.getAttribLocation(program, 'a_position');
- cache.backdropLocation = gl.getUniformLocation(program, 'u_backdrop');
- cache.subtypeLocation = gl.getUniformLocation(program, 'u_subtype');
- var texCoordLocation = gl.getAttribLocation(program, 'a_texCoord');
- var texLayerLocation = gl.getUniformLocation(program, 'u_image');
- var texMaskLocation = gl.getUniformLocation(program, 'u_mask');
- // provide texture coordinates for the rectangle.
- var texCoordBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
- 0.0,
- 0.0,
- 1.0,
- 0.0,
- 0.0,
- 1.0,
- 0.0,
- 1.0,
- 1.0,
- 0.0,
- 1.0,
- 1.0
- ]), gl.STATIC_DRAW);
- gl.enableVertexAttribArray(texCoordLocation);
- gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
- gl.uniform1i(texLayerLocation, 0);
- gl.uniform1i(texMaskLocation, 1);
- smaskCache = cache;
- }
- function composeSMask(layer, mask, properties) {
- var width = layer.width, height = layer.height;
- if (!smaskCache) {
- initSmaskGL();
- }
- var cache = smaskCache, canvas = cache.canvas, gl = cache.gl;
- canvas.width = width;
- canvas.height = height;
- gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
- gl.uniform2f(cache.resolutionLocation, width, height);
- if (properties.backdrop) {
- gl.uniform4f(cache.resolutionLocation, properties.backdrop[0], properties.backdrop[1], properties.backdrop[2], 1);
- } else {
- gl.uniform4f(cache.resolutionLocation, 0, 0, 0, 0);
- }
- gl.uniform1i(cache.subtypeLocation, properties.subtype === 'Luminosity' ? 1 : 0);
- // Create a textures
- var texture = createTexture(gl, layer, gl.TEXTURE0);
- var maskTexture = createTexture(gl, mask, gl.TEXTURE1);
- // Create a buffer and put a single clipspace rectangle in
- // it (2 triangles)
- var buffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
- 0,
- 0,
- width,
- 0,
- 0,
- height,
- 0,
- height,
- width,
- 0,
- width,
- height
- ]), gl.STATIC_DRAW);
- gl.enableVertexAttribArray(cache.positionLocation);
- gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0);
- // draw
- gl.clearColor(0, 0, 0, 0);
- gl.enable(gl.BLEND);
- gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
- gl.clear(gl.COLOR_BUFFER_BIT);
- gl.drawArrays(gl.TRIANGLES, 0, 6);
- gl.flush();
- gl.deleteTexture(texture);
- gl.deleteTexture(maskTexture);
- gl.deleteBuffer(buffer);
- return canvas;
- }
- var figuresVertexShaderCode = '\
- attribute vec2 a_position; \
- attribute vec3 a_color; \
- \
- uniform vec2 u_resolution; \
- uniform vec2 u_scale; \
- uniform vec2 u_offset; \
- \
- varying vec4 v_color; \
- \
- void main() { \
- vec2 position = (a_position + u_offset) * u_scale; \
- vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0; \
- gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
- \
- v_color = vec4(a_color / 255.0, 1.0); \
- } ';
- var figuresFragmentShaderCode = '\
- precision mediump float; \
- \
- varying vec4 v_color; \
- \
- void main() { \
- gl_FragColor = v_color; \
- } ';
- var figuresCache = null;
- function initFiguresGL() {
- var canvas, gl;
- generateGL();
- canvas = currentCanvas;
- currentCanvas = null;
- gl = currentGL;
- currentGL = null;
- // setup a GLSL program
- var vertexShader = createVertexShader(gl, figuresVertexShaderCode);
- var fragmentShader = createFragmentShader(gl, figuresFragmentShaderCode);
- var program = createProgram(gl, [
- vertexShader,
- fragmentShader
- ]);
- gl.useProgram(program);
- var cache = {};
- cache.gl = gl;
- cache.canvas = canvas;
- cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
- cache.scaleLocation = gl.getUniformLocation(program, 'u_scale');
- cache.offsetLocation = gl.getUniformLocation(program, 'u_offset');
- cache.positionLocation = gl.getAttribLocation(program, 'a_position');
- cache.colorLocation = gl.getAttribLocation(program, 'a_color');
- figuresCache = cache;
- }
- function drawFigures(width, height, backgroundColor, figures, context) {
- if (!figuresCache) {
- initFiguresGL();
- }
- var cache = figuresCache, canvas = cache.canvas, gl = cache.gl;
- canvas.width = width;
- canvas.height = height;
- gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
- gl.uniform2f(cache.resolutionLocation, width, height);
- // count triangle points
- var count = 0;
- var i, ii, rows;
- for (i = 0, ii = figures.length; i < ii; i++) {
- switch (figures[i].type) {
- case 'lattice':
- rows = figures[i].coords.length / figures[i].verticesPerRow | 0;
- count += (rows - 1) * (figures[i].verticesPerRow - 1) * 6;
- break;
- case 'triangles':
- count += figures[i].coords.length;
- break;
- }
- }
- // transfer data
- var coords = new Float32Array(count * 2);
- var colors = new Uint8Array(count * 3);
- var coordsMap = context.coords, colorsMap = context.colors;
- var pIndex = 0, cIndex = 0;
- for (i = 0, ii = figures.length; i < ii; i++) {
- var figure = figures[i], ps = figure.coords, cs = figure.colors;
- switch (figure.type) {
- case 'lattice':
- var cols = figure.verticesPerRow;
- rows = ps.length / cols | 0;
- for (var row = 1; row < rows; row++) {
- var offset = row * cols + 1;
- for (var col = 1; col < cols; col++, offset++) {
- coords[pIndex] = coordsMap[ps[offset - cols - 1]];
- coords[pIndex + 1] = coordsMap[ps[offset - cols - 1] + 1];
- coords[pIndex + 2] = coordsMap[ps[offset - cols]];
- coords[pIndex + 3] = coordsMap[ps[offset - cols] + 1];
- coords[pIndex + 4] = coordsMap[ps[offset - 1]];
- coords[pIndex + 5] = coordsMap[ps[offset - 1] + 1];
- colors[cIndex] = colorsMap[cs[offset - cols - 1]];
- colors[cIndex + 1] = colorsMap[cs[offset - cols - 1] + 1];
- colors[cIndex + 2] = colorsMap[cs[offset - cols - 1] + 2];
- colors[cIndex + 3] = colorsMap[cs[offset - cols]];
- colors[cIndex + 4] = colorsMap[cs[offset - cols] + 1];
- colors[cIndex + 5] = colorsMap[cs[offset - cols] + 2];
- colors[cIndex + 6] = colorsMap[cs[offset - 1]];
- colors[cIndex + 7] = colorsMap[cs[offset - 1] + 1];
- colors[cIndex + 8] = colorsMap[cs[offset - 1] + 2];
- coords[pIndex + 6] = coords[pIndex + 2];
- coords[pIndex + 7] = coords[pIndex + 3];
- coords[pIndex + 8] = coords[pIndex + 4];
- coords[pIndex + 9] = coords[pIndex + 5];
- coords[pIndex + 10] = coordsMap[ps[offset]];
- coords[pIndex + 11] = coordsMap[ps[offset] + 1];
- colors[cIndex + 9] = colors[cIndex + 3];
- colors[cIndex + 10] = colors[cIndex + 4];
- colors[cIndex + 11] = colors[cIndex + 5];
- colors[cIndex + 12] = colors[cIndex + 6];
- colors[cIndex + 13] = colors[cIndex + 7];
- colors[cIndex + 14] = colors[cIndex + 8];
- colors[cIndex + 15] = colorsMap[cs[offset]];
- colors[cIndex + 16] = colorsMap[cs[offset] + 1];
- colors[cIndex + 17] = colorsMap[cs[offset] + 2];
- pIndex += 12;
- cIndex += 18;
- }
- }
- break;
- case 'triangles':
- for (var j = 0, jj = ps.length; j < jj; j++) {
- coords[pIndex] = coordsMap[ps[j]];
- coords[pIndex + 1] = coordsMap[ps[j] + 1];
- colors[cIndex] = colorsMap[cs[j]];
- colors[cIndex + 1] = colorsMap[cs[j] + 1];
- colors[cIndex + 2] = colorsMap[cs[j] + 2];
- pIndex += 2;
- cIndex += 3;
- }
- break;
- }
- }
- // draw
- if (backgroundColor) {
- gl.clearColor(backgroundColor[0] / 255, backgroundColor[1] / 255, backgroundColor[2] / 255, 1.0);
- } else {
- gl.clearColor(0, 0, 0, 0);
- }
- gl.clear(gl.COLOR_BUFFER_BIT);
- var coordsBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, coordsBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, coords, gl.STATIC_DRAW);
- gl.enableVertexAttribArray(cache.positionLocation);
- gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0);
- var colorsBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
- gl.enableVertexAttribArray(cache.colorLocation);
- gl.vertexAttribPointer(cache.colorLocation, 3, gl.UNSIGNED_BYTE, false, 0, 0);
- gl.uniform2f(cache.scaleLocation, context.scaleX, context.scaleY);
- gl.uniform2f(cache.offsetLocation, context.offsetX, context.offsetY);
- gl.drawArrays(gl.TRIANGLES, 0, count);
- gl.flush();
- gl.deleteBuffer(coordsBuffer);
- gl.deleteBuffer(colorsBuffer);
- return canvas;
- }
- function cleanup() {
- if (smaskCache && smaskCache.canvas) {
- smaskCache.canvas.width = 0;
- smaskCache.canvas.height = 0;
- }
- if (figuresCache && figuresCache.canvas) {
- figuresCache.canvas.width = 0;
- figuresCache.canvas.height = 0;
- }
- smaskCache = null;
- figuresCache = null;
- }
- return {
- get isEnabled() {
- if (getDefaultSetting('disableWebGL')) {
- return false;
- }
- var enabled = false;
- try {
- generateGL();
- enabled = !!currentGL;
- } catch (e) {
- }
- return shadow(this, 'isEnabled', enabled);
- },
- composeSMask: composeSMask,
- drawFigures: drawFigures,
- clear: cleanup
- };
- }();
- exports.WebGLUtils = WebGLUtils;
- }));
- (function (root, factory) {
- factory(root.pdfjsDisplayPatternHelper = {}, root.pdfjsSharedUtil, root.pdfjsDisplayWebGL);
- }(this, function (exports, sharedUtil, displayWebGL) {
- var Util = sharedUtil.Util;
- var info = sharedUtil.info;
- var isArray = sharedUtil.isArray;
- var error = sharedUtil.error;
- var WebGLUtils = displayWebGL.WebGLUtils;
- var ShadingIRs = {};
- ShadingIRs.RadialAxial = {
- fromIR: function RadialAxial_fromIR(raw) {
- var type = raw[1];
- var colorStops = raw[2];
- var p0 = raw[3];
- var p1 = raw[4];
- var r0 = raw[5];
- var r1 = raw[6];
- return {
- type: 'Pattern',
- getPattern: function RadialAxial_getPattern(ctx) {
- var grad;
- if (type === 'axial') {
- grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
- } else if (type === 'radial') {
- grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
- }
- for (var i = 0, ii = colorStops.length; i < ii; ++i) {
- var c = colorStops[i];
- grad.addColorStop(c[0], c[1]);
- }
- return grad;
- }
- };
- }
- };
- var createMeshCanvas = function createMeshCanvasClosure() {
- function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
- // Very basic Gouraud-shaded triangle rasterization algorithm.
- var coords = context.coords, colors = context.colors;
- var bytes = data.data, rowSize = data.width * 4;
- var tmp;
- if (coords[p1 + 1] > coords[p2 + 1]) {
- tmp = p1;
- p1 = p2;
- p2 = tmp;
- tmp = c1;
- c1 = c2;
- c2 = tmp;
- }
- if (coords[p2 + 1] > coords[p3 + 1]) {
- tmp = p2;
- p2 = p3;
- p3 = tmp;
- tmp = c2;
- c2 = c3;
- c3 = tmp;
- }
- if (coords[p1 + 1] > coords[p2 + 1]) {
- tmp = p1;
- p1 = p2;
- p2 = tmp;
- tmp = c1;
- c1 = c2;
- c2 = tmp;
- }
- var x1 = (coords[p1] + context.offsetX) * context.scaleX;
- var y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;
- var x2 = (coords[p2] + context.offsetX) * context.scaleX;
- var y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY;
- var x3 = (coords[p3] + context.offsetX) * context.scaleX;
- var y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY;
- if (y1 >= y3) {
- return;
- }
- var c1r = colors[c1], c1g = colors[c1 + 1], c1b = colors[c1 + 2];
- var c2r = colors[c2], c2g = colors[c2 + 1], c2b = colors[c2 + 2];
- var c3r = colors[c3], c3g = colors[c3 + 1], c3b = colors[c3 + 2];
- var minY = Math.round(y1), maxY = Math.round(y3);
- var xa, car, cag, cab;
- var xb, cbr, cbg, cbb;
- var k;
- for (var y = minY; y <= maxY; y++) {
- if (y < y2) {
- k = y < y1 ? 0 : y1 === y2 ? 1 : (y1 - y) / (y1 - y2);
- xa = x1 - (x1 - x2) * k;
- car = c1r - (c1r - c2r) * k;
- cag = c1g - (c1g - c2g) * k;
- cab = c1b - (c1b - c2b) * k;
- } else {
- k = y > y3 ? 1 : y2 === y3 ? 0 : (y2 - y) / (y2 - y3);
- xa = x2 - (x2 - x3) * k;
- car = c2r - (c2r - c3r) * k;
- cag = c2g - (c2g - c3g) * k;
- cab = c2b - (c2b - c3b) * k;
- }
- k = y < y1 ? 0 : y > y3 ? 1 : (y1 - y) / (y1 - y3);
- xb = x1 - (x1 - x3) * k;
- cbr = c1r - (c1r - c3r) * k;
- cbg = c1g - (c1g - c3g) * k;
- cbb = c1b - (c1b - c3b) * k;
- var x1_ = Math.round(Math.min(xa, xb));
- var x2_ = Math.round(Math.max(xa, xb));
- var j = rowSize * y + x1_ * 4;
- for (var x = x1_; x <= x2_; x++) {
- k = (xa - x) / (xa - xb);
- k = k < 0 ? 0 : k > 1 ? 1 : k;
- bytes[j++] = car - (car - cbr) * k | 0;
- bytes[j++] = cag - (cag - cbg) * k | 0;
- bytes[j++] = cab - (cab - cbb) * k | 0;
- bytes[j++] = 255;
- }
- }
- }
- function drawFigure(data, figure, context) {
- var ps = figure.coords;
- var cs = figure.colors;
- var i, ii;
- switch (figure.type) {
- case 'lattice':
- var verticesPerRow = figure.verticesPerRow;
- var rows = Math.floor(ps.length / verticesPerRow) - 1;
- var cols = verticesPerRow - 1;
- for (i = 0; i < rows; i++) {
- var q = i * verticesPerRow;
- for (var j = 0; j < cols; j++, q++) {
- drawTriangle(data, context, ps[q], ps[q + 1], ps[q + verticesPerRow], cs[q], cs[q + 1], cs[q + verticesPerRow]);
- drawTriangle(data, context, ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]);
- }
- }
- break;
- case 'triangles':
- for (i = 0, ii = ps.length; i < ii; i += 3) {
- drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]);
- }
- break;
- default:
- error('illigal figure');
- break;
- }
- }
- function createMeshCanvas(bounds, combinesScale, coords, colors, figures, backgroundColor, cachedCanvases) {
- // we will increase scale on some weird factor to let antialiasing take
- // care of "rough" edges
- var EXPECTED_SCALE = 1.1;
- // MAX_PATTERN_SIZE is used to avoid OOM situation.
- var MAX_PATTERN_SIZE = 3000;
- // 10in @ 300dpi shall be enough
- // We need to keep transparent border around our pattern for fill():
- // createPattern with 'no-repeat' will bleed edges across entire area.
- var BORDER_SIZE = 2;
- var offsetX = Math.floor(bounds[0]);
- var offsetY = Math.floor(bounds[1]);
- var boundsWidth = Math.ceil(bounds[2]) - offsetX;
- var boundsHeight = Math.ceil(bounds[3]) - offsetY;
- var width = Math.min(Math.ceil(Math.abs(boundsWidth * combinesScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
- var height = Math.min(Math.ceil(Math.abs(boundsHeight * combinesScale[1] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
- var scaleX = boundsWidth / width;
- var scaleY = boundsHeight / height;
- var context = {
- coords: coords,
- colors: colors,
- offsetX: -offsetX,
- offsetY: -offsetY,
- scaleX: 1 / scaleX,
- scaleY: 1 / scaleY
- };
- var paddedWidth = width + BORDER_SIZE * 2;
- var paddedHeight = height + BORDER_SIZE * 2;
- var canvas, tmpCanvas, i, ii;
- if (WebGLUtils.isEnabled) {
- canvas = WebGLUtils.drawFigures(width, height, backgroundColor, figures, context);
- // https://bugzilla.mozilla.org/show_bug.cgi?id=972126
- tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight, false);
- tmpCanvas.context.drawImage(canvas, BORDER_SIZE, BORDER_SIZE);
- canvas = tmpCanvas.canvas;
- } else {
- tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight, false);
- var tmpCtx = tmpCanvas.context;
- var data = tmpCtx.createImageData(width, height);
- if (backgroundColor) {
- var bytes = data.data;
- for (i = 0, ii = bytes.length; i < ii; i += 4) {
- bytes[i] = backgroundColor[0];
- bytes[i + 1] = backgroundColor[1];
- bytes[i + 2] = backgroundColor[2];
- bytes[i + 3] = 255;
- }
- }
- for (i = 0; i < figures.length; i++) {
- drawFigure(data, figures[i], context);
- }
- tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE);
- canvas = tmpCanvas.canvas;
- }
- return {
- canvas: canvas,
- offsetX: offsetX - BORDER_SIZE * scaleX,
- offsetY: offsetY - BORDER_SIZE * scaleY,
- scaleX: scaleX,
- scaleY: scaleY
- };
- }
- return createMeshCanvas;
- }();
- ShadingIRs.Mesh = {
- fromIR: function Mesh_fromIR(raw) {
- //var type = raw[1];
- var coords = raw[2];
- var colors = raw[3];
- var figures = raw[4];
- var bounds = raw[5];
- var matrix = raw[6];
- //var bbox = raw[7];
- var background = raw[8];
- return {
- type: 'Pattern',
- getPattern: function Mesh_getPattern(ctx, owner, shadingFill) {
- var scale;
- if (shadingFill) {
- scale = Util.singularValueDecompose2dScale(ctx.mozCurrentTransform);
- } else {
- // Obtain scale from matrix and current transformation matrix.
- scale = Util.singularValueDecompose2dScale(owner.baseTransform);
- if (matrix) {
- var matrixScale = Util.singularValueDecompose2dScale(matrix);
- scale = [
- scale[0] * matrixScale[0],
- scale[1] * matrixScale[1]
- ];
- }
- }
- // Rasterizing on the main thread since sending/queue large canvases
- // might cause OOM.
- var temporaryPatternCanvas = createMeshCanvas(bounds, scale, coords, colors, figures, shadingFill ? null : background, owner.cachedCanvases);
- if (!shadingFill) {
- ctx.setTransform.apply(ctx, owner.baseTransform);
- if (matrix) {
- ctx.transform.apply(ctx, matrix);
- }
- }
- ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
- ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY);
- return ctx.createPattern(temporaryPatternCanvas.canvas, 'no-repeat');
- }
- };
- }
- };
- ShadingIRs.Dummy = {
- fromIR: function Dummy_fromIR() {
- return {
- type: 'Pattern',
- getPattern: function Dummy_fromIR_getPattern() {
- return 'hotpink';
- }
- };
- }
- };
- function getShadingPatternFromIR(raw) {
- var shadingIR = ShadingIRs[raw[0]];
- if (!shadingIR) {
- error('Unknown IR type: ' + raw[0]);
- }
- return shadingIR.fromIR(raw);
- }
- var TilingPattern = function TilingPatternClosure() {
- var PaintType = {
- COLORED: 1,
- UNCOLORED: 2
- };
- var MAX_PATTERN_SIZE = 3000;
- // 10in @ 300dpi shall be enough
- function TilingPattern(IR, color, ctx, canvasGraphicsFactory, baseTransform) {
- this.operatorList = IR[2];
- this.matrix = IR[3] || [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0
- ];
- this.bbox = IR[4];
- this.xstep = IR[5];
- this.ystep = IR[6];
- this.paintType = IR[7];
- this.tilingType = IR[8];
- this.color = color;
- this.canvasGraphicsFactory = canvasGraphicsFactory;
- this.baseTransform = baseTransform;
- this.type = 'Pattern';
- this.ctx = ctx;
- }
- TilingPattern.prototype = {
- createPatternCanvas: function TilinPattern_createPatternCanvas(owner) {
- var operatorList = this.operatorList;
- var bbox = this.bbox;
- var xstep = this.xstep;
- var ystep = this.ystep;
- var paintType = this.paintType;
- var tilingType = this.tilingType;
- var color = this.color;
- var canvasGraphicsFactory = this.canvasGraphicsFactory;
- info('TilingType: ' + tilingType);
- var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3];
- var topLeft = [
- x0,
- y0
- ];
- // we want the canvas to be as large as the step size
- var botRight = [
- x0 + xstep,
- y0 + ystep
- ];
- var width = botRight[0] - topLeft[0];
- var height = botRight[1] - topLeft[1];
- // Obtain scale from matrix and current transformation matrix.
- var matrixScale = Util.singularValueDecompose2dScale(this.matrix);
- var curMatrixScale = Util.singularValueDecompose2dScale(this.baseTransform);
- var combinedScale = [
- matrixScale[0] * curMatrixScale[0],
- matrixScale[1] * curMatrixScale[1]
- ];
- // MAX_PATTERN_SIZE is used to avoid OOM situation.
- // Use width and height values that are as close as possible to the end
- // result when the pattern is used. Too low value makes the pattern look
- // blurry. Too large value makes it look too crispy.
- width = Math.min(Math.ceil(Math.abs(width * combinedScale[0])), MAX_PATTERN_SIZE);
- height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])), MAX_PATTERN_SIZE);
- var tmpCanvas = owner.cachedCanvases.getCanvas('pattern', width, height, true);
- var tmpCtx = tmpCanvas.context;
- var graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx);
- graphics.groupLevel = owner.groupLevel;
- this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color);
- this.setScale(width, height, xstep, ystep);
- this.transformToScale(graphics);
- // transform coordinates to pattern space
- var tmpTranslate = [
- 1,
- 0,
- 0,
- 1,
- -topLeft[0],
- -topLeft[1]
- ];
- graphics.transform.apply(graphics, tmpTranslate);
- this.clipBbox(graphics, bbox, x0, y0, x1, y1);
- graphics.executeOperatorList(operatorList);
- return tmpCanvas.canvas;
- },
- setScale: function TilingPattern_setScale(width, height, xstep, ystep) {
- this.scale = [
- width / xstep,
- height / ystep
- ];
- },
- transformToScale: function TilingPattern_transformToScale(graphics) {
- var scale = this.scale;
- var tmpScale = [
- scale[0],
- 0,
- 0,
- scale[1],
- 0,
- 0
- ];
- graphics.transform.apply(graphics, tmpScale);
- },
- scaleToContext: function TilingPattern_scaleToContext() {
- var scale = this.scale;
- this.ctx.scale(1 / scale[0], 1 / scale[1]);
- },
- clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
- if (bbox && isArray(bbox) && bbox.length === 4) {
- var bboxWidth = x1 - x0;
- var bboxHeight = y1 - y0;
- graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight);
- graphics.clip();
- graphics.endPath();
- }
- },
- setFillAndStrokeStyleToContext: function setFillAndStrokeStyleToContext(context, paintType, color) {
- switch (paintType) {
- case PaintType.COLORED:
- var ctx = this.ctx;
- context.fillStyle = ctx.fillStyle;
- context.strokeStyle = ctx.strokeStyle;
- break;
- case PaintType.UNCOLORED:
- var cssColor = Util.makeCssRgb(color[0], color[1], color[2]);
- context.fillStyle = cssColor;
- context.strokeStyle = cssColor;
- break;
- default:
- error('Unsupported paint type: ' + paintType);
- }
- },
- getPattern: function TilingPattern_getPattern(ctx, owner) {
- var temporaryPatternCanvas = this.createPatternCanvas(owner);
- ctx = this.ctx;
- ctx.setTransform.apply(ctx, this.baseTransform);
- ctx.transform.apply(ctx, this.matrix);
- this.scaleToContext();
- return ctx.createPattern(temporaryPatternCanvas, 'repeat');
- }
- };
- return TilingPattern;
- }();
- exports.getShadingPatternFromIR = getShadingPatternFromIR;
- exports.TilingPattern = TilingPattern;
- }));
- (function (root, factory) {
- factory(root.pdfjsDisplayCanvas = {}, root.pdfjsSharedUtil, root.pdfjsDisplayDOMUtils, root.pdfjsDisplayPatternHelper, root.pdfjsDisplayWebGL);
- }(this, function (exports, sharedUtil, displayDOMUtils, displayPatternHelper, displayWebGL) {
- var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX;
- var IDENTITY_MATRIX = sharedUtil.IDENTITY_MATRIX;
- var ImageKind = sharedUtil.ImageKind;
- var OPS = sharedUtil.OPS;
- var TextRenderingMode = sharedUtil.TextRenderingMode;
- var Uint32ArrayView = sharedUtil.Uint32ArrayView;
- var Util = sharedUtil.Util;
- var assert = sharedUtil.assert;
- var info = sharedUtil.info;
- var isNum = sharedUtil.isNum;
- var isArray = sharedUtil.isArray;
- var isLittleEndian = sharedUtil.isLittleEndian;
- var error = sharedUtil.error;
- var shadow = sharedUtil.shadow;
- var warn = sharedUtil.warn;
- var TilingPattern = displayPatternHelper.TilingPattern;
- var getShadingPatternFromIR = displayPatternHelper.getShadingPatternFromIR;
- var WebGLUtils = displayWebGL.WebGLUtils;
- var hasCanvasTypedArrays = displayDOMUtils.hasCanvasTypedArrays;
- // <canvas> contexts store most of the state we need natively.
- // However, PDF needs a bit more state, which we store here.
- // Minimal font size that would be used during canvas fillText operations.
- var MIN_FONT_SIZE = 16;
- // Maximum font size that would be used during canvas fillText operations.
- var MAX_FONT_SIZE = 100;
- var MAX_GROUP_SIZE = 4096;
- // Heuristic value used when enforcing minimum line widths.
- var MIN_WIDTH_FACTOR = 0.65;
- var COMPILE_TYPE3_GLYPHS = true;
- var MAX_SIZE_TO_COMPILE = 1000;
- var FULL_CHUNK_HEIGHT = 16;
- var HasCanvasTypedArraysCached = {
- get value() {
- return shadow(HasCanvasTypedArraysCached, 'value', hasCanvasTypedArrays());
- }
- };
- var IsLittleEndianCached = {
- get value() {
- return shadow(IsLittleEndianCached, 'value', isLittleEndian());
- }
- };
- function createScratchCanvas(width, height) {
- var canvas = document.createElement('canvas');
- canvas.width = width;
- canvas.height = height;
- return canvas;
- }
- function addContextCurrentTransform(ctx) {
- // If the context doesn't expose a `mozCurrentTransform`, add a JS based one.
- if (!ctx.mozCurrentTransform) {
- ctx._originalSave = ctx.save;
- ctx._originalRestore = ctx.restore;
- ctx._originalRotate = ctx.rotate;
- ctx._originalScale = ctx.scale;
- ctx._originalTranslate = ctx.translate;
- ctx._originalTransform = ctx.transform;
- ctx._originalSetTransform = ctx.setTransform;
- ctx._transformMatrix = ctx._transformMatrix || [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0
- ];
- ctx._transformStack = [];
- Object.defineProperty(ctx, 'mozCurrentTransform', {
- get: function getCurrentTransform() {
- return this._transformMatrix;
- }
- });
- Object.defineProperty(ctx, 'mozCurrentTransformInverse', {
- get: function getCurrentTransformInverse() {
- // Calculation done using WolframAlpha:
- // http://www.wolframalpha.com/input/?
- // i=Inverse+{{a%2C+c%2C+e}%2C+{b%2C+d%2C+f}%2C+{0%2C+0%2C+1}}
- var m = this._transformMatrix;
- var a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5];
- var ad_bc = a * d - b * c;
- var bc_ad = b * c - a * d;
- return [
- d / ad_bc,
- b / bc_ad,
- c / bc_ad,
- a / ad_bc,
- (d * e - c * f) / bc_ad,
- (b * e - a * f) / ad_bc
- ];
- }
- });
- ctx.save = function ctxSave() {
- var old = this._transformMatrix;
- this._transformStack.push(old);
- this._transformMatrix = old.slice(0, 6);
- this._originalSave();
- };
- ctx.restore = function ctxRestore() {
- var prev = this._transformStack.pop();
- if (prev) {
- this._transformMatrix = prev;
- this._originalRestore();
- }
- };
- ctx.translate = function ctxTranslate(x, y) {
- var m = this._transformMatrix;
- m[4] = m[0] * x + m[2] * y + m[4];
- m[5] = m[1] * x + m[3] * y + m[5];
- this._originalTranslate(x, y);
- };
- ctx.scale = function ctxScale(x, y) {
- var m = this._transformMatrix;
- m[0] = m[0] * x;
- m[1] = m[1] * x;
- m[2] = m[2] * y;
- m[3] = m[3] * y;
- this._originalScale(x, y);
- };
- ctx.transform = function ctxTransform(a, b, c, d, e, f) {
- var m = this._transformMatrix;
- this._transformMatrix = [
- m[0] * a + m[2] * b,
- m[1] * a + m[3] * b,
- m[0] * c + m[2] * d,
- m[1] * c + m[3] * d,
- m[0] * e + m[2] * f + m[4],
- m[1] * e + m[3] * f + m[5]
- ];
- ctx._originalTransform(a, b, c, d, e, f);
- };
- ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) {
- this._transformMatrix = [
- a,
- b,
- c,
- d,
- e,
- f
- ];
- ctx._originalSetTransform(a, b, c, d, e, f);
- };
- ctx.rotate = function ctxRotate(angle) {
- var cosValue = Math.cos(angle);
- var sinValue = Math.sin(angle);
- var m = this._transformMatrix;
- this._transformMatrix = [
- m[0] * cosValue + m[2] * sinValue,
- m[1] * cosValue + m[3] * sinValue,
- m[0] * -sinValue + m[2] * cosValue,
- m[1] * -sinValue + m[3] * cosValue,
- m[4],
- m[5]
- ];
- this._originalRotate(angle);
- };
- }
- }
- var CachedCanvases = function CachedCanvasesClosure() {
- function CachedCanvases() {
- this.cache = Object.create(null);
- }
- CachedCanvases.prototype = {
- getCanvas: function CachedCanvases_getCanvas(id, width, height, trackTransform) {
- var canvasEntry;
- if (this.cache[id] !== undefined) {
- canvasEntry = this.cache[id];
- canvasEntry.canvas.width = width;
- canvasEntry.canvas.height = height;
- // reset canvas transform for emulated mozCurrentTransform, if needed
- canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0);
- } else {
- var canvas = createScratchCanvas(width, height);
- var ctx = canvas.getContext('2d');
- if (trackTransform) {
- addContextCurrentTransform(ctx);
- }
- this.cache[id] = canvasEntry = {
- canvas: canvas,
- context: ctx
- };
- }
- return canvasEntry;
- },
- clear: function () {
- for (var id in this.cache) {
- var canvasEntry = this.cache[id];
- // Zeroing the width and height causes Firefox to release graphics
- // resources immediately, which can greatly reduce memory consumption.
- canvasEntry.canvas.width = 0;
- canvasEntry.canvas.height = 0;
- delete this.cache[id];
- }
- }
- };
- return CachedCanvases;
- }();
- function compileType3Glyph(imgData) {
- var POINT_TO_PROCESS_LIMIT = 1000;
- var width = imgData.width, height = imgData.height;
- var i, j, j0, width1 = width + 1;
- var points = new Uint8Array(width1 * (height + 1));
- var POINT_TYPES = new Uint8Array([
- 0,
- 2,
- 4,
- 0,
- 1,
- 0,
- 5,
- 4,
- 8,
- 10,
- 0,
- 8,
- 0,
- 2,
- 1,
- 0
- ]);
- // decodes bit-packed mask data
- var lineSize = width + 7 & ~7, data0 = imgData.data;
- var data = new Uint8Array(lineSize * height), pos = 0, ii;
- for (i = 0, ii = data0.length; i < ii; i++) {
- var mask = 128, elem = data0[i];
- while (mask > 0) {
- data[pos++] = elem & mask ? 0 : 255;
- mask >>= 1;
- }
- }
- // finding iteresting points: every point is located between mask pixels,
- // so there will be points of the (width + 1)x(height + 1) grid. Every point
- // will have flags assigned based on neighboring mask pixels:
- // 4 | 8
- // --P--
- // 2 | 1
- // We are interested only in points with the flags:
- // - outside corners: 1, 2, 4, 8;
- // - inside corners: 7, 11, 13, 14;
- // - and, intersections: 5, 10.
- var count = 0;
- pos = 0;
- if (data[pos] !== 0) {
- points[0] = 1;
- ++count;
- }
- for (j = 1; j < width; j++) {
- if (data[pos] !== data[pos + 1]) {
- points[j] = data[pos] ? 2 : 1;
- ++count;
- }
- pos++;
- }
- if (data[pos] !== 0) {
- points[j] = 2;
- ++count;
- }
- for (i = 1; i < height; i++) {
- pos = i * lineSize;
- j0 = i * width1;
- if (data[pos - lineSize] !== data[pos]) {
- points[j0] = data[pos] ? 1 : 8;
- ++count;
- }
- // 'sum' is the position of the current pixel configuration in the 'TYPES'
- // array (in order 8-1-2-4, so we can use '>>2' to shift the column).
- var sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0);
- for (j = 1; j < width; j++) {
- sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + (data[pos - lineSize + 1] ? 8 : 0);
- if (POINT_TYPES[sum]) {
- points[j0 + j] = POINT_TYPES[sum];
- ++count;
- }
- pos++;
- }
- if (data[pos - lineSize] !== data[pos]) {
- points[j0 + j] = data[pos] ? 2 : 4;
- ++count;
- }
- if (count > POINT_TO_PROCESS_LIMIT) {
- return null;
- }
- }
- pos = lineSize * (height - 1);
- j0 = i * width1;
- if (data[pos] !== 0) {
- points[j0] = 8;
- ++count;
- }
- for (j = 1; j < width; j++) {
- if (data[pos] !== data[pos + 1]) {
- points[j0 + j] = data[pos] ? 4 : 8;
- ++count;
- }
- pos++;
- }
- if (data[pos] !== 0) {
- points[j0 + j] = 4;
- ++count;
- }
- if (count > POINT_TO_PROCESS_LIMIT) {
- return null;
- }
- // building outlines
- var steps = new Int32Array([
- 0,
- width1,
- -1,
- 0,
- -width1,
- 0,
- 0,
- 0,
- 1
- ]);
- var outlines = [];
- for (i = 0; count && i <= height; i++) {
- var p = i * width1;
- var end = p + width;
- while (p < end && !points[p]) {
- p++;
- }
- if (p === end) {
- continue;
- }
- var coords = [
- p % width1,
- i
- ];
- var type = points[p], p0 = p, pp;
- do {
- var step = steps[type];
- do {
- p += step;
- } while (!points[p]);
- pp = points[p];
- if (pp !== 5 && pp !== 10) {
- // set new direction
- type = pp;
- // delete mark
- points[p] = 0;
- } else {
- // type is 5 or 10, ie, a crossing
- // set new direction
- type = pp & 0x33 * type >> 4;
- // set new type for "future hit"
- points[p] &= type >> 2 | type << 2;
- }
- coords.push(p % width1);
- coords.push(p / width1 | 0);
- --count;
- } while (p0 !== p);
- outlines.push(coords);
- --i;
- }
- var drawOutline = function (c) {
- c.save();
- // the path shall be painted in [0..1]x[0..1] space
- c.scale(1 / width, -1 / height);
- c.translate(0, -height);
- c.beginPath();
- for (var i = 0, ii = outlines.length; i < ii; i++) {
- var o = outlines[i];
- c.moveTo(o[0], o[1]);
- for (var j = 2, jj = o.length; j < jj; j += 2) {
- c.lineTo(o[j], o[j + 1]);
- }
- }
- c.fill();
- c.beginPath();
- c.restore();
- };
- return drawOutline;
- }
- var CanvasExtraState = function CanvasExtraStateClosure() {
- function CanvasExtraState(old) {
- // Are soft masks and alpha values shapes or opacities?
- this.alphaIsShape = false;
- this.fontSize = 0;
- this.fontSizeScale = 1;
- this.textMatrix = IDENTITY_MATRIX;
- this.textMatrixScale = 1;
- this.fontMatrix = FONT_IDENTITY_MATRIX;
- this.leading = 0;
- // Current point (in user coordinates)
- this.x = 0;
- this.y = 0;
- // Start of text line (in text coordinates)
- this.lineX = 0;
- this.lineY = 0;
- // Character and word spacing
- this.charSpacing = 0;
- this.wordSpacing = 0;
- this.textHScale = 1;
- this.textRenderingMode = TextRenderingMode.FILL;
- this.textRise = 0;
- // Default fore and background colors
- this.fillColor = '#000000';
- this.strokeColor = '#000000';
- this.patternFill = false;
- // Note: fill alpha applies to all non-stroking operations
- this.fillAlpha = 1;
- this.strokeAlpha = 1;
- this.lineWidth = 1;
- this.activeSMask = null;
- this.resumeSMaskCtx = null;
- // nonclonable field (see the save method below)
- this.old = old;
- }
- CanvasExtraState.prototype = {
- clone: function CanvasExtraState_clone() {
- return Object.create(this);
- },
- setCurrentPoint: function CanvasExtraState_setCurrentPoint(x, y) {
- this.x = x;
- this.y = y;
- }
- };
- return CanvasExtraState;
- }();
- var CanvasGraphics = function CanvasGraphicsClosure() {
- // Defines the time the executeOperatorList is going to be executing
- // before it stops and shedules a continue of execution.
- var EXECUTION_TIME = 15;
- // Defines the number of steps before checking the execution time
- var EXECUTION_STEPS = 10;
- function CanvasGraphics(canvasCtx, commonObjs, objs, imageLayer) {
- this.ctx = canvasCtx;
- this.current = new CanvasExtraState();
- this.stateStack = [];
- this.pendingClip = null;
- this.pendingEOFill = false;
- this.res = null;
- this.xobjs = null;
- this.commonObjs = commonObjs;
- this.objs = objs;
- this.imageLayer = imageLayer;
- this.groupStack = [];
- this.processingType3 = null;
- // Patterns are painted relative to the initial page/form transform, see pdf
- // spec 8.7.2 NOTE 1.
- this.baseTransform = null;
- this.baseTransformStack = [];
- this.groupLevel = 0;
- this.smaskStack = [];
- this.smaskCounter = 0;
- this.tempSMask = null;
- this.cachedCanvases = new CachedCanvases();
- if (canvasCtx) {
- // NOTE: if mozCurrentTransform is polyfilled, then the current state of
- // the transformation must already be set in canvasCtx._transformMatrix.
- addContextCurrentTransform(canvasCtx);
- }
- this.cachedGetSinglePixelWidth = null;
- }
- function putBinaryImageData(ctx, imgData) {
- if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) {
- ctx.putImageData(imgData, 0, 0);
- return;
- }
- // Put the image data to the canvas in chunks, rather than putting the
- // whole image at once. This saves JS memory, because the ImageData object
- // is smaller. It also possibly saves C++ memory within the implementation
- // of putImageData(). (E.g. in Firefox we make two short-lived copies of
- // the data passed to putImageData()). |n| shouldn't be too small, however,
- // because too many putImageData() calls will slow things down.
- //
- // Note: as written, if the last chunk is partial, the putImageData() call
- // will (conceptually) put pixels past the bounds of the canvas. But
- // that's ok; any such pixels are ignored.
- var height = imgData.height, width = imgData.width;
- var partialChunkHeight = height % FULL_CHUNK_HEIGHT;
- var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
- var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
- var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
- var srcPos = 0, destPos;
- var src = imgData.data;
- var dest = chunkImgData.data;
- var i, j, thisChunkHeight, elemsInThisChunk;
- // There are multiple forms in which the pixel data can be passed, and
- // imgData.kind tells us which one this is.
- if (imgData.kind === ImageKind.GRAYSCALE_1BPP) {
- // Grayscale, 1 bit per pixel (i.e. black-and-white).
- var srcLength = src.byteLength;
- var dest32 = HasCanvasTypedArraysCached.value ? new Uint32Array(dest.buffer) : new Uint32ArrayView(dest);
- var dest32DataLength = dest32.length;
- var fullSrcDiff = width + 7 >> 3;
- var white = 0xFFFFFFFF;
- var black = IsLittleEndianCached.value || !HasCanvasTypedArraysCached.value ? 0xFF000000 : 0x000000FF;
- for (i = 0; i < totalChunks; i++) {
- thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
- destPos = 0;
- for (j = 0; j < thisChunkHeight; j++) {
- var srcDiff = srcLength - srcPos;
- var k = 0;
- var kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7;
- var kEndUnrolled = kEnd & ~7;
- var mask = 0;
- var srcByte = 0;
- for (; k < kEndUnrolled; k += 8) {
- srcByte = src[srcPos++];
- dest32[destPos++] = srcByte & 128 ? white : black;
- dest32[destPos++] = srcByte & 64 ? white : black;
- dest32[destPos++] = srcByte & 32 ? white : black;
- dest32[destPos++] = srcByte & 16 ? white : black;
- dest32[destPos++] = srcByte & 8 ? white : black;
- dest32[destPos++] = srcByte & 4 ? white : black;
- dest32[destPos++] = srcByte & 2 ? white : black;
- dest32[destPos++] = srcByte & 1 ? white : black;
- }
- for (; k < kEnd; k++) {
- if (mask === 0) {
- srcByte = src[srcPos++];
- mask = 128;
- }
- dest32[destPos++] = srcByte & mask ? white : black;
- mask >>= 1;
- }
- }
- // We ran out of input. Make all remaining pixels transparent.
- while (destPos < dest32DataLength) {
- dest32[destPos++] = 0;
- }
- ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
- }
- } else if (imgData.kind === ImageKind.RGBA_32BPP) {
- // RGBA, 32-bits per pixel.
- j = 0;
- elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4;
- for (i = 0; i < fullChunks; i++) {
- dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
- srcPos += elemsInThisChunk;
- ctx.putImageData(chunkImgData, 0, j);
- j += FULL_CHUNK_HEIGHT;
- }
- if (i < totalChunks) {
- elemsInThisChunk = width * partialChunkHeight * 4;
- dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
- ctx.putImageData(chunkImgData, 0, j);
- }
- } else if (imgData.kind === ImageKind.RGB_24BPP) {
- // RGB, 24-bits per pixel.
- thisChunkHeight = FULL_CHUNK_HEIGHT;
- elemsInThisChunk = width * thisChunkHeight;
- for (i = 0; i < totalChunks; i++) {
- if (i >= fullChunks) {
- thisChunkHeight = partialChunkHeight;
- elemsInThisChunk = width * thisChunkHeight;
- }
- destPos = 0;
- for (j = elemsInThisChunk; j--;) {
- dest[destPos++] = src[srcPos++];
- dest[destPos++] = src[srcPos++];
- dest[destPos++] = src[srcPos++];
- dest[destPos++] = 255;
- }
- ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
- }
- } else {
- error('bad image kind: ' + imgData.kind);
- }
- }
- function putBinaryImageMask(ctx, imgData) {
- var height = imgData.height, width = imgData.width;
- var partialChunkHeight = height % FULL_CHUNK_HEIGHT;
- var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
- var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
- var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
- var srcPos = 0;
- var src = imgData.data;
- var dest = chunkImgData.data;
- for (var i = 0; i < totalChunks; i++) {
- var thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
- // Expand the mask so it can be used by the canvas. Any required
- // inversion has already been handled.
- var destPos = 3;
- // alpha component offset
- for (var j = 0; j < thisChunkHeight; j++) {
- var mask = 0;
- for (var k = 0; k < width; k++) {
- if (!mask) {
- var elem = src[srcPos++];
- mask = 128;
- }
- dest[destPos] = elem & mask ? 0 : 255;
- destPos += 4;
- mask >>= 1;
- }
- }
- ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
- }
- }
- function copyCtxState(sourceCtx, destCtx) {
- var properties = [
- 'strokeStyle',
- 'fillStyle',
- 'fillRule',
- 'globalAlpha',
- 'lineWidth',
- 'lineCap',
- 'lineJoin',
- 'miterLimit',
- 'globalCompositeOperation',
- 'font'
- ];
- for (var i = 0, ii = properties.length; i < ii; i++) {
- var property = properties[i];
- if (sourceCtx[property] !== undefined) {
- destCtx[property] = sourceCtx[property];
- }
- }
- if (sourceCtx.setLineDash !== undefined) {
- destCtx.setLineDash(sourceCtx.getLineDash());
- destCtx.lineDashOffset = sourceCtx.lineDashOffset;
- }
- }
- function composeSMaskBackdrop(bytes, r0, g0, b0) {
- var length = bytes.length;
- for (var i = 3; i < length; i += 4) {
- var alpha = bytes[i];
- if (alpha === 0) {
- bytes[i - 3] = r0;
- bytes[i - 2] = g0;
- bytes[i - 1] = b0;
- } else if (alpha < 255) {
- var alpha_ = 255 - alpha;
- bytes[i - 3] = bytes[i - 3] * alpha + r0 * alpha_ >> 8;
- bytes[i - 2] = bytes[i - 2] * alpha + g0 * alpha_ >> 8;
- bytes[i - 1] = bytes[i - 1] * alpha + b0 * alpha_ >> 8;
- }
- }
- }
- function composeSMaskAlpha(maskData, layerData, transferMap) {
- var length = maskData.length;
- var scale = 1 / 255;
- for (var i = 3; i < length; i += 4) {
- var alpha = transferMap ? transferMap[maskData[i]] : maskData[i];
- layerData[i] = layerData[i] * alpha * scale | 0;
- }
- }
- function composeSMaskLuminosity(maskData, layerData, transferMap) {
- var length = maskData.length;
- for (var i = 3; i < length; i += 4) {
- var y = maskData[i - 3] * 77 + // * 0.3 / 255 * 0x10000
- maskData[i - 2] * 152 + // * 0.59 ....
- maskData[i - 1] * 28;
- // * 0.11 ....
- layerData[i] = transferMap ? layerData[i] * transferMap[y >> 8] >> 8 : layerData[i] * y >> 16;
- }
- }
- function genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap) {
- var hasBackdrop = !!backdrop;
- var r0 = hasBackdrop ? backdrop[0] : 0;
- var g0 = hasBackdrop ? backdrop[1] : 0;
- var b0 = hasBackdrop ? backdrop[2] : 0;
- var composeFn;
- if (subtype === 'Luminosity') {
- composeFn = composeSMaskLuminosity;
- } else {
- composeFn = composeSMaskAlpha;
- }
- // processing image in chunks to save memory
- var PIXELS_TO_PROCESS = 1048576;
- var chunkSize = Math.min(height, Math.ceil(PIXELS_TO_PROCESS / width));
- for (var row = 0; row < height; row += chunkSize) {
- var chunkHeight = Math.min(chunkSize, height - row);
- var maskData = maskCtx.getImageData(0, row, width, chunkHeight);
- var layerData = layerCtx.getImageData(0, row, width, chunkHeight);
- if (hasBackdrop) {
- composeSMaskBackdrop(maskData.data, r0, g0, b0);
- }
- composeFn(maskData.data, layerData.data, transferMap);
- maskCtx.putImageData(layerData, 0, row);
- }
- }
- function composeSMask(ctx, smask, layerCtx) {
- var mask = smask.canvas;
- var maskCtx = smask.context;
- ctx.setTransform(smask.scaleX, 0, 0, smask.scaleY, smask.offsetX, smask.offsetY);
- var backdrop = smask.backdrop || null;
- if (!smask.transferMap && WebGLUtils.isEnabled) {
- var composed = WebGLUtils.composeSMask(layerCtx.canvas, mask, {
- subtype: smask.subtype,
- backdrop: backdrop
- });
- ctx.setTransform(1, 0, 0, 1, 0, 0);
- ctx.drawImage(composed, smask.offsetX, smask.offsetY);
- return;
- }
- genericComposeSMask(maskCtx, layerCtx, mask.width, mask.height, smask.subtype, backdrop, smask.transferMap);
- ctx.drawImage(mask, 0, 0);
- }
- var LINE_CAP_STYLES = [
- 'butt',
- 'round',
- 'square'
- ];
- var LINE_JOIN_STYLES = [
- 'miter',
- 'round',
- 'bevel'
- ];
- var NORMAL_CLIP = {};
- var EO_CLIP = {};
- CanvasGraphics.prototype = {
- beginDrawing: function CanvasGraphics_beginDrawing(transform, viewport, transparency) {
- // For pdfs that use blend modes we have to clear the canvas else certain
- // blend modes can look wrong since we'd be blending with a white
- // backdrop. The problem with a transparent backdrop though is we then
- // don't get sub pixel anti aliasing on text, creating temporary
- // transparent canvas when we have blend modes.
- var width = this.ctx.canvas.width;
- var height = this.ctx.canvas.height;
- this.ctx.save();
- this.ctx.fillStyle = 'rgb(255, 255, 255)';
- this.ctx.fillRect(0, 0, width, height);
- this.ctx.restore();
- if (transparency) {
- var transparentCanvas = this.cachedCanvases.getCanvas('transparent', width, height, true);
- this.compositeCtx = this.ctx;
- this.transparentCanvas = transparentCanvas.canvas;
- this.ctx = transparentCanvas.context;
- this.ctx.save();
- // The transform can be applied before rendering, transferring it to
- // the new canvas.
- this.ctx.transform.apply(this.ctx, this.compositeCtx.mozCurrentTransform);
- }
- this.ctx.save();
- if (transform) {
- this.ctx.transform.apply(this.ctx, transform);
- }
- this.ctx.transform.apply(this.ctx, viewport.transform);
- this.baseTransform = this.ctx.mozCurrentTransform.slice();
- if (this.imageLayer) {
- this.imageLayer.beginLayout();
- }
- },
- executeOperatorList: function CanvasGraphics_executeOperatorList(operatorList, executionStartIdx, continueCallback, stepper) {
- var argsArray = operatorList.argsArray;
- var fnArray = operatorList.fnArray;
- var i = executionStartIdx || 0;
- var argsArrayLen = argsArray.length;
- // Sometimes the OperatorList to execute is empty.
- if (argsArrayLen === i) {
- return i;
- }
- var chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === 'function';
- var endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0;
- var steps = 0;
- var commonObjs = this.commonObjs;
- var objs = this.objs;
- var fnId;
- while (true) {
- if (stepper !== undefined && i === stepper.nextBreakPoint) {
- stepper.breakIt(i, continueCallback);
- return i;
- }
- fnId = fnArray[i];
- if (fnId !== OPS.dependency) {
- this[fnId].apply(this, argsArray[i]);
- } else {
- var deps = argsArray[i];
- for (var n = 0, nn = deps.length; n < nn; n++) {
- var depObjId = deps[n];
- var common = depObjId[0] === 'g' && depObjId[1] === '_';
- var objsPool = common ? commonObjs : objs;
- // If the promise isn't resolved yet, add the continueCallback
- // to the promise and bail out.
- if (!objsPool.isResolved(depObjId)) {
- objsPool.get(depObjId, continueCallback);
- return i;
- }
- }
- }
- i++;
- // If the entire operatorList was executed, stop as were done.
- if (i === argsArrayLen) {
- return i;
- }
- // If the execution took longer then a certain amount of time and
- // `continueCallback` is specified, interrupt the execution.
- if (chunkOperations && ++steps > EXECUTION_STEPS) {
- if (Date.now() > endTime) {
- continueCallback();
- return i;
- }
- steps = 0;
- }
- }
- },
- // If the operatorList isn't executed completely yet OR the execution
- // time was short enough, do another execution round.
- endDrawing: function CanvasGraphics_endDrawing() {
- // Finishing all opened operations such as SMask group painting.
- if (this.current.activeSMask !== null) {
- this.endSMaskGroup();
- }
- this.ctx.restore();
- if (this.transparentCanvas) {
- this.ctx = this.compositeCtx;
- this.ctx.save();
- this.ctx.setTransform(1, 0, 0, 1, 0, 0);
- // Avoid apply transform twice
- this.ctx.drawImage(this.transparentCanvas, 0, 0);
- this.ctx.restore();
- this.transparentCanvas = null;
- }
- this.cachedCanvases.clear();
- WebGLUtils.clear();
- if (this.imageLayer) {
- this.imageLayer.endLayout();
- }
- },
- // Graphics state
- setLineWidth: function CanvasGraphics_setLineWidth(width) {
- this.current.lineWidth = width;
- this.ctx.lineWidth = width;
- },
- setLineCap: function CanvasGraphics_setLineCap(style) {
- this.ctx.lineCap = LINE_CAP_STYLES[style];
- },
- setLineJoin: function CanvasGraphics_setLineJoin(style) {
- this.ctx.lineJoin = LINE_JOIN_STYLES[style];
- },
- setMiterLimit: function CanvasGraphics_setMiterLimit(limit) {
- this.ctx.miterLimit = limit;
- },
- setDash: function CanvasGraphics_setDash(dashArray, dashPhase) {
- var ctx = this.ctx;
- if (ctx.setLineDash !== undefined) {
- ctx.setLineDash(dashArray);
- ctx.lineDashOffset = dashPhase;
- }
- },
- setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) {
- },
- setFlatness: function CanvasGraphics_setFlatness(flatness) {
- },
- setGState: function CanvasGraphics_setGState(states) {
- for (var i = 0, ii = states.length; i < ii; i++) {
- var state = states[i];
- var key = state[0];
- var value = state[1];
- switch (key) {
- case 'LW':
- this.setLineWidth(value);
- break;
- case 'LC':
- this.setLineCap(value);
- break;
- case 'LJ':
- this.setLineJoin(value);
- break;
- case 'ML':
- this.setMiterLimit(value);
- break;
- case 'D':
- this.setDash(value[0], value[1]);
- break;
- case 'RI':
- this.setRenderingIntent(value);
- break;
- case 'FL':
- this.setFlatness(value);
- break;
- case 'Font':
- this.setFont(value[0], value[1]);
- break;
- case 'CA':
- this.current.strokeAlpha = state[1];
- break;
- case 'ca':
- this.current.fillAlpha = state[1];
- this.ctx.globalAlpha = state[1];
- break;
- case 'BM':
- if (value && value.name && value.name !== 'Normal') {
- var mode = value.name.replace(/([A-Z])/g, function (c) {
- return '-' + c.toLowerCase();
- }).substring(1);
- this.ctx.globalCompositeOperation = mode;
- if (this.ctx.globalCompositeOperation !== mode) {
- warn('globalCompositeOperation "' + mode + '" is not supported');
- }
- } else {
- this.ctx.globalCompositeOperation = 'source-over';
- }
- break;
- case 'SMask':
- if (this.current.activeSMask) {
- // If SMask is currrenly used, it needs to be suspended or
- // finished. Suspend only makes sense when at least one save()
- // was performed and state needs to be reverted on restore().
- if (this.stateStack.length > 0 && this.stateStack[this.stateStack.length - 1].activeSMask === this.current.activeSMask) {
- this.suspendSMaskGroup();
- } else {
- this.endSMaskGroup();
- }
- }
- this.current.activeSMask = value ? this.tempSMask : null;
- if (this.current.activeSMask) {
- this.beginSMaskGroup();
- }
- this.tempSMask = null;
- break;
- }
- }
- },
- beginSMaskGroup: function CanvasGraphics_beginSMaskGroup() {
- var activeSMask = this.current.activeSMask;
- var drawnWidth = activeSMask.canvas.width;
- var drawnHeight = activeSMask.canvas.height;
- var cacheId = 'smaskGroupAt' + this.groupLevel;
- var scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight, true);
- var currentCtx = this.ctx;
- var currentTransform = currentCtx.mozCurrentTransform;
- this.ctx.save();
- var groupCtx = scratchCanvas.context;
- groupCtx.scale(1 / activeSMask.scaleX, 1 / activeSMask.scaleY);
- groupCtx.translate(-activeSMask.offsetX, -activeSMask.offsetY);
- groupCtx.transform.apply(groupCtx, currentTransform);
- activeSMask.startTransformInverse = groupCtx.mozCurrentTransformInverse;
- copyCtxState(currentCtx, groupCtx);
- this.ctx = groupCtx;
- this.setGState([
- [
- 'BM',
- 'Normal'
- ],
- [
- 'ca',
- 1
- ],
- [
- 'CA',
- 1
- ]
- ]);
- this.groupStack.push(currentCtx);
- this.groupLevel++;
- },
- suspendSMaskGroup: function CanvasGraphics_endSMaskGroup() {
- // Similar to endSMaskGroup, the intermediate canvas has to be composed
- // and future ctx state restored.
- var groupCtx = this.ctx;
- this.groupLevel--;
- this.ctx = this.groupStack.pop();
- composeSMask(this.ctx, this.current.activeSMask, groupCtx);
- this.ctx.restore();
- this.ctx.save();
- // save is needed since SMask will be resumed.
- copyCtxState(groupCtx, this.ctx);
- // Saving state for resuming.
- this.current.resumeSMaskCtx = groupCtx;
- // Transform was changed in the SMask canvas, reflecting this change on
- // this.ctx.
- var deltaTransform = Util.transform(this.current.activeSMask.startTransformInverse, groupCtx.mozCurrentTransform);
- this.ctx.transform.apply(this.ctx, deltaTransform);
- // SMask was composed, the results at the groupCtx can be cleared.
- groupCtx.save();
- groupCtx.setTransform(1, 0, 0, 1, 0, 0);
- groupCtx.clearRect(0, 0, groupCtx.canvas.width, groupCtx.canvas.height);
- groupCtx.restore();
- },
- resumeSMaskGroup: function CanvasGraphics_endSMaskGroup() {
- // Resuming state saved by suspendSMaskGroup. We don't need to restore
- // any groupCtx state since restore() command (the only caller) will do
- // that for us. See also beginSMaskGroup.
- var groupCtx = this.current.resumeSMaskCtx;
- var currentCtx = this.ctx;
- this.ctx = groupCtx;
- this.groupStack.push(currentCtx);
- this.groupLevel++;
- },
- endSMaskGroup: function CanvasGraphics_endSMaskGroup() {
- var groupCtx = this.ctx;
- this.groupLevel--;
- this.ctx = this.groupStack.pop();
- composeSMask(this.ctx, this.current.activeSMask, groupCtx);
- this.ctx.restore();
- copyCtxState(groupCtx, this.ctx);
- // Transform was changed in the SMask canvas, reflecting this change on
- // this.ctx.
- var deltaTransform = Util.transform(this.current.activeSMask.startTransformInverse, groupCtx.mozCurrentTransform);
- this.ctx.transform.apply(this.ctx, deltaTransform);
- },
- save: function CanvasGraphics_save() {
- this.ctx.save();
- var old = this.current;
- this.stateStack.push(old);
- this.current = old.clone();
- this.current.resumeSMaskCtx = null;
- },
- restore: function CanvasGraphics_restore() {
- // SMask was suspended, we just need to resume it.
- if (this.current.resumeSMaskCtx) {
- this.resumeSMaskGroup();
- }
- // SMask has to be finished once there is no states that are using the
- // same SMask.
- if (this.current.activeSMask !== null && (this.stateStack.length === 0 || this.stateStack[this.stateStack.length - 1].activeSMask !== this.current.activeSMask)) {
- this.endSMaskGroup();
- }
- if (this.stateStack.length !== 0) {
- this.current = this.stateStack.pop();
- this.ctx.restore();
- // Ensure that the clipping path is reset (fixes issue6413.pdf).
- this.pendingClip = null;
- this.cachedGetSinglePixelWidth = null;
- }
- },
- transform: function CanvasGraphics_transform(a, b, c, d, e, f) {
- this.ctx.transform(a, b, c, d, e, f);
- this.cachedGetSinglePixelWidth = null;
- },
- // Path
- constructPath: function CanvasGraphics_constructPath(ops, args) {
- var ctx = this.ctx;
- var current = this.current;
- var x = current.x, y = current.y;
- for (var i = 0, j = 0, ii = ops.length; i < ii; i++) {
- switch (ops[i] | 0) {
- case OPS.rectangle:
- x = args[j++];
- y = args[j++];
- var width = args[j++];
- var height = args[j++];
- if (width === 0) {
- width = this.getSinglePixelWidth();
- }
- if (height === 0) {
- height = this.getSinglePixelWidth();
- }
- var xw = x + width;
- var yh = y + height;
- this.ctx.moveTo(x, y);
- this.ctx.lineTo(xw, y);
- this.ctx.lineTo(xw, yh);
- this.ctx.lineTo(x, yh);
- this.ctx.lineTo(x, y);
- this.ctx.closePath();
- break;
- case OPS.moveTo:
- x = args[j++];
- y = args[j++];
- ctx.moveTo(x, y);
- break;
- case OPS.lineTo:
- x = args[j++];
- y = args[j++];
- ctx.lineTo(x, y);
- break;
- case OPS.curveTo:
- x = args[j + 4];
- y = args[j + 5];
- ctx.bezierCurveTo(args[j], args[j + 1], args[j + 2], args[j + 3], x, y);
- j += 6;
- break;
- case OPS.curveTo2:
- ctx.bezierCurveTo(x, y, args[j], args[j + 1], args[j + 2], args[j + 3]);
- x = args[j + 2];
- y = args[j + 3];
- j += 4;
- break;
- case OPS.curveTo3:
- x = args[j + 2];
- y = args[j + 3];
- ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y);
- j += 4;
- break;
- case OPS.closePath:
- ctx.closePath();
- break;
- }
- }
- current.setCurrentPoint(x, y);
- },
- closePath: function CanvasGraphics_closePath() {
- this.ctx.closePath();
- },
- stroke: function CanvasGraphics_stroke(consumePath) {
- consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
- var ctx = this.ctx;
- var strokeColor = this.current.strokeColor;
- // Prevent drawing too thin lines by enforcing a minimum line width.
- ctx.lineWidth = Math.max(this.getSinglePixelWidth() * MIN_WIDTH_FACTOR, this.current.lineWidth);
- // For stroke we want to temporarily change the global alpha to the
- // stroking alpha.
- ctx.globalAlpha = this.current.strokeAlpha;
- if (strokeColor && strokeColor.hasOwnProperty('type') && strokeColor.type === 'Pattern') {
- // for patterns, we transform to pattern space, calculate
- // the pattern, call stroke, and restore to user space
- ctx.save();
- ctx.strokeStyle = strokeColor.getPattern(ctx, this);
- ctx.stroke();
- ctx.restore();
- } else {
- ctx.stroke();
- }
- if (consumePath) {
- this.consumePath();
- }
- // Restore the global alpha to the fill alpha
- ctx.globalAlpha = this.current.fillAlpha;
- },
- closeStroke: function CanvasGraphics_closeStroke() {
- this.closePath();
- this.stroke();
- },
- fill: function CanvasGraphics_fill(consumePath) {
- consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
- var ctx = this.ctx;
- var fillColor = this.current.fillColor;
- var isPatternFill = this.current.patternFill;
- var needRestore = false;
- if (isPatternFill) {
- ctx.save();
- if (this.baseTransform) {
- ctx.setTransform.apply(ctx, this.baseTransform);
- }
- ctx.fillStyle = fillColor.getPattern(ctx, this);
- needRestore = true;
- }
- if (this.pendingEOFill) {
- if (ctx.mozFillRule !== undefined) {
- ctx.mozFillRule = 'evenodd';
- ctx.fill();
- ctx.mozFillRule = 'nonzero';
- } else {
- ctx.fill('evenodd');
- }
- this.pendingEOFill = false;
- } else {
- ctx.fill();
- }
- if (needRestore) {
- ctx.restore();
- }
- if (consumePath) {
- this.consumePath();
- }
- },
- eoFill: function CanvasGraphics_eoFill() {
- this.pendingEOFill = true;
- this.fill();
- },
- fillStroke: function CanvasGraphics_fillStroke() {
- this.fill(false);
- this.stroke(false);
- this.consumePath();
- },
- eoFillStroke: function CanvasGraphics_eoFillStroke() {
- this.pendingEOFill = true;
- this.fillStroke();
- },
- closeFillStroke: function CanvasGraphics_closeFillStroke() {
- this.closePath();
- this.fillStroke();
- },
- closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() {
- this.pendingEOFill = true;
- this.closePath();
- this.fillStroke();
- },
- endPath: function CanvasGraphics_endPath() {
- this.consumePath();
- },
- // Clipping
- clip: function CanvasGraphics_clip() {
- this.pendingClip = NORMAL_CLIP;
- },
- eoClip: function CanvasGraphics_eoClip() {
- this.pendingClip = EO_CLIP;
- },
- // Text
- beginText: function CanvasGraphics_beginText() {
- this.current.textMatrix = IDENTITY_MATRIX;
- this.current.textMatrixScale = 1;
- this.current.x = this.current.lineX = 0;
- this.current.y = this.current.lineY = 0;
- },
- endText: function CanvasGraphics_endText() {
- var paths = this.pendingTextPaths;
- var ctx = this.ctx;
- if (paths === undefined) {
- ctx.beginPath();
- return;
- }
- ctx.save();
- ctx.beginPath();
- for (var i = 0; i < paths.length; i++) {
- var path = paths[i];
- ctx.setTransform.apply(ctx, path.transform);
- ctx.translate(path.x, path.y);
- path.addToPath(ctx, path.fontSize);
- }
- ctx.restore();
- ctx.clip();
- ctx.beginPath();
- delete this.pendingTextPaths;
- },
- setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) {
- this.current.charSpacing = spacing;
- },
- setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) {
- this.current.wordSpacing = spacing;
- },
- setHScale: function CanvasGraphics_setHScale(scale) {
- this.current.textHScale = scale / 100;
- },
- setLeading: function CanvasGraphics_setLeading(leading) {
- this.current.leading = -leading;
- },
- setFont: function CanvasGraphics_setFont(fontRefName, size) {
- var fontObj = this.commonObjs.get(fontRefName);
- var current = this.current;
- if (!fontObj) {
- error('Can\'t find font for ' + fontRefName);
- }
- current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix : FONT_IDENTITY_MATRIX;
- // A valid matrix needs all main diagonal elements to be non-zero
- // This also ensures we bypass FF bugzilla bug #719844.
- if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) {
- warn('Invalid font matrix for font ' + fontRefName);
- }
- // The spec for Tf (setFont) says that 'size' specifies the font 'scale',
- // and in some docs this can be negative (inverted x-y axes).
- if (size < 0) {
- size = -size;
- current.fontDirection = -1;
- } else {
- current.fontDirection = 1;
- }
- this.current.font = fontObj;
- this.current.fontSize = size;
- if (fontObj.isType3Font) {
- return;
- }
- // we don't need ctx.font for Type3 fonts
- var name = fontObj.loadedName || 'sans-serif';
- var bold = fontObj.black ? fontObj.bold ? '900' : 'bold' : fontObj.bold ? 'bold' : 'normal';
- var italic = fontObj.italic ? 'italic' : 'normal';
- var typeface = '"' + name + '", ' + fontObj.fallbackName;
- // Some font backends cannot handle fonts below certain size.
- // Keeping the font at minimal size and using the fontSizeScale to change
- // the current transformation matrix before the fillText/strokeText.
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=726227
- var browserFontSize = size < MIN_FONT_SIZE ? MIN_FONT_SIZE : size > MAX_FONT_SIZE ? MAX_FONT_SIZE : size;
- this.current.fontSizeScale = size / browserFontSize;
- var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface;
- this.ctx.font = rule;
- },
- setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) {
- this.current.textRenderingMode = mode;
- },
- setTextRise: function CanvasGraphics_setTextRise(rise) {
- this.current.textRise = rise;
- },
- moveText: function CanvasGraphics_moveText(x, y) {
- this.current.x = this.current.lineX += x;
- this.current.y = this.current.lineY += y;
- },
- setLeadingMoveText: function CanvasGraphics_setLeadingMoveText(x, y) {
- this.setLeading(-y);
- this.moveText(x, y);
- },
- setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) {
- this.current.textMatrix = [
- a,
- b,
- c,
- d,
- e,
- f
- ];
- this.current.textMatrixScale = Math.sqrt(a * a + b * b);
- this.current.x = this.current.lineX = 0;
- this.current.y = this.current.lineY = 0;
- },
- nextLine: function CanvasGraphics_nextLine() {
- this.moveText(0, this.current.leading);
- },
- paintChar: function CanvasGraphics_paintChar(character, x, y) {
- var ctx = this.ctx;
- var current = this.current;
- var font = current.font;
- var textRenderingMode = current.textRenderingMode;
- var fontSize = current.fontSize / current.fontSizeScale;
- var fillStrokeMode = textRenderingMode & TextRenderingMode.FILL_STROKE_MASK;
- var isAddToPathSet = !!(textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG);
- var addToPath;
- if (font.disableFontFace || isAddToPathSet) {
- addToPath = font.getPathGenerator(this.commonObjs, character);
- }
- if (font.disableFontFace) {
- ctx.save();
- ctx.translate(x, y);
- ctx.beginPath();
- addToPath(ctx, fontSize);
- if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
- ctx.fill();
- }
- if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
- ctx.stroke();
- }
- ctx.restore();
- } else {
- if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
- ctx.fillText(character, x, y);
- }
- if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
- ctx.strokeText(character, x, y);
- }
- }
- if (isAddToPathSet) {
- var paths = this.pendingTextPaths || (this.pendingTextPaths = []);
- paths.push({
- transform: ctx.mozCurrentTransform,
- x: x,
- y: y,
- fontSize: fontSize,
- addToPath: addToPath
- });
- }
- },
- get isFontSubpixelAAEnabled() {
- // Checks if anti-aliasing is enabled when scaled text is painted.
- // On Windows GDI scaled fonts looks bad.
- var ctx = document.createElement('canvas').getContext('2d');
- ctx.scale(1.5, 1);
- ctx.fillText('I', 0, 10);
- var data = ctx.getImageData(0, 0, 10, 10).data;
- var enabled = false;
- for (var i = 3; i < data.length; i += 4) {
- if (data[i] > 0 && data[i] < 255) {
- enabled = true;
- break;
- }
- }
- return shadow(this, 'isFontSubpixelAAEnabled', enabled);
- },
- showText: function CanvasGraphics_showText(glyphs) {
- var current = this.current;
- var font = current.font;
- if (font.isType3Font) {
- return this.showType3Text(glyphs);
- }
- var fontSize = current.fontSize;
- if (fontSize === 0) {
- return;
- }
- var ctx = this.ctx;
- var fontSizeScale = current.fontSizeScale;
- var charSpacing = current.charSpacing;
- var wordSpacing = current.wordSpacing;
- var fontDirection = current.fontDirection;
- var textHScale = current.textHScale * fontDirection;
- var glyphsLength = glyphs.length;
- var vertical = font.vertical;
- var spacingDir = vertical ? 1 : -1;
- var defaultVMetrics = font.defaultVMetrics;
- var widthAdvanceScale = fontSize * current.fontMatrix[0];
- var simpleFillText = current.textRenderingMode === TextRenderingMode.FILL && !font.disableFontFace;
- ctx.save();
- ctx.transform.apply(ctx, current.textMatrix);
- ctx.translate(current.x, current.y + current.textRise);
- if (current.patternFill) {
- // TODO: Some shading patterns are not applied correctly to text,
- // e.g. issues 3988 and 5432, and ShowText-ShadingPattern.pdf.
- ctx.fillStyle = current.fillColor.getPattern(ctx, this);
- }
- if (fontDirection > 0) {
- ctx.scale(textHScale, -1);
- } else {
- ctx.scale(textHScale, 1);
- }
- var lineWidth = current.lineWidth;
- var scale = current.textMatrixScale;
- if (scale === 0 || lineWidth === 0) {
- var fillStrokeMode = current.textRenderingMode & TextRenderingMode.FILL_STROKE_MASK;
- if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
- this.cachedGetSinglePixelWidth = null;
- lineWidth = this.getSinglePixelWidth() * MIN_WIDTH_FACTOR;
- }
- } else {
- lineWidth /= scale;
- }
- if (fontSizeScale !== 1.0) {
- ctx.scale(fontSizeScale, fontSizeScale);
- lineWidth /= fontSizeScale;
- }
- ctx.lineWidth = lineWidth;
- var x = 0, i;
- for (i = 0; i < glyphsLength; ++i) {
- var glyph = glyphs[i];
- if (isNum(glyph)) {
- x += spacingDir * glyph * fontSize / 1000;
- continue;
- }
- var restoreNeeded = false;
- var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
- var character = glyph.fontChar;
- var accent = glyph.accent;
- var scaledX, scaledY, scaledAccentX, scaledAccentY;
- var width = glyph.width;
- if (vertical) {
- var vmetric, vx, vy;
- vmetric = glyph.vmetric || defaultVMetrics;
- vx = glyph.vmetric ? vmetric[1] : width * 0.5;
- vx = -vx * widthAdvanceScale;
- vy = vmetric[2] * widthAdvanceScale;
- width = vmetric ? -vmetric[0] : width;
- scaledX = vx / fontSizeScale;
- scaledY = (x + vy) / fontSizeScale;
- } else {
- scaledX = x / fontSizeScale;
- scaledY = 0;
- }
- if (font.remeasure && width > 0) {
- // Some standard fonts may not have the exact width: rescale per
- // character if measured width is greater than expected glyph width
- // and subpixel-aa is enabled, otherwise just center the glyph.
- var measuredWidth = ctx.measureText(character).width * 1000 / fontSize * fontSizeScale;
- if (width < measuredWidth && this.isFontSubpixelAAEnabled) {
- var characterScaleX = width / measuredWidth;
- restoreNeeded = true;
- ctx.save();
- ctx.scale(characterScaleX, 1);
- scaledX /= characterScaleX;
- } else if (width !== measuredWidth) {
- scaledX += (width - measuredWidth) / 2000 * fontSize / fontSizeScale;
- }
- }
- // Only attempt to draw the glyph if it is actually in the embedded font
- // file or if there isn't a font file so the fallback font is shown.
- if (glyph.isInFont || font.missingFile) {
- if (simpleFillText && !accent) {
- // common case
- ctx.fillText(character, scaledX, scaledY);
- } else {
- this.paintChar(character, scaledX, scaledY);
- if (accent) {
- scaledAccentX = scaledX + accent.offset.x / fontSizeScale;
- scaledAccentY = scaledY - accent.offset.y / fontSizeScale;
- this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY);
- }
- }
- }
- var charWidth = width * widthAdvanceScale + spacing * fontDirection;
- x += charWidth;
- if (restoreNeeded) {
- ctx.restore();
- }
- }
- if (vertical) {
- current.y -= x * textHScale;
- } else {
- current.x += x * textHScale;
- }
- ctx.restore();
- },
- showType3Text: function CanvasGraphics_showType3Text(glyphs) {
- // Type3 fonts - each glyph is a "mini-PDF"
- var ctx = this.ctx;
- var current = this.current;
- var font = current.font;
- var fontSize = current.fontSize;
- var fontDirection = current.fontDirection;
- var spacingDir = font.vertical ? 1 : -1;
- var charSpacing = current.charSpacing;
- var wordSpacing = current.wordSpacing;
- var textHScale = current.textHScale * fontDirection;
- var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
- var glyphsLength = glyphs.length;
- var isTextInvisible = current.textRenderingMode === TextRenderingMode.INVISIBLE;
- var i, glyph, width, spacingLength;
- if (isTextInvisible || fontSize === 0) {
- return;
- }
- this.cachedGetSinglePixelWidth = null;
- ctx.save();
- ctx.transform.apply(ctx, current.textMatrix);
- ctx.translate(current.x, current.y);
- ctx.scale(textHScale, fontDirection);
- for (i = 0; i < glyphsLength; ++i) {
- glyph = glyphs[i];
- if (isNum(glyph)) {
- spacingLength = spacingDir * glyph * fontSize / 1000;
- this.ctx.translate(spacingLength, 0);
- current.x += spacingLength * textHScale;
- continue;
- }
- var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
- var operatorList = font.charProcOperatorList[glyph.operatorListId];
- if (!operatorList) {
- warn('Type3 character \"' + glyph.operatorListId + '\" is not available');
- continue;
- }
- this.processingType3 = glyph;
- this.save();
- ctx.scale(fontSize, fontSize);
- ctx.transform.apply(ctx, fontMatrix);
- this.executeOperatorList(operatorList);
- this.restore();
- var transformed = Util.applyTransform([
- glyph.width,
- 0
- ], fontMatrix);
- width = transformed[0] * fontSize + spacing;
- ctx.translate(width, 0);
- current.x += width * textHScale;
- }
- ctx.restore();
- this.processingType3 = null;
- },
- // Type3 fonts
- setCharWidth: function CanvasGraphics_setCharWidth(xWidth, yWidth) {
- },
- setCharWidthAndBounds: function CanvasGraphics_setCharWidthAndBounds(xWidth, yWidth, llx, lly, urx, ury) {
- // TODO According to the spec we're also suppose to ignore any operators
- // that set color or include images while processing this type3 font.
- this.ctx.rect(llx, lly, urx - llx, ury - lly);
- this.clip();
- this.endPath();
- },
- // Color
- getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR) {
- var pattern;
- if (IR[0] === 'TilingPattern') {
- var color = IR[1];
- var baseTransform = this.baseTransform || this.ctx.mozCurrentTransform.slice();
- var self = this;
- var canvasGraphicsFactory = {
- createCanvasGraphics: function (ctx) {
- return new CanvasGraphics(ctx, self.commonObjs, self.objs);
- }
- };
- pattern = new TilingPattern(IR, color, this.ctx, canvasGraphicsFactory, baseTransform);
- } else {
- pattern = getShadingPatternFromIR(IR);
- }
- return pattern;
- },
- setStrokeColorN: function CanvasGraphics_setStrokeColorN()
- /*...*/
- {
- this.current.strokeColor = this.getColorN_Pattern(arguments);
- },
- setFillColorN: function CanvasGraphics_setFillColorN()
- /*...*/
- {
- this.current.fillColor = this.getColorN_Pattern(arguments);
- this.current.patternFill = true;
- },
- setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
- var color = Util.makeCssRgb(r, g, b);
- this.ctx.strokeStyle = color;
- this.current.strokeColor = color;
- },
- setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) {
- var color = Util.makeCssRgb(r, g, b);
- this.ctx.fillStyle = color;
- this.current.fillColor = color;
- this.current.patternFill = false;
- },
- shadingFill: function CanvasGraphics_shadingFill(patternIR) {
- var ctx = this.ctx;
- this.save();
- var pattern = getShadingPatternFromIR(patternIR);
- ctx.fillStyle = pattern.getPattern(ctx, this, true);
- var inv = ctx.mozCurrentTransformInverse;
- if (inv) {
- var canvas = ctx.canvas;
- var width = canvas.width;
- var height = canvas.height;
- var bl = Util.applyTransform([
- 0,
- 0
- ], inv);
- var br = Util.applyTransform([
- 0,
- height
- ], inv);
- var ul = Util.applyTransform([
- width,
- 0
- ], inv);
- var ur = Util.applyTransform([
- width,
- height
- ], inv);
- var x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
- var y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
- var x1 = Math.max(bl[0], br[0], ul[0], ur[0]);
- var y1 = Math.max(bl[1], br[1], ul[1], ur[1]);
- this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0);
- } else {
- // HACK to draw the gradient onto an infinite rectangle.
- // PDF gradients are drawn across the entire image while
- // Canvas only allows gradients to be drawn in a rectangle
- // The following bug should allow us to remove this.
- // https://bugzilla.mozilla.org/show_bug.cgi?id=664884
- this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
- }
- this.restore();
- },
- // Images
- beginInlineImage: function CanvasGraphics_beginInlineImage() {
- error('Should not call beginInlineImage');
- },
- beginImageData: function CanvasGraphics_beginImageData() {
- error('Should not call beginImageData');
- },
- paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix, bbox) {
- this.save();
- this.baseTransformStack.push(this.baseTransform);
- if (isArray(matrix) && 6 === matrix.length) {
- this.transform.apply(this, matrix);
- }
- this.baseTransform = this.ctx.mozCurrentTransform;
- if (isArray(bbox) && 4 === bbox.length) {
- var width = bbox[2] - bbox[0];
- var height = bbox[3] - bbox[1];
- this.ctx.rect(bbox[0], bbox[1], width, height);
- this.clip();
- this.endPath();
- }
- },
- paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() {
- this.restore();
- this.baseTransform = this.baseTransformStack.pop();
- },
- beginGroup: function CanvasGraphics_beginGroup(group) {
- this.save();
- var currentCtx = this.ctx;
- // TODO non-isolated groups - according to Rik at adobe non-isolated
- // group results aren't usually that different and they even have tools
- // that ignore this setting. Notes from Rik on implementing:
- // - When you encounter an transparency group, create a new canvas with
- // the dimensions of the bbox
- // - copy the content from the previous canvas to the new canvas
- // - draw as usual
- // - remove the backdrop alpha:
- // alphaNew = 1 - (1 - alpha)/(1 - alphaBackdrop) with 'alpha' the alpha
- // value of your transparency group and 'alphaBackdrop' the alpha of the
- // backdrop
- // - remove background color:
- // colorNew = color - alphaNew *colorBackdrop /(1 - alphaNew)
- if (!group.isolated) {
- info('TODO: Support non-isolated groups.');
- }
- // TODO knockout - supposedly possible with the clever use of compositing
- // modes.
- if (group.knockout) {
- warn('Knockout groups not supported.');
- }
- var currentTransform = currentCtx.mozCurrentTransform;
- if (group.matrix) {
- currentCtx.transform.apply(currentCtx, group.matrix);
- }
- assert(group.bbox, 'Bounding box is required.');
- // Based on the current transform figure out how big the bounding box
- // will actually be.
- var bounds = Util.getAxialAlignedBoundingBox(group.bbox, currentCtx.mozCurrentTransform);
- // Clip the bounding box to the current canvas.
- var canvasBounds = [
- 0,
- 0,
- currentCtx.canvas.width,
- currentCtx.canvas.height
- ];
- bounds = Util.intersect(bounds, canvasBounds) || [
- 0,
- 0,
- 0,
- 0
- ];
- // Use ceil in case we're between sizes so we don't create canvas that is
- // too small and make the canvas at least 1x1 pixels.
- var offsetX = Math.floor(bounds[0]);
- var offsetY = Math.floor(bounds[1]);
- var drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1);
- var drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1);
- var scaleX = 1, scaleY = 1;
- if (drawnWidth > MAX_GROUP_SIZE) {
- scaleX = drawnWidth / MAX_GROUP_SIZE;
- drawnWidth = MAX_GROUP_SIZE;
- }
- if (drawnHeight > MAX_GROUP_SIZE) {
- scaleY = drawnHeight / MAX_GROUP_SIZE;
- drawnHeight = MAX_GROUP_SIZE;
- }
- var cacheId = 'groupAt' + this.groupLevel;
- if (group.smask) {
- // Using two cache entries is case if masks are used one after another.
- cacheId += '_smask_' + this.smaskCounter++ % 2;
- }
- var scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight, true);
- var groupCtx = scratchCanvas.context;
- // Since we created a new canvas that is just the size of the bounding box
- // we have to translate the group ctx.
- groupCtx.scale(1 / scaleX, 1 / scaleY);
- groupCtx.translate(-offsetX, -offsetY);
- groupCtx.transform.apply(groupCtx, currentTransform);
- if (group.smask) {
- // Saving state and cached mask to be used in setGState.
- this.smaskStack.push({
- canvas: scratchCanvas.canvas,
- context: groupCtx,
- offsetX: offsetX,
- offsetY: offsetY,
- scaleX: scaleX,
- scaleY: scaleY,
- subtype: group.smask.subtype,
- backdrop: group.smask.backdrop,
- transferMap: group.smask.transferMap || null,
- startTransformInverse: null
- });
- } else
- // used during suspend operation
- {
- // Setup the current ctx so when the group is popped we draw it at the
- // right location.
- currentCtx.setTransform(1, 0, 0, 1, 0, 0);
- currentCtx.translate(offsetX, offsetY);
- currentCtx.scale(scaleX, scaleY);
- }
- // The transparency group inherits all off the current graphics state
- // except the blend mode, soft mask, and alpha constants.
- copyCtxState(currentCtx, groupCtx);
- this.ctx = groupCtx;
- this.setGState([
- [
- 'BM',
- 'Normal'
- ],
- [
- 'ca',
- 1
- ],
- [
- 'CA',
- 1
- ]
- ]);
- this.groupStack.push(currentCtx);
- this.groupLevel++;
- // Reseting mask state, masks will be applied on restore of the group.
- this.current.activeSMask = null;
- },
- endGroup: function CanvasGraphics_endGroup(group) {
- this.groupLevel--;
- var groupCtx = this.ctx;
- this.ctx = this.groupStack.pop();
- // Turn off image smoothing to avoid sub pixel interpolation which can
- // look kind of blurry for some pdfs.
- if (this.ctx.imageSmoothingEnabled !== undefined) {
- this.ctx.imageSmoothingEnabled = false;
- } else {
- this.ctx.mozImageSmoothingEnabled = false;
- }
- if (group.smask) {
- this.tempSMask = this.smaskStack.pop();
- } else {
- this.ctx.drawImage(groupCtx.canvas, 0, 0);
- }
- this.restore();
- },
- beginAnnotations: function CanvasGraphics_beginAnnotations() {
- this.save();
- this.current = new CanvasExtraState();
- if (this.baseTransform) {
- this.ctx.setTransform.apply(this.ctx, this.baseTransform);
- }
- },
- endAnnotations: function CanvasGraphics_endAnnotations() {
- this.restore();
- },
- beginAnnotation: function CanvasGraphics_beginAnnotation(rect, transform, matrix) {
- this.save();
- if (isArray(rect) && 4 === rect.length) {
- var width = rect[2] - rect[0];
- var height = rect[3] - rect[1];
- this.ctx.rect(rect[0], rect[1], width, height);
- this.clip();
- this.endPath();
- }
- this.transform.apply(this, transform);
- this.transform.apply(this, matrix);
- },
- endAnnotation: function CanvasGraphics_endAnnotation() {
- this.restore();
- },
- paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
- var domImage = this.objs.get(objId);
- if (!domImage) {
- warn('Dependent image isn\'t ready yet');
- return;
- }
- this.save();
- var ctx = this.ctx;
- // scale the image to the unit square
- ctx.scale(1 / w, -1 / h);
- ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height, 0, -h, w, h);
- if (this.imageLayer) {
- var currentTransform = ctx.mozCurrentTransformInverse;
- var position = this.getCanvasPosition(0, 0);
- this.imageLayer.appendImage({
- objId: objId,
- left: position[0],
- top: position[1],
- width: w / currentTransform[0],
- height: h / currentTransform[3]
- });
- }
- this.restore();
- },
- paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) {
- var ctx = this.ctx;
- var width = img.width, height = img.height;
- var fillColor = this.current.fillColor;
- var isPatternFill = this.current.patternFill;
- var glyph = this.processingType3;
- if (COMPILE_TYPE3_GLYPHS && glyph && glyph.compiled === undefined) {
- if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) {
- glyph.compiled = compileType3Glyph({
- data: img.data,
- width: width,
- height: height
- });
- } else {
- glyph.compiled = null;
- }
- }
- if (glyph && glyph.compiled) {
- glyph.compiled(ctx);
- return;
- }
- var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
- var maskCtx = maskCanvas.context;
- maskCtx.save();
- putBinaryImageMask(maskCtx, img);
- maskCtx.globalCompositeOperation = 'source-in';
- maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
- maskCtx.fillRect(0, 0, width, height);
- maskCtx.restore();
- this.paintInlineImageXObject(maskCanvas.canvas);
- },
- paintImageMaskXObjectRepeat: function CanvasGraphics_paintImageMaskXObjectRepeat(imgData, scaleX, scaleY, positions) {
- var width = imgData.width;
- var height = imgData.height;
- var fillColor = this.current.fillColor;
- var isPatternFill = this.current.patternFill;
- var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
- var maskCtx = maskCanvas.context;
- maskCtx.save();
- putBinaryImageMask(maskCtx, imgData);
- maskCtx.globalCompositeOperation = 'source-in';
- maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
- maskCtx.fillRect(0, 0, width, height);
- maskCtx.restore();
- var ctx = this.ctx;
- for (var i = 0, ii = positions.length; i < ii; i += 2) {
- ctx.save();
- ctx.transform(scaleX, 0, 0, scaleY, positions[i], positions[i + 1]);
- ctx.scale(1, -1);
- ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
- ctx.restore();
- }
- },
- paintImageMaskXObjectGroup: function CanvasGraphics_paintImageMaskXObjectGroup(images) {
- var ctx = this.ctx;
- var fillColor = this.current.fillColor;
- var isPatternFill = this.current.patternFill;
- for (var i = 0, ii = images.length; i < ii; i++) {
- var image = images[i];
- var width = image.width, height = image.height;
- var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
- var maskCtx = maskCanvas.context;
- maskCtx.save();
- putBinaryImageMask(maskCtx, image);
- maskCtx.globalCompositeOperation = 'source-in';
- maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
- maskCtx.fillRect(0, 0, width, height);
- maskCtx.restore();
- ctx.save();
- ctx.transform.apply(ctx, image.transform);
- ctx.scale(1, -1);
- ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
- ctx.restore();
- }
- },
- paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
- var imgData = this.objs.get(objId);
- if (!imgData) {
- warn('Dependent image isn\'t ready yet');
- return;
- }
- this.paintInlineImageXObject(imgData);
- },
- paintImageXObjectRepeat: function CanvasGraphics_paintImageXObjectRepeat(objId, scaleX, scaleY, positions) {
- var imgData = this.objs.get(objId);
- if (!imgData) {
- warn('Dependent image isn\'t ready yet');
- return;
- }
- var width = imgData.width;
- var height = imgData.height;
- var map = [];
- for (var i = 0, ii = positions.length; i < ii; i += 2) {
- map.push({
- transform: [
- scaleX,
- 0,
- 0,
- scaleY,
- positions[i],
- positions[i + 1]
- ],
- x: 0,
- y: 0,
- w: width,
- h: height
- });
- }
- this.paintInlineImageXObjectGroup(imgData, map);
- },
- paintInlineImageXObject: function CanvasGraphics_paintInlineImageXObject(imgData) {
- var width = imgData.width;
- var height = imgData.height;
- var ctx = this.ctx;
- this.save();
- // scale the image to the unit square
- ctx.scale(1 / width, -1 / height);
- var currentTransform = ctx.mozCurrentTransformInverse;
- var a = currentTransform[0], b = currentTransform[1];
- var widthScale = Math.max(Math.sqrt(a * a + b * b), 1);
- var c = currentTransform[2], d = currentTransform[3];
- var heightScale = Math.max(Math.sqrt(c * c + d * d), 1);
- var imgToPaint, tmpCanvas;
- // instanceof HTMLElement does not work in jsdom node.js module
- if (imgData instanceof HTMLElement || !imgData.data) {
- imgToPaint = imgData;
- } else {
- tmpCanvas = this.cachedCanvases.getCanvas('inlineImage', width, height);
- var tmpCtx = tmpCanvas.context;
- putBinaryImageData(tmpCtx, imgData);
- imgToPaint = tmpCanvas.canvas;
- }
- var paintWidth = width, paintHeight = height;
- var tmpCanvasId = 'prescale1';
- // Vertial or horizontal scaling shall not be more than 2 to not loose the
- // pixels during drawImage operation, painting on the temporary canvas(es)
- // that are twice smaller in size
- while (widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1) {
- var newWidth = paintWidth, newHeight = paintHeight;
- if (widthScale > 2 && paintWidth > 1) {
- newWidth = Math.ceil(paintWidth / 2);
- widthScale /= paintWidth / newWidth;
- }
- if (heightScale > 2 && paintHeight > 1) {
- newHeight = Math.ceil(paintHeight / 2);
- heightScale /= paintHeight / newHeight;
- }
- tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight);
- tmpCtx = tmpCanvas.context;
- tmpCtx.clearRect(0, 0, newWidth, newHeight);
- tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight);
- imgToPaint = tmpCanvas.canvas;
- paintWidth = newWidth;
- paintHeight = newHeight;
- tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1';
- }
- ctx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, 0, -height, width, height);
- if (this.imageLayer) {
- var position = this.getCanvasPosition(0, -height);
- this.imageLayer.appendImage({
- imgData: imgData,
- left: position[0],
- top: position[1],
- width: width / currentTransform[0],
- height: height / currentTransform[3]
- });
- }
- this.restore();
- },
- paintInlineImageXObjectGroup: function CanvasGraphics_paintInlineImageXObjectGroup(imgData, map) {
- var ctx = this.ctx;
- var w = imgData.width;
- var h = imgData.height;
- var tmpCanvas = this.cachedCanvases.getCanvas('inlineImage', w, h);
- var tmpCtx = tmpCanvas.context;
- putBinaryImageData(tmpCtx, imgData);
- for (var i = 0, ii = map.length; i < ii; i++) {
- var entry = map[i];
- ctx.save();
- ctx.transform.apply(ctx, entry.transform);
- ctx.scale(1, -1);
- ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1);
- if (this.imageLayer) {
- var position = this.getCanvasPosition(entry.x, entry.y);
- this.imageLayer.appendImage({
- imgData: imgData,
- left: position[0],
- top: position[1],
- width: w,
- height: h
- });
- }
- ctx.restore();
- }
- },
- paintSolidColorImageMask: function CanvasGraphics_paintSolidColorImageMask() {
- this.ctx.fillRect(0, 0, 1, 1);
- },
- paintXObject: function CanvasGraphics_paintXObject() {
- warn('Unsupported \'paintXObject\' command.');
- },
- // Marked content
- markPoint: function CanvasGraphics_markPoint(tag) {
- },
- markPointProps: function CanvasGraphics_markPointProps(tag, properties) {
- },
- beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) {
- },
- beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps(tag, properties) {
- },
- endMarkedContent: function CanvasGraphics_endMarkedContent() {
- },
- // Compatibility
- beginCompat: function CanvasGraphics_beginCompat() {
- },
- endCompat: function CanvasGraphics_endCompat() {
- },
- // Helper functions
- consumePath: function CanvasGraphics_consumePath() {
- var ctx = this.ctx;
- if (this.pendingClip) {
- if (this.pendingClip === EO_CLIP) {
- if (ctx.mozFillRule !== undefined) {
- ctx.mozFillRule = 'evenodd';
- ctx.clip();
- ctx.mozFillRule = 'nonzero';
- } else {
- ctx.clip('evenodd');
- }
- } else {
- ctx.clip();
- }
- this.pendingClip = null;
- }
- ctx.beginPath();
- },
- getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) {
- if (this.cachedGetSinglePixelWidth === null) {
- // NOTE: The `save` and `restore` commands used below is a workaround
- // that is necessary in order to prevent `mozCurrentTransformInverse`
- // from intermittently returning incorrect values in Firefox, see:
- // https://github.com/mozilla/pdf.js/issues/7188.
- this.ctx.save();
- var inverse = this.ctx.mozCurrentTransformInverse;
- this.ctx.restore();
- // max of the current horizontal and vertical scale
- this.cachedGetSinglePixelWidth = Math.sqrt(Math.max(inverse[0] * inverse[0] + inverse[1] * inverse[1], inverse[2] * inverse[2] + inverse[3] * inverse[3]));
- }
- return this.cachedGetSinglePixelWidth;
- },
- getCanvasPosition: function CanvasGraphics_getCanvasPosition(x, y) {
- var transform = this.ctx.mozCurrentTransform;
- return [
- transform[0] * x + transform[2] * y + transform[4],
- transform[1] * x + transform[3] * y + transform[5]
- ];
- }
- };
- for (var op in OPS) {
- CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op];
- }
- return CanvasGraphics;
- }();
- exports.CanvasGraphics = CanvasGraphics;
- exports.createScratchCanvas = createScratchCanvas;
- }));
- (function (root, factory) {
- factory(root.pdfjsDisplayAPI = {}, root.pdfjsSharedUtil, root.pdfjsDisplayFontLoader, root.pdfjsDisplayCanvas, root.pdfjsDisplayMetadata, root.pdfjsDisplayDOMUtils);
- }(this, function (exports, sharedUtil, displayFontLoader, displayCanvas, displayMetadata, displayDOMUtils, amdRequire) {
- var InvalidPDFException = sharedUtil.InvalidPDFException;
- var MessageHandler = sharedUtil.MessageHandler;
- var MissingPDFException = sharedUtil.MissingPDFException;
- var PageViewport = sharedUtil.PageViewport;
- var PasswordResponses = sharedUtil.PasswordResponses;
- var PasswordException = sharedUtil.PasswordException;
- var StatTimer = sharedUtil.StatTimer;
- var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
- var UnknownErrorException = sharedUtil.UnknownErrorException;
- var Util = sharedUtil.Util;
- var createPromiseCapability = sharedUtil.createPromiseCapability;
- var error = sharedUtil.error;
- var deprecated = sharedUtil.deprecated;
- var getVerbosityLevel = sharedUtil.getVerbosityLevel;
- var info = sharedUtil.info;
- var isInt = sharedUtil.isInt;
- var isArray = sharedUtil.isArray;
- var isArrayBuffer = sharedUtil.isArrayBuffer;
- var isSameOrigin = sharedUtil.isSameOrigin;
- var loadJpegStream = sharedUtil.loadJpegStream;
- var stringToBytes = sharedUtil.stringToBytes;
- var globalScope = sharedUtil.globalScope;
- var warn = sharedUtil.warn;
- var FontFaceObject = displayFontLoader.FontFaceObject;
- var FontLoader = displayFontLoader.FontLoader;
- var CanvasGraphics = displayCanvas.CanvasGraphics;
- var createScratchCanvas = displayCanvas.createScratchCanvas;
- var Metadata = displayMetadata.Metadata;
- var getDefaultSetting = displayDOMUtils.getDefaultSetting;
- var DEFAULT_RANGE_CHUNK_SIZE = 65536;
- // 2^16 = 65536
- var isWorkerDisabled = false;
- var workerSrc;
- var isPostMessageTransfersDisabled = false;
- var fakeWorkerFilesLoader = null;
- var useRequireEnsure = false;
- /**
- * Document initialization / loading parameters object.
- *
- * @typedef {Object} DocumentInitParameters
- * @property {string} url - The URL of the PDF.
- * @property {TypedArray|Array|string} data - Binary PDF data. Use typed arrays
- * (Uint8Array) to improve the memory usage. If PDF data is BASE64-encoded,
- * use atob() to convert it to a binary string first.
- * @property {Object} httpHeaders - Basic authentication headers.
- * @property {boolean} withCredentials - Indicates whether or not cross-site
- * Access-Control requests should be made using credentials such as cookies
- * or authorization headers. The default is false.
- * @property {string} password - For decrypting password-protected PDFs.
- * @property {TypedArray} initialData - A typed array with the first portion or
- * all of the pdf data. Used by the extension since some data is already
- * loaded before the switch to range requests.
- * @property {number} length - The PDF file length. It's used for progress
- * reports and range requests operations.
- * @property {PDFDataRangeTransport} range
- * @property {number} rangeChunkSize - Optional parameter to specify
- * maximum number of bytes fetched per range request. The default value is
- * 2^16 = 65536.
- * @property {PDFWorker} worker - The worker that will be used for the loading
- * and parsing of the PDF data.
- * @property {string} docBaseUrl - (optional) The base URL of the document,
- * used when attempting to recover valid absolute URLs for annotations, and
- * outline items, that (incorrectly) only specify relative URLs.
- */
- /**
- * @typedef {Object} PDFDocumentStats
- * @property {Array} streamTypes - Used stream types in the document (an item
- * is set to true if specific stream ID was used in the document).
- * @property {Array} fontTypes - Used font type in the document (an item is set
- * to true if specific font ID was used in the document).
- */
- /**
- * This is the main entry point for loading a PDF and interacting with it.
- * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR)
- * is used, which means it must follow the same origin rules that any XHR does
- * e.g. No cross domain requests without CORS.
- *
- * @param {string|TypedArray|DocumentInitParameters|PDFDataRangeTransport} src
- * Can be a url to where a PDF is located, a typed array (Uint8Array)
- * already populated with data or parameter object.
- *
- * @param {PDFDataRangeTransport} pdfDataRangeTransport (deprecated) It is used
- * if you want to manually serve range requests for data in the PDF.
- *
- * @param {function} passwordCallback (deprecated) It is used to request a
- * password if wrong or no password was provided. The callback receives two
- * parameters: function that needs to be called with new password and reason
- * (see {PasswordResponses}).
- *
- * @param {function} progressCallback (deprecated) It is used to be able to
- * monitor the loading progress of the PDF file (necessary to implement e.g.
- * a loading bar). The callback receives an {Object} with the properties:
- * {number} loaded and {number} total.
- *
- * @return {PDFDocumentLoadingTask}
- */
- function getDocument(src, pdfDataRangeTransport, passwordCallback, progressCallback) {
- var task = new PDFDocumentLoadingTask();
- // Support of the obsolete arguments (for compatibility with API v1.0)
- if (arguments.length > 1) {
- deprecated('getDocument is called with pdfDataRangeTransport, ' + 'passwordCallback or progressCallback argument');
- }
- if (pdfDataRangeTransport) {
- if (!(pdfDataRangeTransport instanceof PDFDataRangeTransport)) {
- // Not a PDFDataRangeTransport instance, trying to add missing properties.
- pdfDataRangeTransport = Object.create(pdfDataRangeTransport);
- pdfDataRangeTransport.length = src.length;
- pdfDataRangeTransport.initialData = src.initialData;
- if (!pdfDataRangeTransport.abort) {
- pdfDataRangeTransport.abort = function () {
- };
- }
- }
- src = Object.create(src);
- src.range = pdfDataRangeTransport;
- }
- task.onPassword = passwordCallback || null;
- task.onProgress = progressCallback || null;
- var source;
- if (typeof src === 'string') {
- source = { url: src };
- } else if (isArrayBuffer(src)) {
- source = { data: src };
- } else if (src instanceof PDFDataRangeTransport) {
- source = { range: src };
- } else {
- if (typeof src !== 'object') {
- error('Invalid parameter in getDocument, need either Uint8Array, ' + 'string or a parameter object');
- }
- if (!src.url && !src.data && !src.range) {
- error('Invalid parameter object: need either .data, .range or .url');
- }
- source = src;
- }
- var params = {};
- var rangeTransport = null;
- var worker = null;
- for (var key in source) {
- if (key === 'url' && typeof window !== 'undefined') {
- // The full path is required in the 'url' field.
- params[key] = new URL(source[key], window.location).href;
- continue;
- } else if (key === 'range') {
- rangeTransport = source[key];
- continue;
- } else if (key === 'worker') {
- worker = source[key];
- continue;
- } else if (key === 'data' && !(source[key] instanceof Uint8Array)) {
- // Converting string or array-like data to Uint8Array.
- var pdfBytes = source[key];
- if (typeof pdfBytes === 'string') {
- params[key] = stringToBytes(pdfBytes);
- } else if (typeof pdfBytes === 'object' && pdfBytes !== null && !isNaN(pdfBytes.length)) {
- params[key] = new Uint8Array(pdfBytes);
- } else if (isArrayBuffer(pdfBytes)) {
- params[key] = new Uint8Array(pdfBytes);
- } else {
- error('Invalid PDF binary data: either typed array, string or ' + 'array-like object is expected in the data property.');
- }
- continue;
- }
- params[key] = source[key];
- }
- params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
- if (!worker) {
- // Worker was not provided -- creating and owning our own.
- worker = new PDFWorker();
- task._worker = worker;
- }
- var docId = task.docId;
- worker.promise.then(function () {
- if (task.destroyed) {
- throw new Error('Loading aborted');
- }
- return _fetchDocument(worker, params, rangeTransport, docId).then(function (workerId) {
- if (task.destroyed) {
- throw new Error('Loading aborted');
- }
- var messageHandler = new MessageHandler(docId, workerId, worker.port);
- var transport = new WorkerTransport(messageHandler, task, rangeTransport);
- task._transport = transport;
- messageHandler.send('Ready', null);
- });
- }).catch(task._capability.reject);
- return task;
- }
- /**
- * Starts fetching of specified PDF document/data.
- * @param {PDFWorker} worker
- * @param {Object} source
- * @param {PDFDataRangeTransport} pdfDataRangeTransport
- * @param {string} docId Unique document id, used as MessageHandler id.
- * @returns {Promise} The promise, which is resolved when worker id of
- * MessageHandler is known.
- * @private
- */
- function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
- if (worker.destroyed) {
- return Promise.reject(new Error('Worker was destroyed'));
- }
- source.disableAutoFetch = getDefaultSetting('disableAutoFetch');
- source.disableStream = getDefaultSetting('disableStream');
- source.chunkedViewerLoading = !!pdfDataRangeTransport;
- if (pdfDataRangeTransport) {
- source.length = pdfDataRangeTransport.length;
- source.initialData = pdfDataRangeTransport.initialData;
- }
- return worker.messageHandler.sendWithPromise('GetDocRequest', {
- docId: docId,
- source: source,
- disableRange: getDefaultSetting('disableRange'),
- maxImageSize: getDefaultSetting('maxImageSize'),
- cMapUrl: getDefaultSetting('cMapUrl'),
- cMapPacked: getDefaultSetting('cMapPacked'),
- disableFontFace: getDefaultSetting('disableFontFace'),
- disableCreateObjectURL: getDefaultSetting('disableCreateObjectURL'),
- postMessageTransfers: getDefaultSetting('postMessageTransfers') && !isPostMessageTransfersDisabled,
- docBaseUrl: source.docBaseUrl
- }).then(function (workerId) {
- if (worker.destroyed) {
- throw new Error('Worker was destroyed');
- }
- return workerId;
- });
- }
- /**
- * PDF document loading operation.
- * @class
- * @alias PDFDocumentLoadingTask
- */
- var PDFDocumentLoadingTask = function PDFDocumentLoadingTaskClosure() {
- var nextDocumentId = 0;
- /** @constructs PDFDocumentLoadingTask */
- function PDFDocumentLoadingTask() {
- this._capability = createPromiseCapability();
- this._transport = null;
- this._worker = null;
- /**
- * Unique document loading task id -- used in MessageHandlers.
- * @type {string}
- */
- this.docId = 'd' + nextDocumentId++;
- /**
- * Shows if loading task is destroyed.
- * @type {boolean}
- */
- this.destroyed = false;
- /**
- * Callback to request a password if wrong or no password was provided.
- * The callback receives two parameters: function that needs to be called
- * with new password and reason (see {PasswordResponses}).
- */
- this.onPassword = null;
- /**
- * Callback to be able to monitor the loading progress of the PDF file
- * (necessary to implement e.g. a loading bar). The callback receives
- * an {Object} with the properties: {number} loaded and {number} total.
- */
- this.onProgress = null;
- /**
- * Callback to when unsupported feature is used. The callback receives
- * an {UNSUPPORTED_FEATURES} argument.
- */
- this.onUnsupportedFeature = null;
- }
- PDFDocumentLoadingTask.prototype = /** @lends PDFDocumentLoadingTask.prototype */
- {
- /**
- * @return {Promise}
- */
- get promise() {
- return this._capability.promise;
- },
- /**
- * Aborts all network requests and destroys worker.
- * @return {Promise} A promise that is resolved after destruction activity
- * is completed.
- */
- destroy: function () {
- this.destroyed = true;
- var transportDestroyed = !this._transport ? Promise.resolve() : this._transport.destroy();
- return transportDestroyed.then(function () {
- this._transport = null;
- if (this._worker) {
- this._worker.destroy();
- this._worker = null;
- }
- }.bind(this));
- },
- /**
- * Registers callbacks to indicate the document loading completion.
- *
- * @param {function} onFulfilled The callback for the loading completion.
- * @param {function} onRejected The callback for the loading failure.
- * @return {Promise} A promise that is resolved after the onFulfilled or
- * onRejected callback.
- */
- then: function PDFDocumentLoadingTask_then(onFulfilled, onRejected) {
- return this.promise.then.apply(this.promise, arguments);
- }
- };
- return PDFDocumentLoadingTask;
- }();
- /**
- * Abstract class to support range requests file loading.
- * @class
- * @alias PDFDataRangeTransport
- * @param {number} length
- * @param {Uint8Array} initialData
- */
- var PDFDataRangeTransport = function pdfDataRangeTransportClosure() {
- function PDFDataRangeTransport(length, initialData) {
- this.length = length;
- this.initialData = initialData;
- this._rangeListeners = [];
- this._progressListeners = [];
- this._progressiveReadListeners = [];
- this._readyCapability = createPromiseCapability();
- }
- PDFDataRangeTransport.prototype = /** @lends PDFDataRangeTransport.prototype */
- {
- addRangeListener: function PDFDataRangeTransport_addRangeListener(listener) {
- this._rangeListeners.push(listener);
- },
- addProgressListener: function PDFDataRangeTransport_addProgressListener(listener) {
- this._progressListeners.push(listener);
- },
- addProgressiveReadListener: function PDFDataRangeTransport_addProgressiveReadListener(listener) {
- this._progressiveReadListeners.push(listener);
- },
- onDataRange: function PDFDataRangeTransport_onDataRange(begin, chunk) {
- var listeners = this._rangeListeners;
- for (var i = 0, n = listeners.length; i < n; ++i) {
- listeners[i](begin, chunk);
- }
- },
- onDataProgress: function PDFDataRangeTransport_onDataProgress(loaded) {
- this._readyCapability.promise.then(function () {
- var listeners = this._progressListeners;
- for (var i = 0, n = listeners.length; i < n; ++i) {
- listeners[i](loaded);
- }
- }.bind(this));
- },
- onDataProgressiveRead: function PDFDataRangeTransport_onDataProgress(chunk) {
- this._readyCapability.promise.then(function () {
- var listeners = this._progressiveReadListeners;
- for (var i = 0, n = listeners.length; i < n; ++i) {
- listeners[i](chunk);
- }
- }.bind(this));
- },
- transportReady: function PDFDataRangeTransport_transportReady() {
- this._readyCapability.resolve();
- },
- requestDataRange: function PDFDataRangeTransport_requestDataRange(begin, end) {
- throw new Error('Abstract method PDFDataRangeTransport.requestDataRange');
- },
- abort: function PDFDataRangeTransport_abort() {
- }
- };
- return PDFDataRangeTransport;
- }();
- /**
- * Proxy to a PDFDocument in the worker thread. Also, contains commonly used
- * properties that can be read synchronously.
- * @class
- * @alias PDFDocumentProxy
- */
- var PDFDocumentProxy = function PDFDocumentProxyClosure() {
- function PDFDocumentProxy(pdfInfo, transport, loadingTask) {
- this.pdfInfo = pdfInfo;
- this.transport = transport;
- this.loadingTask = loadingTask;
- }
- PDFDocumentProxy.prototype = /** @lends PDFDocumentProxy.prototype */
- {
- /**
- * @return {number} Total number of pages the PDF contains.
- */
- get numPages() {
- return this.pdfInfo.numPages;
- },
- /**
- * @return {string} A unique ID to identify a PDF. Not guaranteed to be
- * unique.
- */
- get fingerprint() {
- return this.pdfInfo.fingerprint;
- },
- /**
- * @param {number} pageNumber The page number to get. The first page is 1.
- * @return {Promise} A promise that is resolved with a {@link PDFPageProxy}
- * object.
- */
- getPage: function PDFDocumentProxy_getPage(pageNumber) {
- return this.transport.getPage(pageNumber);
- },
- /**
- * @param {{num: number, gen: number}} ref The page reference. Must have
- * the 'num' and 'gen' properties.
- * @return {Promise} A promise that is resolved with the page index that is
- * associated with the reference.
- */
- getPageIndex: function PDFDocumentProxy_getPageIndex(ref) {
- return this.transport.getPageIndex(ref);
- },
- /**
- * @return {Promise} A promise that is resolved with a lookup table for
- * mapping named destinations to reference numbers.
- *
- * This can be slow for large documents: use getDestination instead
- */
- getDestinations: function PDFDocumentProxy_getDestinations() {
- return this.transport.getDestinations();
- },
- /**
- * @param {string} id The named destination to get.
- * @return {Promise} A promise that is resolved with all information
- * of the given named destination.
- */
- getDestination: function PDFDocumentProxy_getDestination(id) {
- return this.transport.getDestination(id);
- },
- /**
- * @return {Promise} A promise that is resolved with:
- * an Array containing the pageLabels that correspond to the pageIndexes,
- * or `null` when no pageLabels are present in the PDF file.
- */
- getPageLabels: function PDFDocumentProxy_getPageLabels() {
- return this.transport.getPageLabels();
- },
- /**
- * @return {Promise} A promise that is resolved with a lookup table for
- * mapping named attachments to their content.
- */
- getAttachments: function PDFDocumentProxy_getAttachments() {
- return this.transport.getAttachments();
- },
- /**
- * @return {Promise} A promise that is resolved with an array of all the
- * JavaScript strings in the name tree.
- */
- getJavaScript: function PDFDocumentProxy_getJavaScript() {
- return this.transport.getJavaScript();
- },
- /**
- * @return {Promise} A promise that is resolved with an {Array} that is a
- * tree outline (if it has one) of the PDF. The tree is in the format of:
- * [
- * {
- * title: string,
- * bold: boolean,
- * italic: boolean,
- * color: rgb Uint8Array,
- * dest: dest obj,
- * url: string,
- * items: array of more items like this
- * },
- * ...
- * ].
- */
- getOutline: function PDFDocumentProxy_getOutline() {
- return this.transport.getOutline();
- },
- /**
- * @return {Promise} A promise that is resolved with an {Object} that has
- * info and metadata properties. Info is an {Object} filled with anything
- * available in the information dictionary and similarly metadata is a
- * {Metadata} object with information from the metadata section of the PDF.
- */
- getMetadata: function PDFDocumentProxy_getMetadata() {
- return this.transport.getMetadata();
- },
- /**
- * @return {Promise} A promise that is resolved with a TypedArray that has
- * the raw data from the PDF.
- */
- getData: function PDFDocumentProxy_getData() {
- return this.transport.getData();
- },
- /**
- * @return {Promise} A promise that is resolved when the document's data
- * is loaded. It is resolved with an {Object} that contains the length
- * property that indicates size of the PDF data in bytes.
- */
- getDownloadInfo: function PDFDocumentProxy_getDownloadInfo() {
- return this.transport.downloadInfoCapability.promise;
- },
- /**
- * @return {Promise} A promise this is resolved with current stats about
- * document structures (see {@link PDFDocumentStats}).
- */
- getStats: function PDFDocumentProxy_getStats() {
- return this.transport.getStats();
- },
- /**
- * Cleans up resources allocated by the document, e.g. created @font-face.
- */
- cleanup: function PDFDocumentProxy_cleanup() {
- this.transport.startCleanup();
- },
- /**
- * Destroys current document instance and terminates worker.
- */
- destroy: function PDFDocumentProxy_destroy() {
- return this.loadingTask.destroy();
- }
- };
- return PDFDocumentProxy;
- }();
- /**
- * Page getTextContent parameters.
- *
- * @typedef {Object} getTextContentParameters
- * @property {boolean} normalizeWhitespace - replaces all occurrences of
- * whitespace with standard spaces (0x20). The default value is `false`.
- * @property {boolean} disableCombineTextItems - do not attempt to combine
- * same line {@link TextItem}'s. The default value is `false`.
- */
- /**
- * Page text content.
- *
- * @typedef {Object} TextContent
- * @property {array} items - array of {@link TextItem}
- * @property {Object} styles - {@link TextStyles} objects, indexed by font name.
- */
- /**
- * Page text content part.
- *
- * @typedef {Object} TextItem
- * @property {string} str - text content.
- * @property {string} dir - text direction: 'ttb', 'ltr' or 'rtl'.
- * @property {array} transform - transformation matrix.
- * @property {number} width - width in device space.
- * @property {number} height - height in device space.
- * @property {string} fontName - font name used by pdf.js for converted font.
- */
- /**
- * Text style.
- *
- * @typedef {Object} TextStyle
- * @property {number} ascent - font ascent.
- * @property {number} descent - font descent.
- * @property {boolean} vertical - text is in vertical mode.
- * @property {string} fontFamily - possible font family
- */
- /**
- * Page annotation parameters.
- *
- * @typedef {Object} GetAnnotationsParameters
- * @property {string} intent - Determines the annotations that will be fetched,
- * can be either 'display' (viewable annotations) or 'print'
- * (printable annotations).
- * If the parameter is omitted, all annotations are fetched.
- */
- /**
- * Page render parameters.
- *
- * @typedef {Object} RenderParameters
- * @property {Object} canvasContext - A 2D context of a DOM Canvas object.
- * @property {PageViewport} viewport - Rendering viewport obtained by
- * calling of PDFPage.getViewport method.
- * @property {string} intent - Rendering intent, can be 'display' or 'print'
- * (default value is 'display').
- * @property {boolean} renderInteractiveForms - (optional) Whether or not
- * interactive form elements are rendered in the display
- * layer. If so, we do not render them on canvas as well.
- * @property {Array} transform - (optional) Additional transform, applied
- * just before viewport transform.
- * @property {Object} imageLayer - (optional) An object that has beginLayout,
- * endLayout and appendImage functions.
- * @property {function} continueCallback - (deprecated) A function that will be
- * called each time the rendering is paused. To continue
- * rendering call the function that is the first argument
- * to the callback.
- */
- /**
- * PDF page operator list.
- *
- * @typedef {Object} PDFOperatorList
- * @property {Array} fnArray - Array containing the operator functions.
- * @property {Array} argsArray - Array containing the arguments of the
- * functions.
- */
- /**
- * Proxy to a PDFPage in the worker thread.
- * @class
- * @alias PDFPageProxy
- */
- var PDFPageProxy = function PDFPageProxyClosure() {
- function PDFPageProxy(pageIndex, pageInfo, transport) {
- this.pageIndex = pageIndex;
- this.pageInfo = pageInfo;
- this.transport = transport;
- this.stats = new StatTimer();
- this.stats.enabled = getDefaultSetting('enableStats');
- this.commonObjs = transport.commonObjs;
- this.objs = new PDFObjects();
- this.cleanupAfterRender = false;
- this.pendingCleanup = false;
- this.intentStates = Object.create(null);
- this.destroyed = false;
- }
- PDFPageProxy.prototype = /** @lends PDFPageProxy.prototype */
- {
- /**
- * @return {number} Page number of the page. First page is 1.
- */
- get pageNumber() {
- return this.pageIndex + 1;
- },
- /**
- * @return {number} The number of degrees the page is rotated clockwise.
- */
- get rotate() {
- return this.pageInfo.rotate;
- },
- /**
- * @return {Object} The reference that points to this page. It has 'num' and
- * 'gen' properties.
- */
- get ref() {
- return this.pageInfo.ref;
- },
- /**
- * @return {Array} An array of the visible portion of the PDF page in the
- * user space units - [x1, y1, x2, y2].
- */
- get view() {
- return this.pageInfo.view;
- },
- /**
- * @param {number} scale The desired scale of the viewport.
- * @param {number} rotate Degrees to rotate the viewport. If omitted this
- * defaults to the page rotation.
- * @return {PageViewport} Contains 'width' and 'height' properties
- * along with transforms required for rendering.
- */
- getViewport: function PDFPageProxy_getViewport(scale, rotate) {
- if (arguments.length < 2) {
- rotate = this.rotate;
- }
- return new PageViewport(this.view, scale, rotate, 0, 0);
- },
- /**
- * @param {GetAnnotationsParameters} params - Annotation parameters.
- * @return {Promise} A promise that is resolved with an {Array} of the
- * annotation objects.
- */
- getAnnotations: function PDFPageProxy_getAnnotations(params) {
- var intent = params && params.intent || null;
- if (!this.annotationsPromise || this.annotationsIntent !== intent) {
- this.annotationsPromise = this.transport.getAnnotations(this.pageIndex, intent);
- this.annotationsIntent = intent;
- }
- return this.annotationsPromise;
- },
- /**
- * Begins the process of rendering a page to the desired context.
- * @param {RenderParameters} params Page render parameters.
- * @return {RenderTask} An object that contains the promise, which
- * is resolved when the page finishes rendering.
- */
- render: function PDFPageProxy_render(params) {
- var stats = this.stats;
- stats.time('Overall');
- // If there was a pending destroy cancel it so no cleanup happens during
- // this call to render.
- this.pendingCleanup = false;
- var renderingIntent = params.intent === 'print' ? 'print' : 'display';
- var renderInteractiveForms = params.renderInteractiveForms === true ? true : /* Default */
- false;
- if (!this.intentStates[renderingIntent]) {
- this.intentStates[renderingIntent] = Object.create(null);
- }
- var intentState = this.intentStates[renderingIntent];
- // If there's no displayReadyCapability yet, then the operatorList
- // was never requested before. Make the request and create the promise.
- if (!intentState.displayReadyCapability) {
- intentState.receivingOperatorList = true;
- intentState.displayReadyCapability = createPromiseCapability();
- intentState.operatorList = {
- fnArray: [],
- argsArray: [],
- lastChunk: false
- };
- this.stats.time('Page Request');
- this.transport.messageHandler.send('RenderPageRequest', {
- pageIndex: this.pageNumber - 1,
- intent: renderingIntent,
- renderInteractiveForms: renderInteractiveForms
- });
- }
- var internalRenderTask = new InternalRenderTask(complete, params, this.objs, this.commonObjs, intentState.operatorList, this.pageNumber);
- internalRenderTask.useRequestAnimationFrame = renderingIntent !== 'print';
- if (!intentState.renderTasks) {
- intentState.renderTasks = [];
- }
- intentState.renderTasks.push(internalRenderTask);
- var renderTask = internalRenderTask.task;
- // Obsolete parameter support
- if (params.continueCallback) {
- deprecated('render is used with continueCallback parameter');
- renderTask.onContinue = params.continueCallback;
- }
- var self = this;
- intentState.displayReadyCapability.promise.then(function pageDisplayReadyPromise(transparency) {
- if (self.pendingCleanup) {
- complete();
- return;
- }
- stats.time('Rendering');
- internalRenderTask.initializeGraphics(transparency);
- internalRenderTask.operatorListChanged();
- }, function pageDisplayReadPromiseError(reason) {
- complete(reason);
- });
- function complete(error) {
- var i = intentState.renderTasks.indexOf(internalRenderTask);
- if (i >= 0) {
- intentState.renderTasks.splice(i, 1);
- }
- if (self.cleanupAfterRender) {
- self.pendingCleanup = true;
- }
- self._tryCleanup();
- if (error) {
- internalRenderTask.capability.reject(error);
- } else {
- internalRenderTask.capability.resolve();
- }
- stats.timeEnd('Rendering');
- stats.timeEnd('Overall');
- }
- return renderTask;
- },
- /**
- * @return {Promise} A promise resolved with an {@link PDFOperatorList}
- * object that represents page's operator list.
- */
- getOperatorList: function PDFPageProxy_getOperatorList() {
- function operatorListChanged() {
- if (intentState.operatorList.lastChunk) {
- intentState.opListReadCapability.resolve(intentState.operatorList);
- var i = intentState.renderTasks.indexOf(opListTask);
- if (i >= 0) {
- intentState.renderTasks.splice(i, 1);
- }
- }
- }
- var renderingIntent = 'oplist';
- if (!this.intentStates[renderingIntent]) {
- this.intentStates[renderingIntent] = Object.create(null);
- }
- var intentState = this.intentStates[renderingIntent];
- var opListTask;
- if (!intentState.opListReadCapability) {
- opListTask = {};
- opListTask.operatorListChanged = operatorListChanged;
- intentState.receivingOperatorList = true;
- intentState.opListReadCapability = createPromiseCapability();
- intentState.renderTasks = [];
- intentState.renderTasks.push(opListTask);
- intentState.operatorList = {
- fnArray: [],
- argsArray: [],
- lastChunk: false
- };
- this.transport.messageHandler.send('RenderPageRequest', {
- pageIndex: this.pageIndex,
- intent: renderingIntent
- });
- }
- return intentState.opListReadCapability.promise;
- },
- /**
- * @param {getTextContentParameters} params - getTextContent parameters.
- * @return {Promise} That is resolved a {@link TextContent}
- * object that represent the page text content.
- */
- getTextContent: function PDFPageProxy_getTextContent(params) {
- return this.transport.messageHandler.sendWithPromise('GetTextContent', {
- pageIndex: this.pageNumber - 1,
- normalizeWhitespace: params && params.normalizeWhitespace === true ? true : /* Default */
- false,
- combineTextItems: params && params.disableCombineTextItems === true ? false : /* Default */
- true
- });
- },
- /**
- * Destroys page object.
- */
- _destroy: function PDFPageProxy_destroy() {
- this.destroyed = true;
- this.transport.pageCache[this.pageIndex] = null;
- var waitOn = [];
- Object.keys(this.intentStates).forEach(function (intent) {
- if (intent === 'oplist') {
- // Avoid errors below, since the renderTasks are just stubs.
- return;
- }
- var intentState = this.intentStates[intent];
- intentState.renderTasks.forEach(function (renderTask) {
- var renderCompleted = renderTask.capability.promise.catch(function () {
- });
- // ignoring failures
- waitOn.push(renderCompleted);
- renderTask.cancel();
- });
- }, this);
- this.objs.clear();
- this.annotationsPromise = null;
- this.pendingCleanup = false;
- return Promise.all(waitOn);
- },
- /**
- * Cleans up resources allocated by the page. (deprecated)
- */
- destroy: function () {
- deprecated('page destroy method, use cleanup() instead');
- this.cleanup();
- },
- /**
- * Cleans up resources allocated by the page.
- */
- cleanup: function PDFPageProxy_cleanup() {
- this.pendingCleanup = true;
- this._tryCleanup();
- },
- /**
- * For internal use only. Attempts to clean up if rendering is in a state
- * where that's possible.
- * @ignore
- */
- _tryCleanup: function PDFPageProxy_tryCleanup() {
- if (!this.pendingCleanup || Object.keys(this.intentStates).some(function (intent) {
- var intentState = this.intentStates[intent];
- return intentState.renderTasks.length !== 0 || intentState.receivingOperatorList;
- }, this)) {
- return;
- }
- Object.keys(this.intentStates).forEach(function (intent) {
- delete this.intentStates[intent];
- }, this);
- this.objs.clear();
- this.annotationsPromise = null;
- this.pendingCleanup = false;
- },
- /**
- * For internal use only.
- * @ignore
- */
- _startRenderPage: function PDFPageProxy_startRenderPage(transparency, intent) {
- var intentState = this.intentStates[intent];
- // TODO Refactor RenderPageRequest to separate rendering
- // and operator list logic
- if (intentState.displayReadyCapability) {
- intentState.displayReadyCapability.resolve(transparency);
- }
- },
- /**
- * For internal use only.
- * @ignore
- */
- _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk, intent) {
- var intentState = this.intentStates[intent];
- var i, ii;
- // Add the new chunk to the current operator list.
- for (i = 0, ii = operatorListChunk.length; i < ii; i++) {
- intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
- intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
- }
- intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
- // Notify all the rendering tasks there are more operators to be consumed.
- for (i = 0; i < intentState.renderTasks.length; i++) {
- intentState.renderTasks[i].operatorListChanged();
- }
- if (operatorListChunk.lastChunk) {
- intentState.receivingOperatorList = false;
- this._tryCleanup();
- }
- }
- };
- return PDFPageProxy;
- }();
- /**
- * PDF.js web worker abstraction, it controls instantiation of PDF documents and
- * WorkerTransport for them. If creation of a web worker is not possible,
- * a "fake" worker will be used instead.
- * @class
- */
- var PDFWorker = function PDFWorkerClosure() {
- var nextFakeWorkerId = 0;
- function getWorkerSrc() {
- if (typeof workerSrc !== 'undefined') {
- return workerSrc;
- }
- if (getDefaultSetting('workerSrc')) {
- return getDefaultSetting('workerSrc');
- }
- error('No PDFJS.workerSrc specified');
- }
- var fakeWorkerFilesLoadedCapability;
- // Loads worker code into main thread.
- function setupFakeWorkerGlobal() {
- var WorkerMessageHandler;
- if (fakeWorkerFilesLoadedCapability) {
- return fakeWorkerFilesLoadedCapability.promise;
- }
- fakeWorkerFilesLoadedCapability = createPromiseCapability();
- var loader = fakeWorkerFilesLoader || function (callback) {
- Util.loadScript(getWorkerSrc(), function () {
- callback(window.pdfjsDistBuildPdfWorker.WorkerMessageHandler);
- });
- };
- loader(fakeWorkerFilesLoadedCapability.resolve);
- return fakeWorkerFilesLoadedCapability.promise;
- }
- function FakeWorkerPort(defer) {
- this._listeners = [];
- this._defer = defer;
- this._deferred = Promise.resolve(undefined);
- }
- FakeWorkerPort.prototype = {
- postMessage: function (obj, transfers) {
- function cloneValue(value) {
- // Trying to perform a structured clone close to the spec, including
- // transfers.
- if (typeof value !== 'object' || value === null) {
- return value;
- }
- if (cloned.has(value)) {
- // already cloned the object
- return cloned.get(value);
- }
- var result;
- var buffer;
- if ((buffer = value.buffer) && isArrayBuffer(buffer)) {
- // We found object with ArrayBuffer (typed array).
- var transferable = transfers && transfers.indexOf(buffer) >= 0;
- if (value === buffer) {
- // Special case when we are faking typed arrays in compatibility.js.
- result = value;
- } else if (transferable) {
- result = new value.constructor(buffer, value.byteOffset, value.byteLength);
- } else {
- result = new value.constructor(value);
- }
- cloned.set(value, result);
- return result;
- }
- result = isArray(value) ? [] : {};
- cloned.set(value, result);
- // adding to cache now for cyclic references
- // Cloning all value and object properties, however ignoring properties
- // defined via getter.
- for (var i in value) {
- var desc, p = value;
- while (!(desc = Object.getOwnPropertyDescriptor(p, i))) {
- p = Object.getPrototypeOf(p);
- }
- if (typeof desc.value === 'undefined' || typeof desc.value === 'function') {
- continue;
- }
- result[i] = cloneValue(desc.value);
- }
- return result;
- }
- if (!this._defer) {
- this._listeners.forEach(function (listener) {
- listener.call(this, { data: obj });
- }, this);
- return;
- }
- var cloned = new WeakMap();
- var e = { data: cloneValue(obj) };
- this._deferred.then(function () {
- this._listeners.forEach(function (listener) {
- listener.call(this, e);
- }, this);
- }.bind(this));
- },
- addEventListener: function (name, listener) {
- this._listeners.push(listener);
- },
- removeEventListener: function (name, listener) {
- var i = this._listeners.indexOf(listener);
- this._listeners.splice(i, 1);
- },
- terminate: function () {
- this._listeners = [];
- }
- };
- function createCDNWrapper(url) {
- // We will rely on blob URL's property to specify origin.
- // We want this function to fail in case if createObjectURL or Blob do not
- // exist or fail for some reason -- our Worker creation will fail anyway.
- var wrapper = 'importScripts(\'' + url + '\');';
- return URL.createObjectURL(new Blob([wrapper]));
- }
- function PDFWorker(name) {
- this.name = name;
- this.destroyed = false;
- this._readyCapability = createPromiseCapability();
- this._port = null;
- this._webWorker = null;
- this._messageHandler = null;
- this._initialize();
- }
- PDFWorker.prototype = /** @lends PDFWorker.prototype */
- {
- get promise() {
- return this._readyCapability.promise;
- },
- get port() {
- return this._port;
- },
- get messageHandler() {
- return this._messageHandler;
- },
- _initialize: function PDFWorker_initialize() {
- // If worker support isn't disabled explicit and the browser has worker
- // support, create a new web worker and test if it/the browser fulfills
- // all requirements to run parts of pdf.js in a web worker.
- // Right now, the requirement is, that an Uint8Array is still an
- // Uint8Array as it arrives on the worker. (Chrome added this with v.15.)
- if (!isWorkerDisabled && !getDefaultSetting('disableWorker') && typeof Worker !== 'undefined') {
- var workerSrc = getWorkerSrc();
- try {
- // Some versions of FF can't create a worker on localhost, see:
- // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
- var worker = new Worker(workerSrc);
- var messageHandler = new MessageHandler('main', 'worker', worker);
- var terminateEarly = function () {
- worker.removeEventListener('error', onWorkerError);
- messageHandler.destroy();
- worker.terminate();
- if (this.destroyed) {
- this._readyCapability.reject(new Error('Worker was destroyed'));
- } else {
- // Fall back to fake worker if the termination is caused by an
- // error (e.g. NetworkError / SecurityError).
- this._setupFakeWorker();
- }
- }.bind(this);
- var onWorkerError = function (event) {
- if (!this._webWorker) {
- // Worker failed to initialize due to an error. Clean up and fall
- // back to the fake worker.
- terminateEarly();
- }
- }.bind(this);
- worker.addEventListener('error', onWorkerError);
- messageHandler.on('test', function PDFWorker_test(data) {
- worker.removeEventListener('error', onWorkerError);
- if (this.destroyed) {
- terminateEarly();
- return;
- }
- // worker was destroyed
- var supportTypedArray = data && data.supportTypedArray;
- if (supportTypedArray) {
- this._messageHandler = messageHandler;
- this._port = worker;
- this._webWorker = worker;
- if (!data.supportTransfers) {
- isPostMessageTransfersDisabled = true;
- }
- this._readyCapability.resolve();
- // Send global setting, e.g. verbosity level.
- messageHandler.send('configure', { verbosity: getVerbosityLevel() });
- } else {
- this._setupFakeWorker();
- messageHandler.destroy();
- worker.terminate();
- }
- }.bind(this));
- messageHandler.on('console_log', function (data) {
- console.log.apply(console, data);
- });
- messageHandler.on('console_error', function (data) {
- console.error.apply(console, data);
- });
- messageHandler.on('ready', function (data) {
- worker.removeEventListener('error', onWorkerError);
- if (this.destroyed) {
- terminateEarly();
- return;
- }
- // worker was destroyed
- try {
- sendTest();
- } catch (e) {
- // We need fallback to a faked worker.
- this._setupFakeWorker();
- }
- }.bind(this));
- var sendTest = function () {
- var postMessageTransfers = getDefaultSetting('postMessageTransfers') && !isPostMessageTransfersDisabled;
- var testObj = new Uint8Array([postMessageTransfers ? 255 : 0]);
- // Some versions of Opera throw a DATA_CLONE_ERR on serializing the
- // typed array. Also, checking if we can use transfers.
- try {
- messageHandler.send('test', testObj, [testObj.buffer]);
- } catch (ex) {
- info('Cannot use postMessage transfers');
- testObj[0] = 0;
- messageHandler.send('test', testObj);
- }
- };
- // It might take time for worker to initialize (especially when AMD
- // loader is used). We will try to send test immediately, and then
- // when 'ready' message will arrive. The worker shall process only
- // first received 'test'.
- sendTest();
- return;
- } catch (e) {
- info('The worker has been disabled.');
- }
- }
- // Either workers are disabled, not supported or have thrown an exception.
- // Thus, we fallback to a faked worker.
- this._setupFakeWorker();
- },
- _setupFakeWorker: function PDFWorker_setupFakeWorker() {
- if (!isWorkerDisabled && !getDefaultSetting('disableWorker')) {
- warn('Setting up fake worker.');
- isWorkerDisabled = true;
- }
- setupFakeWorkerGlobal().then(function (WorkerMessageHandler) {
- if (this.destroyed) {
- this._readyCapability.reject(new Error('Worker was destroyed'));
- return;
- }
- // We cannot turn on proper fake port simulation (this includes
- // structured cloning) when typed arrays are not supported. Relying
- // on a chance that messages will be sent in proper order.
- var isTypedArraysPresent = Uint8Array !== Float32Array;
- var port = new FakeWorkerPort(isTypedArraysPresent);
- this._port = port;
- // All fake workers use the same port, making id unique.
- var id = 'fake' + nextFakeWorkerId++;
- // If the main thread is our worker, setup the handling for the
- // messages -- the main thread sends to it self.
- var workerHandler = new MessageHandler(id + '_worker', id, port);
- WorkerMessageHandler.setup(workerHandler, port);
- var messageHandler = new MessageHandler(id, id + '_worker', port);
- this._messageHandler = messageHandler;
- this._readyCapability.resolve();
- }.bind(this));
- },
- /**
- * Destroys the worker instance.
- */
- destroy: function PDFWorker_destroy() {
- this.destroyed = true;
- if (this._webWorker) {
- // We need to terminate only web worker created resource.
- this._webWorker.terminate();
- this._webWorker = null;
- }
- this._port = null;
- if (this._messageHandler) {
- this._messageHandler.destroy();
- this._messageHandler = null;
- }
- }
- };
- return PDFWorker;
- }();
- /**
- * For internal use only.
- * @ignore
- */
- var WorkerTransport = function WorkerTransportClosure() {
- function WorkerTransport(messageHandler, loadingTask, pdfDataRangeTransport) {
- this.messageHandler = messageHandler;
- this.loadingTask = loadingTask;
- this.pdfDataRangeTransport = pdfDataRangeTransport;
- this.commonObjs = new PDFObjects();
- this.fontLoader = new FontLoader(loadingTask.docId);
- this.destroyed = false;
- this.destroyCapability = null;
- this.pageCache = [];
- this.pagePromises = [];
- this.downloadInfoCapability = createPromiseCapability();
- this.setupMessageHandler();
- }
- WorkerTransport.prototype = {
- destroy: function WorkerTransport_destroy() {
- if (this.destroyCapability) {
- return this.destroyCapability.promise;
- }
- this.destroyed = true;
- this.destroyCapability = createPromiseCapability();
- var waitOn = [];
- // We need to wait for all renderings to be completed, e.g.
- // timeout/rAF can take a long time.
- this.pageCache.forEach(function (page) {
- if (page) {
- waitOn.push(page._destroy());
- }
- });
- this.pageCache = [];
- this.pagePromises = [];
- var self = this;
- // We also need to wait for the worker to finish its long running tasks.
- var terminated = this.messageHandler.sendWithPromise('Terminate', null);
- waitOn.push(terminated);
- Promise.all(waitOn).then(function () {
- self.fontLoader.clear();
- if (self.pdfDataRangeTransport) {
- self.pdfDataRangeTransport.abort();
- self.pdfDataRangeTransport = null;
- }
- if (self.messageHandler) {
- self.messageHandler.destroy();
- self.messageHandler = null;
- }
- self.destroyCapability.resolve();
- }, this.destroyCapability.reject);
- return this.destroyCapability.promise;
- },
- setupMessageHandler: function WorkerTransport_setupMessageHandler() {
- var messageHandler = this.messageHandler;
- function updatePassword(password) {
- messageHandler.send('UpdatePassword', password);
- }
- var pdfDataRangeTransport = this.pdfDataRangeTransport;
- if (pdfDataRangeTransport) {
- pdfDataRangeTransport.addRangeListener(function (begin, chunk) {
- messageHandler.send('OnDataRange', {
- begin: begin,
- chunk: chunk
- });
- });
- pdfDataRangeTransport.addProgressListener(function (loaded) {
- messageHandler.send('OnDataProgress', { loaded: loaded });
- });
- pdfDataRangeTransport.addProgressiveReadListener(function (chunk) {
- messageHandler.send('OnDataRange', { chunk: chunk });
- });
- messageHandler.on('RequestDataRange', function transportDataRange(data) {
- pdfDataRangeTransport.requestDataRange(data.begin, data.end);
- }, this);
- }
- messageHandler.on('GetDoc', function transportDoc(data) {
- var pdfInfo = data.pdfInfo;
- this.numPages = data.pdfInfo.numPages;
- var loadingTask = this.loadingTask;
- var pdfDocument = new PDFDocumentProxy(pdfInfo, this, loadingTask);
- this.pdfDocument = pdfDocument;
- loadingTask._capability.resolve(pdfDocument);
- }, this);
- messageHandler.on('NeedPassword', function transportNeedPassword(exception) {
- var loadingTask = this.loadingTask;
- if (loadingTask.onPassword) {
- return loadingTask.onPassword(updatePassword, PasswordResponses.NEED_PASSWORD);
- }
- loadingTask._capability.reject(new PasswordException(exception.message, exception.code));
- }, this);
- messageHandler.on('IncorrectPassword', function transportIncorrectPassword(exception) {
- var loadingTask = this.loadingTask;
- if (loadingTask.onPassword) {
- return loadingTask.onPassword(updatePassword, PasswordResponses.INCORRECT_PASSWORD);
- }
- loadingTask._capability.reject(new PasswordException(exception.message, exception.code));
- }, this);
- messageHandler.on('InvalidPDF', function transportInvalidPDF(exception) {
- this.loadingTask._capability.reject(new InvalidPDFException(exception.message));
- }, this);
- messageHandler.on('MissingPDF', function transportMissingPDF(exception) {
- this.loadingTask._capability.reject(new MissingPDFException(exception.message));
- }, this);
- messageHandler.on('UnexpectedResponse', function transportUnexpectedResponse(exception) {
- this.loadingTask._capability.reject(new UnexpectedResponseException(exception.message, exception.status));
- }, this);
- messageHandler.on('UnknownError', function transportUnknownError(exception) {
- this.loadingTask._capability.reject(new UnknownErrorException(exception.message, exception.details));
- }, this);
- messageHandler.on('DataLoaded', function transportPage(data) {
- this.downloadInfoCapability.resolve(data);
- }, this);
- messageHandler.on('PDFManagerReady', function transportPage(data) {
- if (this.pdfDataRangeTransport) {
- this.pdfDataRangeTransport.transportReady();
- }
- }, this);
- messageHandler.on('StartRenderPage', function transportRender(data) {
- if (this.destroyed) {
- return;
- }
- // Ignore any pending requests if the worker was terminated.
- var page = this.pageCache[data.pageIndex];
- page.stats.timeEnd('Page Request');
- page._startRenderPage(data.transparency, data.intent);
- }, this);
- messageHandler.on('RenderPageChunk', function transportRender(data) {
- if (this.destroyed) {
- return;
- }
- // Ignore any pending requests if the worker was terminated.
- var page = this.pageCache[data.pageIndex];
- page._renderPageChunk(data.operatorList, data.intent);
- }, this);
- messageHandler.on('commonobj', function transportObj(data) {
- if (this.destroyed) {
- return;
- }
- // Ignore any pending requests if the worker was terminated.
- var id = data[0];
- var type = data[1];
- if (this.commonObjs.hasData(id)) {
- return;
- }
- switch (type) {
- case 'Font':
- var exportedData = data[2];
- if ('error' in exportedData) {
- var exportedError = exportedData.error;
- warn('Error during font loading: ' + exportedError);
- this.commonObjs.resolve(id, exportedError);
- break;
- }
- var fontRegistry = null;
- if (getDefaultSetting('pdfBug') && globalScope.FontInspector && globalScope['FontInspector'].enabled) {
- fontRegistry = {
- registerFont: function (font, url) {
- globalScope['FontInspector'].fontAdded(font, url);
- }
- };
- }
- var font = new FontFaceObject(exportedData, {
- isEvalSuported: getDefaultSetting('isEvalSupported'),
- disableFontFace: getDefaultSetting('disableFontFace'),
- fontRegistry: fontRegistry
- });
- this.fontLoader.bind([font], function fontReady(fontObjs) {
- this.commonObjs.resolve(id, font);
- }.bind(this));
- break;
- case 'FontPath':
- this.commonObjs.resolve(id, data[2]);
- break;
- default:
- error('Got unknown common object type ' + type);
- }
- }, this);
- messageHandler.on('obj', function transportObj(data) {
- if (this.destroyed) {
- return;
- }
- // Ignore any pending requests if the worker was terminated.
- var id = data[0];
- var pageIndex = data[1];
- var type = data[2];
- var pageProxy = this.pageCache[pageIndex];
- var imageData;
- if (pageProxy.objs.hasData(id)) {
- return;
- }
- switch (type) {
- case 'JpegStream':
- imageData = data[3];
- loadJpegStream(id, imageData, pageProxy.objs);
- break;
- case 'Image':
- imageData = data[3];
- pageProxy.objs.resolve(id, imageData);
- // heuristics that will allow not to store large data
- var MAX_IMAGE_SIZE_TO_STORE = 8000000;
- if (imageData && 'data' in imageData && imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) {
- pageProxy.cleanupAfterRender = true;
- }
- break;
- default:
- error('Got unknown object type ' + type);
- }
- }, this);
- messageHandler.on('DocProgress', function transportDocProgress(data) {
- if (this.destroyed) {
- return;
- }
- // Ignore any pending requests if the worker was terminated.
- var loadingTask = this.loadingTask;
- if (loadingTask.onProgress) {
- loadingTask.onProgress({
- loaded: data.loaded,
- total: data.total
- });
- }
- }, this);
- messageHandler.on('PageError', function transportError(data) {
- if (this.destroyed) {
- return;
- }
- // Ignore any pending requests if the worker was terminated.
- var page = this.pageCache[data.pageNum - 1];
- var intentState = page.intentStates[data.intent];
- if (intentState.displayReadyCapability) {
- intentState.displayReadyCapability.reject(data.error);
- } else {
- error(data.error);
- }
- if (intentState.operatorList) {
- // Mark operator list as complete.
- intentState.operatorList.lastChunk = true;
- for (var i = 0; i < intentState.renderTasks.length; i++) {
- intentState.renderTasks[i].operatorListChanged();
- }
- }
- }, this);
- messageHandler.on('UnsupportedFeature', function transportUnsupportedFeature(data) {
- if (this.destroyed) {
- return;
- }
- // Ignore any pending requests if the worker was terminated.
- var featureId = data.featureId;
- var loadingTask = this.loadingTask;
- if (loadingTask.onUnsupportedFeature) {
- loadingTask.onUnsupportedFeature(featureId);
- }
- _UnsupportedManager.notify(featureId);
- }, this);
- messageHandler.on('JpegDecode', function (data) {
- if (this.destroyed) {
- return Promise.reject(new Error('Worker was destroyed'));
- }
- var imageUrl = data[0];
- var components = data[1];
- if (components !== 3 && components !== 1) {
- return Promise.reject(new Error('Only 3 components or 1 component can be returned'));
- }
- return new Promise(function (resolve, reject) {
- var img = new Image();
- img.onload = function () {
- var width = img.width;
- var height = img.height;
- var size = width * height;
- var rgbaLength = size * 4;
- var buf = new Uint8Array(size * components);
- var tmpCanvas = createScratchCanvas(width, height);
- var tmpCtx = tmpCanvas.getContext('2d');
- tmpCtx.drawImage(img, 0, 0);
- var data = tmpCtx.getImageData(0, 0, width, height).data;
- var i, j;
- if (components === 3) {
- for (i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
- buf[j] = data[i];
- buf[j + 1] = data[i + 1];
- buf[j + 2] = data[i + 2];
- }
- } else if (components === 1) {
- for (i = 0, j = 0; i < rgbaLength; i += 4, j++) {
- buf[j] = data[i];
- }
- }
- resolve({
- data: buf,
- width: width,
- height: height
- });
- };
- img.onerror = function () {
- reject(new Error('JpegDecode failed to load image'));
- };
- img.src = imageUrl;
- });
- }, this);
- },
- getData: function WorkerTransport_getData() {
- return this.messageHandler.sendWithPromise('GetData', null);
- },
- getPage: function WorkerTransport_getPage(pageNumber, capability) {
- if (!isInt(pageNumber) || pageNumber <= 0 || pageNumber > this.numPages) {
- return Promise.reject(new Error('Invalid page request'));
- }
- var pageIndex = pageNumber - 1;
- if (pageIndex in this.pagePromises) {
- return this.pagePromises[pageIndex];
- }
- var promise = this.messageHandler.sendWithPromise('GetPage', { pageIndex: pageIndex }).then(function (pageInfo) {
- if (this.destroyed) {
- throw new Error('Transport destroyed');
- }
- var page = new PDFPageProxy(pageIndex, pageInfo, this);
- this.pageCache[pageIndex] = page;
- return page;
- }.bind(this));
- this.pagePromises[pageIndex] = promise;
- return promise;
- },
- getPageIndex: function WorkerTransport_getPageIndexByRef(ref) {
- return this.messageHandler.sendWithPromise('GetPageIndex', { ref: ref }).catch(function (reason) {
- return Promise.reject(new Error(reason));
- });
- },
- getAnnotations: function WorkerTransport_getAnnotations(pageIndex, intent) {
- return this.messageHandler.sendWithPromise('GetAnnotations', {
- pageIndex: pageIndex,
- intent: intent
- });
- },
- getDestinations: function WorkerTransport_getDestinations() {
- return this.messageHandler.sendWithPromise('GetDestinations', null);
- },
- getDestination: function WorkerTransport_getDestination(id) {
- return this.messageHandler.sendWithPromise('GetDestination', { id: id });
- },
- getPageLabels: function WorkerTransport_getPageLabels() {
- return this.messageHandler.sendWithPromise('GetPageLabels', null);
- },
- getAttachments: function WorkerTransport_getAttachments() {
- return this.messageHandler.sendWithPromise('GetAttachments', null);
- },
- getJavaScript: function WorkerTransport_getJavaScript() {
- return this.messageHandler.sendWithPromise('GetJavaScript', null);
- },
- getOutline: function WorkerTransport_getOutline() {
- return this.messageHandler.sendWithPromise('GetOutline', null);
- },
- getMetadata: function WorkerTransport_getMetadata() {
- return this.messageHandler.sendWithPromise('GetMetadata', null).then(function transportMetadata(results) {
- return {
- info: results[0],
- metadata: results[1] ? new Metadata(results[1]) : null
- };
- });
- },
- getStats: function WorkerTransport_getStats() {
- return this.messageHandler.sendWithPromise('GetStats', null);
- },
- startCleanup: function WorkerTransport_startCleanup() {
- this.messageHandler.sendWithPromise('Cleanup', null).then(function endCleanup() {
- for (var i = 0, ii = this.pageCache.length; i < ii; i++) {
- var page = this.pageCache[i];
- if (page) {
- page.cleanup();
- }
- }
- this.commonObjs.clear();
- this.fontLoader.clear();
- }.bind(this));
- }
- };
- return WorkerTransport;
- }();
- /**
- * A PDF document and page is built of many objects. E.g. there are objects
- * for fonts, images, rendering code and such. These objects might get processed
- * inside of a worker. The `PDFObjects` implements some basic functions to
- * manage these objects.
- * @ignore
- */
- var PDFObjects = function PDFObjectsClosure() {
- function PDFObjects() {
- this.objs = Object.create(null);
- }
- PDFObjects.prototype = {
- /**
- * Internal function.
- * Ensures there is an object defined for `objId`.
- */
- ensureObj: function PDFObjects_ensureObj(objId) {
- if (this.objs[objId]) {
- return this.objs[objId];
- }
- var obj = {
- capability: createPromiseCapability(),
- data: null,
- resolved: false
- };
- this.objs[objId] = obj;
- return obj;
- },
- /**
- * If called *without* callback, this returns the data of `objId` but the
- * object needs to be resolved. If it isn't, this function throws.
- *
- * If called *with* a callback, the callback is called with the data of the
- * object once the object is resolved. That means, if you call this
- * function and the object is already resolved, the callback gets called
- * right away.
- */
- get: function PDFObjects_get(objId, callback) {
- // If there is a callback, then the get can be async and the object is
- // not required to be resolved right now
- if (callback) {
- this.ensureObj(objId).capability.promise.then(callback);
- return null;
- }
- // If there isn't a callback, the user expects to get the resolved data
- // directly.
- var obj = this.objs[objId];
- // If there isn't an object yet or the object isn't resolved, then the
- // data isn't ready yet!
- if (!obj || !obj.resolved) {
- error('Requesting object that isn\'t resolved yet ' + objId);
- }
- return obj.data;
- },
- /**
- * Resolves the object `objId` with optional `data`.
- */
- resolve: function PDFObjects_resolve(objId, data) {
- var obj = this.ensureObj(objId);
- obj.resolved = true;
- obj.data = data;
- obj.capability.resolve(data);
- },
- isResolved: function PDFObjects_isResolved(objId) {
- var objs = this.objs;
- if (!objs[objId]) {
- return false;
- } else {
- return objs[objId].resolved;
- }
- },
- hasData: function PDFObjects_hasData(objId) {
- return this.isResolved(objId);
- },
- /**
- * Returns the data of `objId` if object exists, null otherwise.
- */
- getData: function PDFObjects_getData(objId) {
- var objs = this.objs;
- if (!objs[objId] || !objs[objId].resolved) {
- return null;
- } else {
- return objs[objId].data;
- }
- },
- clear: function PDFObjects_clear() {
- this.objs = Object.create(null);
- }
- };
- return PDFObjects;
- }();
- /**
- * Allows controlling of the rendering tasks.
- * @class
- * @alias RenderTask
- */
- var RenderTask = function RenderTaskClosure() {
- function RenderTask(internalRenderTask) {
- this._internalRenderTask = internalRenderTask;
- /**
- * Callback for incremental rendering -- a function that will be called
- * each time the rendering is paused. To continue rendering call the
- * function that is the first argument to the callback.
- * @type {function}
- */
- this.onContinue = null;
- }
- RenderTask.prototype = /** @lends RenderTask.prototype */
- {
- /**
- * Promise for rendering task completion.
- * @return {Promise}
- */
- get promise() {
- return this._internalRenderTask.capability.promise;
- },
- /**
- * Cancels the rendering task. If the task is currently rendering it will
- * not be cancelled until graphics pauses with a timeout. The promise that
- * this object extends will resolved when cancelled.
- */
- cancel: function RenderTask_cancel() {
- this._internalRenderTask.cancel();
- },
- /**
- * Registers callbacks to indicate the rendering task completion.
- *
- * @param {function} onFulfilled The callback for the rendering completion.
- * @param {function} onRejected The callback for the rendering failure.
- * @return {Promise} A promise that is resolved after the onFulfilled or
- * onRejected callback.
- */
- then: function RenderTask_then(onFulfilled, onRejected) {
- return this.promise.then.apply(this.promise, arguments);
- }
- };
- return RenderTask;
- }();
- /**
- * For internal use only.
- * @ignore
- */
- var InternalRenderTask = function InternalRenderTaskClosure() {
- function InternalRenderTask(callback, params, objs, commonObjs, operatorList, pageNumber) {
- this.callback = callback;
- this.params = params;
- this.objs = objs;
- this.commonObjs = commonObjs;
- this.operatorListIdx = null;
- this.operatorList = operatorList;
- this.pageNumber = pageNumber;
- this.running = false;
- this.graphicsReadyCallback = null;
- this.graphicsReady = false;
- this.useRequestAnimationFrame = false;
- this.cancelled = false;
- this.capability = createPromiseCapability();
- this.task = new RenderTask(this);
- // caching this-bound methods
- this._continueBound = this._continue.bind(this);
- this._scheduleNextBound = this._scheduleNext.bind(this);
- this._nextBound = this._next.bind(this);
- }
- InternalRenderTask.prototype = {
- initializeGraphics: function InternalRenderTask_initializeGraphics(transparency) {
- if (this.cancelled) {
- return;
- }
- if (getDefaultSetting('pdfBug') && globalScope.StepperManager && globalScope.StepperManager.enabled) {
- this.stepper = globalScope.StepperManager.create(this.pageNumber - 1);
- this.stepper.init(this.operatorList);
- this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
- }
- var params = this.params;
- this.gfx = new CanvasGraphics(params.canvasContext, this.commonObjs, this.objs, params.imageLayer);
- this.gfx.beginDrawing(params.transform, params.viewport, transparency);
- this.operatorListIdx = 0;
- this.graphicsReady = true;
- if (this.graphicsReadyCallback) {
- this.graphicsReadyCallback();
- }
- },
- cancel: function InternalRenderTask_cancel() {
- this.running = false;
- this.cancelled = true;
- this.callback('cancelled');
- },
- operatorListChanged: function InternalRenderTask_operatorListChanged() {
- if (!this.graphicsReady) {
- if (!this.graphicsReadyCallback) {
- this.graphicsReadyCallback = this._continueBound;
- }
- return;
- }
- if (this.stepper) {
- this.stepper.updateOperatorList(this.operatorList);
- }
- if (this.running) {
- return;
- }
- this._continue();
- },
- _continue: function InternalRenderTask__continue() {
- this.running = true;
- if (this.cancelled) {
- return;
- }
- if (this.task.onContinue) {
- this.task.onContinue.call(this.task, this._scheduleNextBound);
- } else {
- this._scheduleNext();
- }
- },
- _scheduleNext: function InternalRenderTask__scheduleNext() {
- if (this.useRequestAnimationFrame && typeof window !== 'undefined') {
- window.requestAnimationFrame(this._nextBound);
- } else {
- Promise.resolve(undefined).then(this._nextBound);
- }
- },
- _next: function InternalRenderTask__next() {
- if (this.cancelled) {
- return;
- }
- this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, this.operatorListIdx, this._continueBound, this.stepper);
- if (this.operatorListIdx === this.operatorList.argsArray.length) {
- this.running = false;
- if (this.operatorList.lastChunk) {
- this.gfx.endDrawing();
- this.callback();
- }
- }
- }
- };
- return InternalRenderTask;
- }();
- /**
- * (Deprecated) Global observer of unsupported feature usages. Use
- * onUnsupportedFeature callback of the {PDFDocumentLoadingTask} instance.
- */
- var _UnsupportedManager = function UnsupportedManagerClosure() {
- var listeners = [];
- return {
- listen: function (cb) {
- deprecated('Global UnsupportedManager.listen is used: ' + ' use PDFDocumentLoadingTask.onUnsupportedFeature instead');
- listeners.push(cb);
- },
- notify: function (featureId) {
- for (var i = 0, ii = listeners.length; i < ii; i++) {
- listeners[i](featureId);
- }
- }
- };
- }();
- if (typeof pdfjsVersion !== 'undefined') {
- exports.version = pdfjsVersion;
- }
- if (typeof pdfjsBuild !== 'undefined') {
- exports.build = pdfjsBuild;
- }
- exports.getDocument = getDocument;
- exports.PDFDataRangeTransport = PDFDataRangeTransport;
- exports.PDFWorker = PDFWorker;
- exports.PDFDocumentProxy = PDFDocumentProxy;
- exports.PDFPageProxy = PDFPageProxy;
- exports._UnsupportedManager = _UnsupportedManager;
- }));
- (function (root, factory) {
- factory(root.pdfjsDisplayGlobal = {}, root.pdfjsSharedUtil, root.pdfjsDisplayDOMUtils, root.pdfjsDisplayAPI, root.pdfjsDisplayAnnotationLayer, root.pdfjsDisplayTextLayer, root.pdfjsDisplayMetadata, root.pdfjsDisplaySVG);
- }(this, function (exports, sharedUtil, displayDOMUtils, displayAPI, displayAnnotationLayer, displayTextLayer, displayMetadata, displaySVG) {
- var globalScope = sharedUtil.globalScope;
- var deprecated = sharedUtil.deprecated;
- var warn = sharedUtil.warn;
- var LinkTarget = displayDOMUtils.LinkTarget;
- var isWorker = typeof window === 'undefined';
- // The global PDFJS object is now deprecated and will not be supported in
- // the future. The members below are maintained for backward compatibility
- // and shall not be extended or modified. If the global.js is included as
- // a module, we will create a global PDFJS object instance or use existing.
- if (!globalScope.PDFJS) {
- globalScope.PDFJS = {};
- }
- var PDFJS = globalScope.PDFJS;
- if (typeof pdfjsVersion !== 'undefined') {
- PDFJS.version = pdfjsVersion;
- }
- if (typeof pdfjsBuild !== 'undefined') {
- PDFJS.build = pdfjsBuild;
- }
- PDFJS.pdfBug = false;
- if (PDFJS.verbosity !== undefined) {
- sharedUtil.setVerbosityLevel(PDFJS.verbosity);
- }
- delete PDFJS.verbosity;
- Object.defineProperty(PDFJS, 'verbosity', {
- get: function () {
- return sharedUtil.getVerbosityLevel();
- },
- set: function (level) {
- sharedUtil.setVerbosityLevel(level);
- },
- enumerable: true,
- configurable: true
- });
- PDFJS.VERBOSITY_LEVELS = sharedUtil.VERBOSITY_LEVELS;
- PDFJS.OPS = sharedUtil.OPS;
- PDFJS.UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES;
- PDFJS.isValidUrl = displayDOMUtils.isValidUrl;
- PDFJS.shadow = sharedUtil.shadow;
- PDFJS.createBlob = sharedUtil.createBlob;
- PDFJS.createObjectURL = function PDFJS_createObjectURL(data, contentType) {
- return sharedUtil.createObjectURL(data, contentType, PDFJS.disableCreateObjectURL);
- };
- Object.defineProperty(PDFJS, 'isLittleEndian', {
- configurable: true,
- get: function PDFJS_isLittleEndian() {
- var value = sharedUtil.isLittleEndian();
- return sharedUtil.shadow(PDFJS, 'isLittleEndian', value);
- }
- });
- PDFJS.removeNullCharacters = sharedUtil.removeNullCharacters;
- PDFJS.PasswordResponses = sharedUtil.PasswordResponses;
- PDFJS.PasswordException = sharedUtil.PasswordException;
- PDFJS.UnknownErrorException = sharedUtil.UnknownErrorException;
- PDFJS.InvalidPDFException = sharedUtil.InvalidPDFException;
- PDFJS.MissingPDFException = sharedUtil.MissingPDFException;
- PDFJS.UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
- PDFJS.Util = sharedUtil.Util;
- PDFJS.PageViewport = sharedUtil.PageViewport;
- PDFJS.createPromiseCapability = sharedUtil.createPromiseCapability;
- /**
- * The maximum allowed image size in total pixels e.g. width * height. Images
- * above this value will not be drawn. Use -1 for no limit.
- * @var {number}
- */
- PDFJS.maxImageSize = PDFJS.maxImageSize === undefined ? -1 : PDFJS.maxImageSize;
- /**
- * The url of where the predefined Adobe CMaps are located. Include trailing
- * slash.
- * @var {string}
- */
- PDFJS.cMapUrl = PDFJS.cMapUrl === undefined ? null : PDFJS.cMapUrl;
- /**
- * Specifies if CMaps are binary packed.
- * @var {boolean}
- */
- PDFJS.cMapPacked = PDFJS.cMapPacked === undefined ? false : PDFJS.cMapPacked;
- /**
- * By default fonts are converted to OpenType fonts and loaded via font face
- * rules. If disabled, the font will be rendered using a built in font
- * renderer that constructs the glyphs with primitive path commands.
- * @var {boolean}
- */
- PDFJS.disableFontFace = PDFJS.disableFontFace === undefined ? false : PDFJS.disableFontFace;
- /**
- * Path for image resources, mainly for annotation icons. Include trailing
- * slash.
- * @var {string}
- */
- PDFJS.imageResourcesPath = PDFJS.imageResourcesPath === undefined ? '' : PDFJS.imageResourcesPath;
- /**
- * Disable the web worker and run all code on the main thread. This will
- * happen automatically if the browser doesn't support workers or sending
- * typed arrays to workers.
- * @var {boolean}
- */
- PDFJS.disableWorker = PDFJS.disableWorker === undefined ? false : PDFJS.disableWorker;
- /**
- * Path and filename of the worker file. Required when the worker is enabled
- * in development mode. If unspecified in the production build, the worker
- * will be loaded based on the location of the pdf.js file. It is recommended
- * that the workerSrc is set in a custom application to prevent issues caused
- * by third-party frameworks and libraries.
- * @var {string}
- */
- PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc;
- /**
- * Disable range request loading of PDF files. When enabled and if the server
- * supports partial content requests then the PDF will be fetched in chunks.
- * Enabled (false) by default.
- * @var {boolean}
- */
- PDFJS.disableRange = PDFJS.disableRange === undefined ? false : PDFJS.disableRange;
- /**
- * Disable streaming of PDF file data. By default PDF.js attempts to load PDF
- * in chunks. This default behavior can be disabled.
- * @var {boolean}
- */
- PDFJS.disableStream = PDFJS.disableStream === undefined ? false : PDFJS.disableStream;
- /**
- * Disable pre-fetching of PDF file data. When range requests are enabled
- * PDF.js will automatically keep fetching more data even if it isn't needed
- * to display the current page. This default behavior can be disabled.
- *
- * NOTE: It is also necessary to disable streaming, see above,
- * in order for disabling of pre-fetching to work correctly.
- * @var {boolean}
- */
- PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ? false : PDFJS.disableAutoFetch;
- /**
- * Enables special hooks for debugging PDF.js.
- * @var {boolean}
- */
- PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug;
- /**
- * Enables transfer usage in postMessage for ArrayBuffers.
- * @var {boolean}
- */
- PDFJS.postMessageTransfers = PDFJS.postMessageTransfers === undefined ? true : PDFJS.postMessageTransfers;
- /**
- * Disables URL.createObjectURL usage.
- * @var {boolean}
- */
- PDFJS.disableCreateObjectURL = PDFJS.disableCreateObjectURL === undefined ? false : PDFJS.disableCreateObjectURL;
- /**
- * Disables WebGL usage.
- * @var {boolean}
- */
- PDFJS.disableWebGL = PDFJS.disableWebGL === undefined ? true : PDFJS.disableWebGL;
- /**
- * Specifies the |target| attribute for external links.
- * The constants from PDFJS.LinkTarget should be used:
- * - NONE [default]
- * - SELF
- * - BLANK
- * - PARENT
- * - TOP
- * @var {number}
- */
- PDFJS.externalLinkTarget = PDFJS.externalLinkTarget === undefined ? LinkTarget.NONE : PDFJS.externalLinkTarget;
- /**
- * Specifies the |rel| attribute for external links. Defaults to stripping
- * the referrer.
- * @var {string}
- */
- PDFJS.externalLinkRel = PDFJS.externalLinkRel === undefined ? 'noreferrer' : PDFJS.externalLinkRel;
- /**
- * Determines if we can eval strings as JS. Primarily used to improve
- * performance for font rendering.
- * @var {boolean}
- */
- PDFJS.isEvalSupported = PDFJS.isEvalSupported === undefined ? true : PDFJS.isEvalSupported;
- PDFJS.getDocument = displayAPI.getDocument;
- PDFJS.PDFDataRangeTransport = displayAPI.PDFDataRangeTransport;
- PDFJS.PDFWorker = displayAPI.PDFWorker;
- Object.defineProperty(PDFJS, 'hasCanvasTypedArrays', {
- configurable: true,
- get: function PDFJS_hasCanvasTypedArrays() {
- var value = displayDOMUtils.hasCanvasTypedArrays();
- return sharedUtil.shadow(PDFJS, 'hasCanvasTypedArrays', value);
- }
- });
- PDFJS.CustomStyle = displayDOMUtils.CustomStyle;
- PDFJS.LinkTarget = LinkTarget;
- PDFJS.addLinkAttributes = displayDOMUtils.addLinkAttributes;
- PDFJS.getFilenameFromUrl = displayDOMUtils.getFilenameFromUrl;
- PDFJS.isExternalLinkTargetSet = displayDOMUtils.isExternalLinkTargetSet;
- PDFJS.AnnotationLayer = displayAnnotationLayer.AnnotationLayer;
- PDFJS.renderTextLayer = displayTextLayer.renderTextLayer;
- PDFJS.Metadata = displayMetadata.Metadata;
- PDFJS.SVGGraphics = displaySVG.SVGGraphics;
- PDFJS.UnsupportedManager = displayAPI._UnsupportedManager;
- exports.globalScope = globalScope;
- exports.isWorker = isWorker;
- exports.PDFJS = globalScope.PDFJS;
- }));
- }.call(pdfjsLibs));
- exports.PDFJS = pdfjsLibs.pdfjsDisplayGlobal.PDFJS;
- exports.build = pdfjsLibs.pdfjsDisplayAPI.build;
- exports.version = pdfjsLibs.pdfjsDisplayAPI.version;
- exports.getDocument = pdfjsLibs.pdfjsDisplayAPI.getDocument;
- exports.PDFDataRangeTransport = pdfjsLibs.pdfjsDisplayAPI.PDFDataRangeTransport;
- exports.PDFWorker = pdfjsLibs.pdfjsDisplayAPI.PDFWorker;
- exports.renderTextLayer = pdfjsLibs.pdfjsDisplayTextLayer.renderTextLayer;
- exports.AnnotationLayer = pdfjsLibs.pdfjsDisplayAnnotationLayer.AnnotationLayer;
- exports.CustomStyle = pdfjsLibs.pdfjsDisplayDOMUtils.CustomStyle;
- exports.PasswordResponses = pdfjsLibs.pdfjsSharedUtil.PasswordResponses;
- exports.InvalidPDFException = pdfjsLibs.pdfjsSharedUtil.InvalidPDFException;
- exports.MissingPDFException = pdfjsLibs.pdfjsSharedUtil.MissingPDFException;
- exports.SVGGraphics = pdfjsLibs.pdfjsDisplaySVG.SVGGraphics;
- exports.UnexpectedResponseException = pdfjsLibs.pdfjsSharedUtil.UnexpectedResponseException;
- exports.OPS = pdfjsLibs.pdfjsSharedUtil.OPS;
- exports.UNSUPPORTED_FEATURES = pdfjsLibs.pdfjsSharedUtil.UNSUPPORTED_FEATURES;
- exports.isValidUrl = pdfjsLibs.pdfjsDisplayDOMUtils.isValidUrl;
- exports.createValidAbsoluteUrl = pdfjsLibs.pdfjsSharedUtil.createValidAbsoluteUrl;
- exports.createObjectURL = pdfjsLibs.pdfjsSharedUtil.createObjectURL;
- exports.removeNullCharacters = pdfjsLibs.pdfjsSharedUtil.removeNullCharacters;
- exports.shadow = pdfjsLibs.pdfjsSharedUtil.shadow;
- exports.createBlob = pdfjsLibs.pdfjsSharedUtil.createBlob;
- exports.getFilenameFromUrl = pdfjsLibs.pdfjsDisplayDOMUtils.getFilenameFromUrl;
- exports.addLinkAttributes = pdfjsLibs.pdfjsDisplayDOMUtils.addLinkAttributes;
-})); \ No newline at end of file
diff --git a/extensions/pdfjs/content/build/pdf.worker.js b/extensions/pdfjs/content/build/pdf.worker.js
deleted file mode 100644
index 6ce5199..0000000
--- a/extensions/pdfjs/content/build/pdf.worker.js
+++ /dev/null
@@ -1,52500 +0,0 @@
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-(function (root, factory) {
- 'use strict';
- if (typeof define === 'function' && define.amd) {
- define('pdfjs-dist/build/pdf.worker', ['exports'], factory);
- } else if (typeof exports !== 'undefined') {
- factory(exports);
- } else {
- factory(root['pdfjsDistBuildPdfWorker'] = {});
- }
-}(this, function (exports) {
- // Use strict in our context only - users might not want it
- 'use strict';
- var pdfjsVersion = '1.6.315';
- var pdfjsBuild = 'a139c75';
- var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : null;
- var pdfjsLibs = {};
- (function pdfjsWrapper() {
- (function (root, factory) {
- factory(root.pdfjsCoreArithmeticDecoder = {});
- }(this, function (exports) {
- /* This class implements the QM Coder decoding as defined in
- * JPEG 2000 Part I Final Committee Draft Version 1.0
- * Annex C.3 Arithmetic decoding procedure
- * available at http://www.jpeg.org/public/fcd15444-1.pdf
- *
- * The arithmetic decoder is used in conjunction with context models to decode
- * JPEG2000 and JBIG2 streams.
- */
- var ArithmeticDecoder = function ArithmeticDecoderClosure() {
- // Table C-2
- var QeTable = [
- {
- qe: 0x5601,
- nmps: 1,
- nlps: 1,
- switchFlag: 1
- },
- {
- qe: 0x3401,
- nmps: 2,
- nlps: 6,
- switchFlag: 0
- },
- {
- qe: 0x1801,
- nmps: 3,
- nlps: 9,
- switchFlag: 0
- },
- {
- qe: 0x0AC1,
- nmps: 4,
- nlps: 12,
- switchFlag: 0
- },
- {
- qe: 0x0521,
- nmps: 5,
- nlps: 29,
- switchFlag: 0
- },
- {
- qe: 0x0221,
- nmps: 38,
- nlps: 33,
- switchFlag: 0
- },
- {
- qe: 0x5601,
- nmps: 7,
- nlps: 6,
- switchFlag: 1
- },
- {
- qe: 0x5401,
- nmps: 8,
- nlps: 14,
- switchFlag: 0
- },
- {
- qe: 0x4801,
- nmps: 9,
- nlps: 14,
- switchFlag: 0
- },
- {
- qe: 0x3801,
- nmps: 10,
- nlps: 14,
- switchFlag: 0
- },
- {
- qe: 0x3001,
- nmps: 11,
- nlps: 17,
- switchFlag: 0
- },
- {
- qe: 0x2401,
- nmps: 12,
- nlps: 18,
- switchFlag: 0
- },
- {
- qe: 0x1C01,
- nmps: 13,
- nlps: 20,
- switchFlag: 0
- },
- {
- qe: 0x1601,
- nmps: 29,
- nlps: 21,
- switchFlag: 0
- },
- {
- qe: 0x5601,
- nmps: 15,
- nlps: 14,
- switchFlag: 1
- },
- {
- qe: 0x5401,
- nmps: 16,
- nlps: 14,
- switchFlag: 0
- },
- {
- qe: 0x5101,
- nmps: 17,
- nlps: 15,
- switchFlag: 0
- },
- {
- qe: 0x4801,
- nmps: 18,
- nlps: 16,
- switchFlag: 0
- },
- {
- qe: 0x3801,
- nmps: 19,
- nlps: 17,
- switchFlag: 0
- },
- {
- qe: 0x3401,
- nmps: 20,
- nlps: 18,
- switchFlag: 0
- },
- {
- qe: 0x3001,
- nmps: 21,
- nlps: 19,
- switchFlag: 0
- },
- {
- qe: 0x2801,
- nmps: 22,
- nlps: 19,
- switchFlag: 0
- },
- {
- qe: 0x2401,
- nmps: 23,
- nlps: 20,
- switchFlag: 0
- },
- {
- qe: 0x2201,
- nmps: 24,
- nlps: 21,
- switchFlag: 0
- },
- {
- qe: 0x1C01,
- nmps: 25,
- nlps: 22,
- switchFlag: 0
- },
- {
- qe: 0x1801,
- nmps: 26,
- nlps: 23,
- switchFlag: 0
- },
- {
- qe: 0x1601,
- nmps: 27,
- nlps: 24,
- switchFlag: 0
- },
- {
- qe: 0x1401,
- nmps: 28,
- nlps: 25,
- switchFlag: 0
- },
- {
- qe: 0x1201,
- nmps: 29,
- nlps: 26,
- switchFlag: 0
- },
- {
- qe: 0x1101,
- nmps: 30,
- nlps: 27,
- switchFlag: 0
- },
- {
- qe: 0x0AC1,
- nmps: 31,
- nlps: 28,
- switchFlag: 0
- },
- {
- qe: 0x09C1,
- nmps: 32,
- nlps: 29,
- switchFlag: 0
- },
- {
- qe: 0x08A1,
- nmps: 33,
- nlps: 30,
- switchFlag: 0
- },
- {
- qe: 0x0521,
- nmps: 34,
- nlps: 31,
- switchFlag: 0
- },
- {
- qe: 0x0441,
- nmps: 35,
- nlps: 32,
- switchFlag: 0
- },
- {
- qe: 0x02A1,
- nmps: 36,
- nlps: 33,
- switchFlag: 0
- },
- {
- qe: 0x0221,
- nmps: 37,
- nlps: 34,
- switchFlag: 0
- },
- {
- qe: 0x0141,
- nmps: 38,
- nlps: 35,
- switchFlag: 0
- },
- {
- qe: 0x0111,
- nmps: 39,
- nlps: 36,
- switchFlag: 0
- },
- {
- qe: 0x0085,
- nmps: 40,
- nlps: 37,
- switchFlag: 0
- },
- {
- qe: 0x0049,
- nmps: 41,
- nlps: 38,
- switchFlag: 0
- },
- {
- qe: 0x0025,
- nmps: 42,
- nlps: 39,
- switchFlag: 0
- },
- {
- qe: 0x0015,
- nmps: 43,
- nlps: 40,
- switchFlag: 0
- },
- {
- qe: 0x0009,
- nmps: 44,
- nlps: 41,
- switchFlag: 0
- },
- {
- qe: 0x0005,
- nmps: 45,
- nlps: 42,
- switchFlag: 0
- },
- {
- qe: 0x0001,
- nmps: 45,
- nlps: 43,
- switchFlag: 0
- },
- {
- qe: 0x5601,
- nmps: 46,
- nlps: 46,
- switchFlag: 0
- }
- ];
- // C.3.5 Initialisation of the decoder (INITDEC)
- function ArithmeticDecoder(data, start, end) {
- this.data = data;
- this.bp = start;
- this.dataEnd = end;
- this.chigh = data[start];
- this.clow = 0;
- this.byteIn();
- this.chigh = this.chigh << 7 & 0xFFFF | this.clow >> 9 & 0x7F;
- this.clow = this.clow << 7 & 0xFFFF;
- this.ct -= 7;
- this.a = 0x8000;
- }
- ArithmeticDecoder.prototype = {
- // C.3.4 Compressed data input (BYTEIN)
- byteIn: function ArithmeticDecoder_byteIn() {
- var data = this.data;
- var bp = this.bp;
- if (data[bp] === 0xFF) {
- var b1 = data[bp + 1];
- if (b1 > 0x8F) {
- this.clow += 0xFF00;
- this.ct = 8;
- } else {
- bp++;
- this.clow += data[bp] << 9;
- this.ct = 7;
- this.bp = bp;
- }
- } else {
- bp++;
- this.clow += bp < this.dataEnd ? data[bp] << 8 : 0xFF00;
- this.ct = 8;
- this.bp = bp;
- }
- if (this.clow > 0xFFFF) {
- this.chigh += this.clow >> 16;
- this.clow &= 0xFFFF;
- }
- },
- // C.3.2 Decoding a decision (DECODE)
- readBit: function ArithmeticDecoder_readBit(contexts, pos) {
- // contexts are packed into 1 byte:
- // highest 7 bits carry cx.index, lowest bit carries cx.mps
- var cx_index = contexts[pos] >> 1, cx_mps = contexts[pos] & 1;
- var qeTableIcx = QeTable[cx_index];
- var qeIcx = qeTableIcx.qe;
- var d;
- var a = this.a - qeIcx;
- if (this.chigh < qeIcx) {
- // exchangeLps
- if (a < qeIcx) {
- a = qeIcx;
- d = cx_mps;
- cx_index = qeTableIcx.nmps;
- } else {
- a = qeIcx;
- d = 1 ^ cx_mps;
- if (qeTableIcx.switchFlag === 1) {
- cx_mps = d;
- }
- cx_index = qeTableIcx.nlps;
- }
- } else {
- this.chigh -= qeIcx;
- if ((a & 0x8000) !== 0) {
- this.a = a;
- return cx_mps;
- }
- // exchangeMps
- if (a < qeIcx) {
- d = 1 ^ cx_mps;
- if (qeTableIcx.switchFlag === 1) {
- cx_mps = d;
- }
- cx_index = qeTableIcx.nlps;
- } else {
- d = cx_mps;
- cx_index = qeTableIcx.nmps;
- }
- }
- // C.3.3 renormD;
- do {
- if (this.ct === 0) {
- this.byteIn();
- }
- a <<= 1;
- this.chigh = this.chigh << 1 & 0xFFFF | this.clow >> 15 & 1;
- this.clow = this.clow << 1 & 0xFFFF;
- this.ct--;
- } while ((a & 0x8000) === 0);
- this.a = a;
- contexts[pos] = cx_index << 1 | cx_mps;
- return d;
- }
- };
- return ArithmeticDecoder;
- }();
- exports.ArithmeticDecoder = ArithmeticDecoder;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreBidi = {});
- }(this, function (exports) {
- // Character types for symbols from 0000 to 00FF.
- var baseTypes = [
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'S',
- 'B',
- 'S',
- 'WS',
- 'B',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'B',
- 'B',
- 'B',
- 'S',
- 'WS',
- 'ON',
- 'ON',
- 'ET',
- 'ET',
- 'ET',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'CS',
- 'ON',
- 'CS',
- 'ON',
- 'EN',
- 'EN',
- 'EN',
- 'EN',
- 'EN',
- 'EN',
- 'EN',
- 'EN',
- 'EN',
- 'EN',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'B',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'BN',
- 'CS',
- 'ON',
- 'ET',
- 'ET',
- 'ET',
- 'ET',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'L',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'ET',
- 'ET',
- 'EN',
- 'EN',
- 'ON',
- 'L',
- 'ON',
- 'ON',
- 'ON',
- 'EN',
- 'L',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'ON',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'ON',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'ON',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L',
- 'L'
- ];
- // Character types for symbols from 0600 to 06FF
- var arabicTypes = [
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'CS',
- 'AL',
- 'ON',
- 'ON',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AN',
- 'AN',
- 'AN',
- 'AN',
- 'AN',
- 'AN',
- 'AN',
- 'AN',
- 'AN',
- 'AN',
- 'ET',
- 'AN',
- 'AN',
- 'AL',
- 'AL',
- 'AL',
- 'NSM',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'ON',
- 'NSM',
- 'NSM',
- 'NSM',
- 'NSM',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL',
- 'AL'
- ];
- function isOdd(i) {
- return (i & 1) !== 0;
- }
- function isEven(i) {
- return (i & 1) === 0;
- }
- function findUnequal(arr, start, value) {
- for (var j = start, jj = arr.length; j < jj; ++j) {
- if (arr[j] !== value) {
- return j;
- }
- }
- return j;
- }
- function setValues(arr, start, end, value) {
- for (var j = start; j < end; ++j) {
- arr[j] = value;
- }
- }
- function reverseValues(arr, start, end) {
- for (var i = start, j = end - 1; i < j; ++i, --j) {
- var temp = arr[i];
- arr[i] = arr[j];
- arr[j] = temp;
- }
- }
- function createBidiText(str, isLTR, vertical) {
- return {
- str: str,
- dir: vertical ? 'ttb' : isLTR ? 'ltr' : 'rtl'
- };
- }
- // These are used in bidi(), which is called frequently. We re-use them on
- // each call to avoid unnecessary allocations.
- var chars = [];
- var types = [];
- function bidi(str, startLevel, vertical) {
- var isLTR = true;
- var strLength = str.length;
- if (strLength === 0 || vertical) {
- return createBidiText(str, isLTR, vertical);
- }
- // Get types and fill arrays
- chars.length = strLength;
- types.length = strLength;
- var numBidi = 0;
- var i, ii;
- for (i = 0; i < strLength; ++i) {
- chars[i] = str.charAt(i);
- var charCode = str.charCodeAt(i);
- var charType = 'L';
- if (charCode <= 0x00ff) {
- charType = baseTypes[charCode];
- } else if (0x0590 <= charCode && charCode <= 0x05f4) {
- charType = 'R';
- } else if (0x0600 <= charCode && charCode <= 0x06ff) {
- charType = arabicTypes[charCode & 0xff];
- } else if (0x0700 <= charCode && charCode <= 0x08AC) {
- charType = 'AL';
- }
- if (charType === 'R' || charType === 'AL' || charType === 'AN') {
- numBidi++;
- }
- types[i] = charType;
- }
- // Detect the bidi method
- // - If there are no rtl characters then no bidi needed
- // - If less than 30% chars are rtl then string is primarily ltr
- // - If more than 30% chars are rtl then string is primarily rtl
- if (numBidi === 0) {
- isLTR = true;
- return createBidiText(str, isLTR);
- }
- if (startLevel === -1) {
- if (strLength / numBidi < 0.3) {
- isLTR = true;
- startLevel = 0;
- } else {
- isLTR = false;
- startLevel = 1;
- }
- }
- var levels = [];
- for (i = 0; i < strLength; ++i) {
- levels[i] = startLevel;
- }
- /*
- X1-X10: skip most of this, since we are NOT doing the embeddings.
- */
- var e = isOdd(startLevel) ? 'R' : 'L';
- var sor = e;
- var eor = sor;
- /*
- W1. Examine each non-spacing mark (NSM) in the level run, and change the
- type of the NSM to the type of the previous character. If the NSM is at the
- start of the level run, it will get the type of sor.
- */
- var lastType = sor;
- for (i = 0; i < strLength; ++i) {
- if (types[i] === 'NSM') {
- types[i] = lastType;
- } else {
- lastType = types[i];
- }
- }
- /*
- W2. Search backwards from each instance of a European number until the
- first strong type (R, L, AL, or sor) is found. If an AL is found, change
- the type of the European number to Arabic number.
- */
- lastType = sor;
- var t;
- for (i = 0; i < strLength; ++i) {
- t = types[i];
- if (t === 'EN') {
- types[i] = lastType === 'AL' ? 'AN' : 'EN';
- } else if (t === 'R' || t === 'L' || t === 'AL') {
- lastType = t;
- }
- }
- /*
- W3. Change all ALs to R.
- */
- for (i = 0; i < strLength; ++i) {
- t = types[i];
- if (t === 'AL') {
- types[i] = 'R';
- }
- }
- /*
- W4. A single European separator between two European numbers changes to a
- European number. A single common separator between two numbers of the same
- type changes to that type:
- */
- for (i = 1; i < strLength - 1; ++i) {
- if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') {
- types[i] = 'EN';
- }
- if (types[i] === 'CS' && (types[i - 1] === 'EN' || types[i - 1] === 'AN') && types[i + 1] === types[i - 1]) {
- types[i] = types[i - 1];
- }
- }
- /*
- W5. A sequence of European terminators adjacent to European numbers changes
- to all European numbers:
- */
- for (i = 0; i < strLength; ++i) {
- if (types[i] === 'EN') {
- // do before
- var j;
- for (j = i - 1; j >= 0; --j) {
- if (types[j] !== 'ET') {
- break;
- }
- types[j] = 'EN';
- }
- // do after
- for (j = i + 1; j < strLength; ++j) {
- if (types[j] !== 'ET') {
- break;
- }
- types[j] = 'EN';
- }
- }
- }
- /*
- W6. Otherwise, separators and terminators change to Other Neutral:
- */
- for (i = 0; i < strLength; ++i) {
- t = types[i];
- if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') {
- types[i] = 'ON';
- }
- }
- /*
- W7. Search backwards from each instance of a European number until the
- first strong type (R, L, or sor) is found. If an L is found, then change
- the type of the European number to L.
- */
- lastType = sor;
- for (i = 0; i < strLength; ++i) {
- t = types[i];
- if (t === 'EN') {
- types[i] = lastType === 'L' ? 'L' : 'EN';
- } else if (t === 'R' || t === 'L') {
- lastType = t;
- }
- }
- /*
- N1. A sequence of neutrals takes the direction of the surrounding strong
- text if the text on both sides has the same direction. European and Arabic
- numbers are treated as though they were R. Start-of-level-run (sor) and
- end-of-level-run (eor) are used at level run boundaries.
- */
- for (i = 0; i < strLength; ++i) {
- if (types[i] === 'ON') {
- var end = findUnequal(types, i + 1, 'ON');
- var before = sor;
- if (i > 0) {
- before = types[i - 1];
- }
- var after = eor;
- if (end + 1 < strLength) {
- after = types[end + 1];
- }
- if (before !== 'L') {
- before = 'R';
- }
- if (after !== 'L') {
- after = 'R';
- }
- if (before === after) {
- setValues(types, i, end, before);
- }
- i = end - 1;
- }
- }
- // reset to end (-1 so next iteration is ok)
- /*
- N2. Any remaining neutrals take the embedding direction.
- */
- for (i = 0; i < strLength; ++i) {
- if (types[i] === 'ON') {
- types[i] = e;
- }
- }
- /*
- I1. For all characters with an even (left-to-right) embedding direction,
- those of type R go up one level and those of type AN or EN go up two
- levels.
- I2. For all characters with an odd (right-to-left) embedding direction,
- those of type L, EN or AN go up one level.
- */
- for (i = 0; i < strLength; ++i) {
- t = types[i];
- if (isEven(levels[i])) {
- if (t === 'R') {
- levels[i] += 1;
- } else if (t === 'AN' || t === 'EN') {
- levels[i] += 2;
- }
- } else {
- // isOdd
- if (t === 'L' || t === 'AN' || t === 'EN') {
- levels[i] += 1;
- }
- }
- }
- /*
- L1. On each line, reset the embedding level of the following characters to
- the paragraph embedding level:
-
- segment separators,
- paragraph separators,
- any sequence of whitespace characters preceding a segment separator or
- paragraph separator, and any sequence of white space characters at the end
- of the line.
- */
- // don't bother as text is only single line
- /*
- L2. From the highest level found in the text to the lowest odd level on
- each line, reverse any contiguous sequence of characters that are at that
- level or higher.
- */
- // find highest level & lowest odd level
- var highestLevel = -1;
- var lowestOddLevel = 99;
- var level;
- for (i = 0, ii = levels.length; i < ii; ++i) {
- level = levels[i];
- if (highestLevel < level) {
- highestLevel = level;
- }
- if (lowestOddLevel > level && isOdd(level)) {
- lowestOddLevel = level;
- }
- }
- // now reverse between those limits
- for (level = highestLevel; level >= lowestOddLevel; --level) {
- // find segments to reverse
- var start = -1;
- for (i = 0, ii = levels.length; i < ii; ++i) {
- if (levels[i] < level) {
- if (start >= 0) {
- reverseValues(chars, start, i);
- start = -1;
- }
- } else if (start < 0) {
- start = i;
- }
- }
- if (start >= 0) {
- reverseValues(chars, start, levels.length);
- }
- }
- /*
- L3. Combining marks applied to a right-to-left base character will at this
- point precede their base character. If the rendering engine expects them to
- follow the base characters in the final display process, then the ordering
- of the marks and the base character must be reversed.
- */
- // don't bother for now
- /*
- L4. A character that possesses the mirrored property as specified by
- Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved
- directionality of that character is R.
- */
- // don't mirror as characters are already mirrored in the pdf
- // Finally, return string
- for (i = 0, ii = chars.length; i < ii; ++i) {
- var ch = chars[i];
- if (ch === '<' || ch === '>') {
- chars[i] = '';
- }
- }
- return createBidiText(chars.join(''), isLTR);
- }
- exports.bidi = bidi;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreCharsets = {});
- }(this, function (exports) {
- var ISOAdobeCharset = [
- '.notdef',
- 'space',
- 'exclam',
- 'quotedbl',
- 'numbersign',
- 'dollar',
- 'percent',
- 'ampersand',
- 'quoteright',
- 'parenleft',
- 'parenright',
- 'asterisk',
- 'plus',
- 'comma',
- 'hyphen',
- 'period',
- 'slash',
- 'zero',
- 'one',
- 'two',
- 'three',
- 'four',
- 'five',
- 'six',
- 'seven',
- 'eight',
- 'nine',
- 'colon',
- 'semicolon',
- 'less',
- 'equal',
- 'greater',
- 'question',
- 'at',
- 'A',
- 'B',
- 'C',
- 'D',
- 'E',
- 'F',
- 'G',
- 'H',
- 'I',
- 'J',
- 'K',
- 'L',
- 'M',
- 'N',
- 'O',
- 'P',
- 'Q',
- 'R',
- 'S',
- 'T',
- 'U',
- 'V',
- 'W',
- 'X',
- 'Y',
- 'Z',
- 'bracketleft',
- 'backslash',
- 'bracketright',
- 'asciicircum',
- 'underscore',
- 'quoteleft',
- 'a',
- 'b',
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i',
- 'j',
- 'k',
- 'l',
- 'm',
- 'n',
- 'o',
- 'p',
- 'q',
- 'r',
- 's',
- 't',
- 'u',
- 'v',
- 'w',
- 'x',
- 'y',
- 'z',
- 'braceleft',
- 'bar',
- 'braceright',
- 'asciitilde',
- 'exclamdown',
- 'cent',
- 'sterling',
- 'fraction',
- 'yen',
- 'florin',
- 'section',
- 'currency',
- 'quotesingle',
- 'quotedblleft',
- 'guillemotleft',
- 'guilsinglleft',
- 'guilsinglright',
- 'fi',
- 'fl',
- 'endash',
- 'dagger',
- 'daggerdbl',
- 'periodcentered',
- 'paragraph',
- 'bullet',
- 'quotesinglbase',
- 'quotedblbase',
- 'quotedblright',
- 'guillemotright',
- 'ellipsis',
- 'perthousand',
- 'questiondown',
- 'grave',
- 'acute',
- 'circumflex',
- 'tilde',
- 'macron',
- 'breve',
- 'dotaccent',
- 'dieresis',
- 'ring',
- 'cedilla',
- 'hungarumlaut',
- 'ogonek',
- 'caron',
- 'emdash',
- 'AE',
- 'ordfeminine',
- 'Lslash',
- 'Oslash',
- 'OE',
- 'ordmasculine',
- 'ae',
- 'dotlessi',
- 'lslash',
- 'oslash',
- 'oe',
- 'germandbls',
- 'onesuperior',
- 'logicalnot',
- 'mu',
- 'trademark',
- 'Eth',
- 'onehalf',
- 'plusminus',
- 'Thorn',
- 'onequarter',
- 'divide',
- 'brokenbar',
- 'degree',
- 'thorn',
- 'threequarters',
- 'twosuperior',
- 'registered',
- 'minus',
- 'eth',
- 'multiply',
- 'threesuperior',
- 'copyright',
- 'Aacute',
- 'Acircumflex',
- 'Adieresis',
- 'Agrave',
- 'Aring',
- 'Atilde',
- 'Ccedilla',
- 'Eacute',
- 'Ecircumflex',
- 'Edieresis',
- 'Egrave',
- 'Iacute',
- 'Icircumflex',
- 'Idieresis',
- 'Igrave',
- 'Ntilde',
- 'Oacute',
- 'Ocircumflex',
- 'Odieresis',
- 'Ograve',
- 'Otilde',
- 'Scaron',
- 'Uacute',
- 'Ucircumflex',
- 'Udieresis',
- 'Ugrave',
- 'Yacute',
- 'Ydieresis',
- 'Zcaron',
- 'aacute',
- 'acircumflex',
- 'adieresis',
- 'agrave',
- 'aring',
- 'atilde',
- 'ccedilla',
- 'eacute',
- 'ecircumflex',
- 'edieresis',
- 'egrave',
- 'iacute',
- 'icircumflex',
- 'idieresis',
- 'igrave',
- 'ntilde',
- 'oacute',
- 'ocircumflex',
- 'odieresis',
- 'ograve',
- 'otilde',
- 'scaron',
- 'uacute',
- 'ucircumflex',
- 'udieresis',
- 'ugrave',
- 'yacute',
- 'ydieresis',
- 'zcaron'
- ];
- var ExpertCharset = [
- '.notdef',
- 'space',
- 'exclamsmall',
- 'Hungarumlautsmall',
- 'dollaroldstyle',
- 'dollarsuperior',
- 'ampersandsmall',
- 'Acutesmall',
- 'parenleftsuperior',
- 'parenrightsuperior',
- 'twodotenleader',
- 'onedotenleader',
- 'comma',
- 'hyphen',
- 'period',
- 'fraction',
- 'zerooldstyle',
- 'oneoldstyle',
- 'twooldstyle',
- 'threeoldstyle',
- 'fouroldstyle',
- 'fiveoldstyle',
- 'sixoldstyle',
- 'sevenoldstyle',
- 'eightoldstyle',
- 'nineoldstyle',
- 'colon',
- 'semicolon',
- 'commasuperior',
- 'threequartersemdash',
- 'periodsuperior',
- 'questionsmall',
- 'asuperior',
- 'bsuperior',
- 'centsuperior',
- 'dsuperior',
- 'esuperior',
- 'isuperior',
- 'lsuperior',
- 'msuperior',
- 'nsuperior',
- 'osuperior',
- 'rsuperior',
- 'ssuperior',
- 'tsuperior',
- 'ff',
- 'fi',
- 'fl',
- 'ffi',
- 'ffl',
- 'parenleftinferior',
- 'parenrightinferior',
- 'Circumflexsmall',
- 'hyphensuperior',
- 'Gravesmall',
- 'Asmall',
- 'Bsmall',
- 'Csmall',
- 'Dsmall',
- 'Esmall',
- 'Fsmall',
- 'Gsmall',
- 'Hsmall',
- 'Ismall',
- 'Jsmall',
- 'Ksmall',
- 'Lsmall',
- 'Msmall',
- 'Nsmall',
- 'Osmall',
- 'Psmall',
- 'Qsmall',
- 'Rsmall',
- 'Ssmall',
- 'Tsmall',
- 'Usmall',
- 'Vsmall',
- 'Wsmall',
- 'Xsmall',
- 'Ysmall',
- 'Zsmall',
- 'colonmonetary',
- 'onefitted',
- 'rupiah',
- 'Tildesmall',
- 'exclamdownsmall',
- 'centoldstyle',
- 'Lslashsmall',
- 'Scaronsmall',
- 'Zcaronsmall',
- 'Dieresissmall',
- 'Brevesmall',
- 'Caronsmall',
- 'Dotaccentsmall',
- 'Macronsmall',
- 'figuredash',
- 'hypheninferior',
- 'Ogoneksmall',
- 'Ringsmall',
- 'Cedillasmall',
- 'onequarter',
- 'onehalf',
- 'threequarters',
- 'questiondownsmall',
- 'oneeighth',
- 'threeeighths',
- 'fiveeighths',
- 'seveneighths',
- 'onethird',
- 'twothirds',
- 'zerosuperior',
- 'onesuperior',
- 'twosuperior',
- 'threesuperior',
- 'foursuperior',
- 'fivesuperior',
- 'sixsuperior',
- 'sevensuperior',
- 'eightsuperior',
- 'ninesuperior',
- 'zeroinferior',
- 'oneinferior',
- 'twoinferior',
- 'threeinferior',
- 'fourinferior',
- 'fiveinferior',
- 'sixinferior',
- 'seveninferior',
- 'eightinferior',
- 'nineinferior',
- 'centinferior',
- 'dollarinferior',
- 'periodinferior',
- 'commainferior',
- 'Agravesmall',
- 'Aacutesmall',
- 'Acircumflexsmall',
- 'Atildesmall',
- 'Adieresissmall',
- 'Aringsmall',
- 'AEsmall',
- 'Ccedillasmall',
- 'Egravesmall',
- 'Eacutesmall',
- 'Ecircumflexsmall',
- 'Edieresissmall',
- 'Igravesmall',
- 'Iacutesmall',
- 'Icircumflexsmall',
- 'Idieresissmall',
- 'Ethsmall',
- 'Ntildesmall',
- 'Ogravesmall',
- 'Oacutesmall',
- 'Ocircumflexsmall',
- 'Otildesmall',
- 'Odieresissmall',
- 'OEsmall',
- 'Oslashsmall',
- 'Ugravesmall',
- 'Uacutesmall',
- 'Ucircumflexsmall',
- 'Udieresissmall',
- 'Yacutesmall',
- 'Thornsmall',
- 'Ydieresissmall'
- ];
- var ExpertSubsetCharset = [
- '.notdef',
- 'space',
- 'dollaroldstyle',
- 'dollarsuperior',
- 'parenleftsuperior',
- 'parenrightsuperior',
- 'twodotenleader',
- 'onedotenleader',
- 'comma',
- 'hyphen',
- 'period',
- 'fraction',
- 'zerooldstyle',
- 'oneoldstyle',
- 'twooldstyle',
- 'threeoldstyle',
- 'fouroldstyle',
- 'fiveoldstyle',
- 'sixoldstyle',
- 'sevenoldstyle',
- 'eightoldstyle',
- 'nineoldstyle',
- 'colon',
- 'semicolon',
- 'commasuperior',
- 'threequartersemdash',
- 'periodsuperior',
- 'asuperior',
- 'bsuperior',
- 'centsuperior',
- 'dsuperior',
- 'esuperior',
- 'isuperior',
- 'lsuperior',
- 'msuperior',
- 'nsuperior',
- 'osuperior',
- 'rsuperior',
- 'ssuperior',
- 'tsuperior',
- 'ff',
- 'fi',
- 'fl',
- 'ffi',
- 'ffl',
- 'parenleftinferior',
- 'parenrightinferior',
- 'hyphensuperior',
- 'colonmonetary',
- 'onefitted',
- 'rupiah',
- 'centoldstyle',
- 'figuredash',
- 'hypheninferior',
- 'onequarter',
- 'onehalf',
- 'threequarters',
- 'oneeighth',
- 'threeeighths',
- 'fiveeighths',
- 'seveneighths',
- 'onethird',
- 'twothirds',
- 'zerosuperior',
- 'onesuperior',
- 'twosuperior',
- 'threesuperior',
- 'foursuperior',
- 'fivesuperior',
- 'sixsuperior',
- 'sevensuperior',
- 'eightsuperior',
- 'ninesuperior',
- 'zeroinferior',
- 'oneinferior',
- 'twoinferior',
- 'threeinferior',
- 'fourinferior',
- 'fiveinferior',
- 'sixinferior',
- 'seveninferior',
- 'eightinferior',
- 'nineinferior',
- 'centinferior',
- 'dollarinferior',
- 'periodinferior',
- 'commainferior'
- ];
- exports.ISOAdobeCharset = ISOAdobeCharset;
- exports.ExpertCharset = ExpertCharset;
- exports.ExpertSubsetCharset = ExpertSubsetCharset;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreEncodings = {});
- }(this, function (exports) {
- var ExpertEncoding = [
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'space',
- 'exclamsmall',
- 'Hungarumlautsmall',
- '',
- 'dollaroldstyle',
- 'dollarsuperior',
- 'ampersandsmall',
- 'Acutesmall',
- 'parenleftsuperior',
- 'parenrightsuperior',
- 'twodotenleader',
- 'onedotenleader',
- 'comma',
- 'hyphen',
- 'period',
- 'fraction',
- 'zerooldstyle',
- 'oneoldstyle',
- 'twooldstyle',
- 'threeoldstyle',
- 'fouroldstyle',
- 'fiveoldstyle',
- 'sixoldstyle',
- 'sevenoldstyle',
- 'eightoldstyle',
- 'nineoldstyle',
- 'colon',
- 'semicolon',
- 'commasuperior',
- 'threequartersemdash',
- 'periodsuperior',
- 'questionsmall',
- '',
- 'asuperior',
- 'bsuperior',
- 'centsuperior',
- 'dsuperior',
- 'esuperior',
- '',
- '',
- 'isuperior',
- '',
- '',
- 'lsuperior',
- 'msuperior',
- 'nsuperior',
- 'osuperior',
- '',
- '',
- 'rsuperior',
- 'ssuperior',
- 'tsuperior',
- '',
- 'ff',
- 'fi',
- 'fl',
- 'ffi',
- 'ffl',
- 'parenleftinferior',
- '',
- 'parenrightinferior',
- 'Circumflexsmall',
- 'hyphensuperior',
- 'Gravesmall',
- 'Asmall',
- 'Bsmall',
- 'Csmall',
- 'Dsmall',
- 'Esmall',
- 'Fsmall',
- 'Gsmall',
- 'Hsmall',
- 'Ismall',
- 'Jsmall',
- 'Ksmall',
- 'Lsmall',
- 'Msmall',
- 'Nsmall',
- 'Osmall',
- 'Psmall',
- 'Qsmall',
- 'Rsmall',
- 'Ssmall',
- 'Tsmall',
- 'Usmall',
- 'Vsmall',
- 'Wsmall',
- 'Xsmall',
- 'Ysmall',
- 'Zsmall',
- 'colonmonetary',
- 'onefitted',
- 'rupiah',
- 'Tildesmall',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'exclamdownsmall',
- 'centoldstyle',
- 'Lslashsmall',
- '',
- '',
- 'Scaronsmall',
- 'Zcaronsmall',
- 'Dieresissmall',
- 'Brevesmall',
- 'Caronsmall',
- '',
- 'Dotaccentsmall',
- '',
- '',
- 'Macronsmall',
- '',
- '',
- 'figuredash',
- 'hypheninferior',
- '',
- '',
- 'Ogoneksmall',
- 'Ringsmall',
- 'Cedillasmall',
- '',
- '',
- '',
- 'onequarter',
- 'onehalf',
- 'threequarters',
- 'questiondownsmall',
- 'oneeighth',
- 'threeeighths',
- 'fiveeighths',
- 'seveneighths',
- 'onethird',
- 'twothirds',
- '',
- '',
- 'zerosuperior',
- 'onesuperior',
- 'twosuperior',
- 'threesuperior',
- 'foursuperior',
- 'fivesuperior',
- 'sixsuperior',
- 'sevensuperior',
- 'eightsuperior',
- 'ninesuperior',
- 'zeroinferior',
- 'oneinferior',
- 'twoinferior',
- 'threeinferior',
- 'fourinferior',
- 'fiveinferior',
- 'sixinferior',
- 'seveninferior',
- 'eightinferior',
- 'nineinferior',
- 'centinferior',
- 'dollarinferior',
- 'periodinferior',
- 'commainferior',
- 'Agravesmall',
- 'Aacutesmall',
- 'Acircumflexsmall',
- 'Atildesmall',
- 'Adieresissmall',
- 'Aringsmall',
- 'AEsmall',
- 'Ccedillasmall',
- 'Egravesmall',
- 'Eacutesmall',
- 'Ecircumflexsmall',
- 'Edieresissmall',
- 'Igravesmall',
- 'Iacutesmall',
- 'Icircumflexsmall',
- 'Idieresissmall',
- 'Ethsmall',
- 'Ntildesmall',
- 'Ogravesmall',
- 'Oacutesmall',
- 'Ocircumflexsmall',
- 'Otildesmall',
- 'Odieresissmall',
- 'OEsmall',
- 'Oslashsmall',
- 'Ugravesmall',
- 'Uacutesmall',
- 'Ucircumflexsmall',
- 'Udieresissmall',
- 'Yacutesmall',
- 'Thornsmall',
- 'Ydieresissmall'
- ];
- var MacExpertEncoding = [
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'space',
- 'exclamsmall',
- 'Hungarumlautsmall',
- 'centoldstyle',
- 'dollaroldstyle',
- 'dollarsuperior',
- 'ampersandsmall',
- 'Acutesmall',
- 'parenleftsuperior',
- 'parenrightsuperior',
- 'twodotenleader',
- 'onedotenleader',
- 'comma',
- 'hyphen',
- 'period',
- 'fraction',
- 'zerooldstyle',
- 'oneoldstyle',
- 'twooldstyle',
- 'threeoldstyle',
- 'fouroldstyle',
- 'fiveoldstyle',
- 'sixoldstyle',
- 'sevenoldstyle',
- 'eightoldstyle',
- 'nineoldstyle',
- 'colon',
- 'semicolon',
- '',
- 'threequartersemdash',
- '',
- 'questionsmall',
- '',
- '',
- '',
- '',
- 'Ethsmall',
- '',
- '',
- 'onequarter',
- 'onehalf',
- 'threequarters',
- 'oneeighth',
- 'threeeighths',
- 'fiveeighths',
- 'seveneighths',
- 'onethird',
- 'twothirds',
- '',
- '',
- '',
- '',
- '',
- '',
- 'ff',
- 'fi',
- 'fl',
- 'ffi',
- 'ffl',
- 'parenleftinferior',
- '',
- 'parenrightinferior',
- 'Circumflexsmall',
- 'hypheninferior',
- 'Gravesmall',
- 'Asmall',
- 'Bsmall',
- 'Csmall',
- 'Dsmall',
- 'Esmall',
- 'Fsmall',
- 'Gsmall',
- 'Hsmall',
- 'Ismall',
- 'Jsmall',
- 'Ksmall',
- 'Lsmall',
- 'Msmall',
- 'Nsmall',
- 'Osmall',
- 'Psmall',
- 'Qsmall',
- 'Rsmall',
- 'Ssmall',
- 'Tsmall',
- 'Usmall',
- 'Vsmall',
- 'Wsmall',
- 'Xsmall',
- 'Ysmall',
- 'Zsmall',
- 'colonmonetary',
- 'onefitted',
- 'rupiah',
- 'Tildesmall',
- '',
- '',
- 'asuperior',
- 'centsuperior',
- '',
- '',
- '',
- '',
- 'Aacutesmall',
- 'Agravesmall',
- 'Acircumflexsmall',
- 'Adieresissmall',
- 'Atildesmall',
- 'Aringsmall',
- 'Ccedillasmall',
- 'Eacutesmall',
- 'Egravesmall',
- 'Ecircumflexsmall',
- 'Edieresissmall',
- 'Iacutesmall',
- 'Igravesmall',
- 'Icircumflexsmall',
- 'Idieresissmall',
- 'Ntildesmall',
- 'Oacutesmall',
- 'Ogravesmall',
- 'Ocircumflexsmall',
- 'Odieresissmall',
- 'Otildesmall',
- 'Uacutesmall',
- 'Ugravesmall',
- 'Ucircumflexsmall',
- 'Udieresissmall',
- '',
- 'eightsuperior',
- 'fourinferior',
- 'threeinferior',
- 'sixinferior',
- 'eightinferior',
- 'seveninferior',
- 'Scaronsmall',
- '',
- 'centinferior',
- 'twoinferior',
- '',
- 'Dieresissmall',
- '',
- 'Caronsmall',
- 'osuperior',
- 'fiveinferior',
- '',
- 'commainferior',
- 'periodinferior',
- 'Yacutesmall',
- '',
- 'dollarinferior',
- '',
- 'Thornsmall',
- '',
- 'nineinferior',
- 'zeroinferior',
- 'Zcaronsmall',
- 'AEsmall',
- 'Oslashsmall',
- 'questiondownsmall',
- 'oneinferior',
- 'Lslashsmall',
- '',
- '',
- '',
- '',
- '',
- '',
- 'Cedillasmall',
- '',
- '',
- '',
- '',
- '',
- 'OEsmall',
- 'figuredash',
- 'hyphensuperior',
- '',
- '',
- '',
- '',
- 'exclamdownsmall',
- '',
- 'Ydieresissmall',
- '',
- 'onesuperior',
- 'twosuperior',
- 'threesuperior',
- 'foursuperior',
- 'fivesuperior',
- 'sixsuperior',
- 'sevensuperior',
- 'ninesuperior',
- 'zerosuperior',
- '',
- 'esuperior',
- 'rsuperior',
- 'tsuperior',
- '',
- '',
- 'isuperior',
- 'ssuperior',
- 'dsuperior',
- '',
- '',
- '',
- '',
- '',
- 'lsuperior',
- 'Ogoneksmall',
- 'Brevesmall',
- 'Macronsmall',
- 'bsuperior',
- 'nsuperior',
- 'msuperior',
- 'commasuperior',
- 'periodsuperior',
- 'Dotaccentsmall',
- 'Ringsmall'
- ];
- var MacRomanEncoding = [
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'space',
- 'exclam',
- 'quotedbl',
- 'numbersign',
- 'dollar',
- 'percent',
- 'ampersand',
- 'quotesingle',
- 'parenleft',
- 'parenright',
- 'asterisk',
- 'plus',
- 'comma',
- 'hyphen',
- 'period',
- 'slash',
- 'zero',
- 'one',
- 'two',
- 'three',
- 'four',
- 'five',
- 'six',
- 'seven',
- 'eight',
- 'nine',
- 'colon',
- 'semicolon',
- 'less',
- 'equal',
- 'greater',
- 'question',
- 'at',
- 'A',
- 'B',
- 'C',
- 'D',
- 'E',
- 'F',
- 'G',
- 'H',
- 'I',
- 'J',
- 'K',
- 'L',
- 'M',
- 'N',
- 'O',
- 'P',
- 'Q',
- 'R',
- 'S',
- 'T',
- 'U',
- 'V',
- 'W',
- 'X',
- 'Y',
- 'Z',
- 'bracketleft',
- 'backslash',
- 'bracketright',
- 'asciicircum',
- 'underscore',
- 'grave',
- 'a',
- 'b',
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i',
- 'j',
- 'k',
- 'l',
- 'm',
- 'n',
- 'o',
- 'p',
- 'q',
- 'r',
- 's',
- 't',
- 'u',
- 'v',
- 'w',
- 'x',
- 'y',
- 'z',
- 'braceleft',
- 'bar',
- 'braceright',
- 'asciitilde',
- '',
- 'Adieresis',
- 'Aring',
- 'Ccedilla',
- 'Eacute',
- 'Ntilde',
- 'Odieresis',
- 'Udieresis',
- 'aacute',
- 'agrave',
- 'acircumflex',
- 'adieresis',
- 'atilde',
- 'aring',
- 'ccedilla',
- 'eacute',
- 'egrave',
- 'ecircumflex',
- 'edieresis',
- 'iacute',
- 'igrave',
- 'icircumflex',
- 'idieresis',
- 'ntilde',
- 'oacute',
- 'ograve',
- 'ocircumflex',
- 'odieresis',
- 'otilde',
- 'uacute',
- 'ugrave',
- 'ucircumflex',
- 'udieresis',
- 'dagger',
- 'degree',
- 'cent',
- 'sterling',
- 'section',
- 'bullet',
- 'paragraph',
- 'germandbls',
- 'registered',
- 'copyright',
- 'trademark',
- 'acute',
- 'dieresis',
- 'notequal',
- 'AE',
- 'Oslash',
- 'infinity',
- 'plusminus',
- 'lessequal',
- 'greaterequal',
- 'yen',
- 'mu',
- 'partialdiff',
- 'summation',
- 'product',
- 'pi',
- 'integral',
- 'ordfeminine',
- 'ordmasculine',
- 'Omega',
- 'ae',
- 'oslash',
- 'questiondown',
- 'exclamdown',
- 'logicalnot',
- 'radical',
- 'florin',
- 'approxequal',
- 'Delta',
- 'guillemotleft',
- 'guillemotright',
- 'ellipsis',
- 'space',
- 'Agrave',
- 'Atilde',
- 'Otilde',
- 'OE',
- 'oe',
- 'endash',
- 'emdash',
- 'quotedblleft',
- 'quotedblright',
- 'quoteleft',
- 'quoteright',
- 'divide',
- 'lozenge',
- 'ydieresis',
- 'Ydieresis',
- 'fraction',
- 'currency',
- 'guilsinglleft',
- 'guilsinglright',
- 'fi',
- 'fl',
- 'daggerdbl',
- 'periodcentered',
- 'quotesinglbase',
- 'quotedblbase',
- 'perthousand',
- 'Acircumflex',
- 'Ecircumflex',
- 'Aacute',
- 'Edieresis',
- 'Egrave',
- 'Iacute',
- 'Icircumflex',
- 'Idieresis',
- 'Igrave',
- 'Oacute',
- 'Ocircumflex',
- 'apple',
- 'Ograve',
- 'Uacute',
- 'Ucircumflex',
- 'Ugrave',
- 'dotlessi',
- 'circumflex',
- 'tilde',
- 'macron',
- 'breve',
- 'dotaccent',
- 'ring',
- 'cedilla',
- 'hungarumlaut',
- 'ogonek',
- 'caron'
- ];
- var StandardEncoding = [
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'space',
- 'exclam',
- 'quotedbl',
- 'numbersign',
- 'dollar',
- 'percent',
- 'ampersand',
- 'quoteright',
- 'parenleft',
- 'parenright',
- 'asterisk',
- 'plus',
- 'comma',
- 'hyphen',
- 'period',
- 'slash',
- 'zero',
- 'one',
- 'two',
- 'three',
- 'four',
- 'five',
- 'six',
- 'seven',
- 'eight',
- 'nine',
- 'colon',
- 'semicolon',
- 'less',
- 'equal',
- 'greater',
- 'question',
- 'at',
- 'A',
- 'B',
- 'C',
- 'D',
- 'E',
- 'F',
- 'G',
- 'H',
- 'I',
- 'J',
- 'K',
- 'L',
- 'M',
- 'N',
- 'O',
- 'P',
- 'Q',
- 'R',
- 'S',
- 'T',
- 'U',
- 'V',
- 'W',
- 'X',
- 'Y',
- 'Z',
- 'bracketleft',
- 'backslash',
- 'bracketright',
- 'asciicircum',
- 'underscore',
- 'quoteleft',
- 'a',
- 'b',
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i',
- 'j',
- 'k',
- 'l',
- 'm',
- 'n',
- 'o',
- 'p',
- 'q',
- 'r',
- 's',
- 't',
- 'u',
- 'v',
- 'w',
- 'x',
- 'y',
- 'z',
- 'braceleft',
- 'bar',
- 'braceright',
- 'asciitilde',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'exclamdown',
- 'cent',
- 'sterling',
- 'fraction',
- 'yen',
- 'florin',
- 'section',
- 'currency',
- 'quotesingle',
- 'quotedblleft',
- 'guillemotleft',
- 'guilsinglleft',
- 'guilsinglright',
- 'fi',
- 'fl',
- '',
- 'endash',
- 'dagger',
- 'daggerdbl',
- 'periodcentered',
- '',
- 'paragraph',
- 'bullet',
- 'quotesinglbase',
- 'quotedblbase',
- 'quotedblright',
- 'guillemotright',
- 'ellipsis',
- 'perthousand',
- '',
- 'questiondown',
- '',
- 'grave',
- 'acute',
- 'circumflex',
- 'tilde',
- 'macron',
- 'breve',
- 'dotaccent',
- 'dieresis',
- '',
- 'ring',
- 'cedilla',
- '',
- 'hungarumlaut',
- 'ogonek',
- 'caron',
- 'emdash',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'AE',
- '',
- 'ordfeminine',
- '',
- '',
- '',
- '',
- 'Lslash',
- 'Oslash',
- 'OE',
- 'ordmasculine',
- '',
- '',
- '',
- '',
- '',
- 'ae',
- '',
- '',
- '',
- 'dotlessi',
- '',
- '',
- 'lslash',
- 'oslash',
- 'oe',
- 'germandbls'
- ];
- var WinAnsiEncoding = [
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'space',
- 'exclam',
- 'quotedbl',
- 'numbersign',
- 'dollar',
- 'percent',
- 'ampersand',
- 'quotesingle',
- 'parenleft',
- 'parenright',
- 'asterisk',
- 'plus',
- 'comma',
- 'hyphen',
- 'period',
- 'slash',
- 'zero',
- 'one',
- 'two',
- 'three',
- 'four',
- 'five',
- 'six',
- 'seven',
- 'eight',
- 'nine',
- 'colon',
- 'semicolon',
- 'less',
- 'equal',
- 'greater',
- 'question',
- 'at',
- 'A',
- 'B',
- 'C',
- 'D',
- 'E',
- 'F',
- 'G',
- 'H',
- 'I',
- 'J',
- 'K',
- 'L',
- 'M',
- 'N',
- 'O',
- 'P',
- 'Q',
- 'R',
- 'S',
- 'T',
- 'U',
- 'V',
- 'W',
- 'X',
- 'Y',
- 'Z',
- 'bracketleft',
- 'backslash',
- 'bracketright',
- 'asciicircum',
- 'underscore',
- 'grave',
- 'a',
- 'b',
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i',
- 'j',
- 'k',
- 'l',
- 'm',
- 'n',
- 'o',
- 'p',
- 'q',
- 'r',
- 's',
- 't',
- 'u',
- 'v',
- 'w',
- 'x',
- 'y',
- 'z',
- 'braceleft',
- 'bar',
- 'braceright',
- 'asciitilde',
- 'bullet',
- 'Euro',
- 'bullet',
- 'quotesinglbase',
- 'florin',
- 'quotedblbase',
- 'ellipsis',
- 'dagger',
- 'daggerdbl',
- 'circumflex',
- 'perthousand',
- 'Scaron',
- 'guilsinglleft',
- 'OE',
- 'bullet',
- 'Zcaron',
- 'bullet',
- 'bullet',
- 'quoteleft',
- 'quoteright',
- 'quotedblleft',
- 'quotedblright',
- 'bullet',
- 'endash',
- 'emdash',
- 'tilde',
- 'trademark',
- 'scaron',
- 'guilsinglright',
- 'oe',
- 'bullet',
- 'zcaron',
- 'Ydieresis',
- 'space',
- 'exclamdown',
- 'cent',
- 'sterling',
- 'currency',
- 'yen',
- 'brokenbar',
- 'section',
- 'dieresis',
- 'copyright',
- 'ordfeminine',
- 'guillemotleft',
- 'logicalnot',
- 'hyphen',
- 'registered',
- 'macron',
- 'degree',
- 'plusminus',
- 'twosuperior',
- 'threesuperior',
- 'acute',
- 'mu',
- 'paragraph',
- 'periodcentered',
- 'cedilla',
- 'onesuperior',
- 'ordmasculine',
- 'guillemotright',
- 'onequarter',
- 'onehalf',
- 'threequarters',
- 'questiondown',
- 'Agrave',
- 'Aacute',
- 'Acircumflex',
- 'Atilde',
- 'Adieresis',
- 'Aring',
- 'AE',
- 'Ccedilla',
- 'Egrave',
- 'Eacute',
- 'Ecircumflex',
- 'Edieresis',
- 'Igrave',
- 'Iacute',
- 'Icircumflex',
- 'Idieresis',
- 'Eth',
- 'Ntilde',
- 'Ograve',
- 'Oacute',
- 'Ocircumflex',
- 'Otilde',
- 'Odieresis',
- 'multiply',
- 'Oslash',
- 'Ugrave',
- 'Uacute',
- 'Ucircumflex',
- 'Udieresis',
- 'Yacute',
- 'Thorn',
- 'germandbls',
- 'agrave',
- 'aacute',
- 'acircumflex',
- 'atilde',
- 'adieresis',
- 'aring',
- 'ae',
- 'ccedilla',
- 'egrave',
- 'eacute',
- 'ecircumflex',
- 'edieresis',
- 'igrave',
- 'iacute',
- 'icircumflex',
- 'idieresis',
- 'eth',
- 'ntilde',
- 'ograve',
- 'oacute',
- 'ocircumflex',
- 'otilde',
- 'odieresis',
- 'divide',
- 'oslash',
- 'ugrave',
- 'uacute',
- 'ucircumflex',
- 'udieresis',
- 'yacute',
- 'thorn',
- 'ydieresis'
- ];
- var SymbolSetEncoding = [
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'space',
- 'exclam',
- 'universal',
- 'numbersign',
- 'existential',
- 'percent',
- 'ampersand',
- 'suchthat',
- 'parenleft',
- 'parenright',
- 'asteriskmath',
- 'plus',
- 'comma',
- 'minus',
- 'period',
- 'slash',
- 'zero',
- 'one',
- 'two',
- 'three',
- 'four',
- 'five',
- 'six',
- 'seven',
- 'eight',
- 'nine',
- 'colon',
- 'semicolon',
- 'less',
- 'equal',
- 'greater',
- 'question',
- 'congruent',
- 'Alpha',
- 'Beta',
- 'Chi',
- 'Delta',
- 'Epsilon',
- 'Phi',
- 'Gamma',
- 'Eta',
- 'Iota',
- 'theta1',
- 'Kappa',
- 'Lambda',
- 'Mu',
- 'Nu',
- 'Omicron',
- 'Pi',
- 'Theta',
- 'Rho',
- 'Sigma',
- 'Tau',
- 'Upsilon',
- 'sigma1',
- 'Omega',
- 'Xi',
- 'Psi',
- 'Zeta',
- 'bracketleft',
- 'therefore',
- 'bracketright',
- 'perpendicular',
- 'underscore',
- 'radicalex',
- 'alpha',
- 'beta',
- 'chi',
- 'delta',
- 'epsilon',
- 'phi',
- 'gamma',
- 'eta',
- 'iota',
- 'phi1',
- 'kappa',
- 'lambda',
- 'mu',
- 'nu',
- 'omicron',
- 'pi',
- 'theta',
- 'rho',
- 'sigma',
- 'tau',
- 'upsilon',
- 'omega1',
- 'omega',
- 'xi',
- 'psi',
- 'zeta',
- 'braceleft',
- 'bar',
- 'braceright',
- 'similar',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'Euro',
- 'Upsilon1',
- 'minute',
- 'lessequal',
- 'fraction',
- 'infinity',
- 'florin',
- 'club',
- 'diamond',
- 'heart',
- 'spade',
- 'arrowboth',
- 'arrowleft',
- 'arrowup',
- 'arrowright',
- 'arrowdown',
- 'degree',
- 'plusminus',
- 'second',
- 'greaterequal',
- 'multiply',
- 'proportional',
- 'partialdiff',
- 'bullet',
- 'divide',
- 'notequal',
- 'equivalence',
- 'approxequal',
- 'ellipsis',
- 'arrowvertex',
- 'arrowhorizex',
- 'carriagereturn',
- 'aleph',
- 'Ifraktur',
- 'Rfraktur',
- 'weierstrass',
- 'circlemultiply',
- 'circleplus',
- 'emptyset',
- 'intersection',
- 'union',
- 'propersuperset',
- 'reflexsuperset',
- 'notsubset',
- 'propersubset',
- 'reflexsubset',
- 'element',
- 'notelement',
- 'angle',
- 'gradient',
- 'registerserif',
- 'copyrightserif',
- 'trademarkserif',
- 'product',
- 'radical',
- 'dotmath',
- 'logicalnot',
- 'logicaland',
- 'logicalor',
- 'arrowdblboth',
- 'arrowdblleft',
- 'arrowdblup',
- 'arrowdblright',
- 'arrowdbldown',
- 'lozenge',
- 'angleleft',
- 'registersans',
- 'copyrightsans',
- 'trademarksans',
- 'summation',
- 'parenlefttp',
- 'parenleftex',
- 'parenleftbt',
- 'bracketlefttp',
- 'bracketleftex',
- 'bracketleftbt',
- 'bracelefttp',
- 'braceleftmid',
- 'braceleftbt',
- 'braceex',
- '',
- 'angleright',
- 'integral',
- 'integraltp',
- 'integralex',
- 'integralbt',
- 'parenrighttp',
- 'parenrightex',
- 'parenrightbt',
- 'bracketrighttp',
- 'bracketrightex',
- 'bracketrightbt',
- 'bracerighttp',
- 'bracerightmid',
- 'bracerightbt'
- ];
- var ZapfDingbatsEncoding = [
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'space',
- 'a1',
- 'a2',
- 'a202',
- 'a3',
- 'a4',
- 'a5',
- 'a119',
- 'a118',
- 'a117',
- 'a11',
- 'a12',
- 'a13',
- 'a14',
- 'a15',
- 'a16',
- 'a105',
- 'a17',
- 'a18',
- 'a19',
- 'a20',
- 'a21',
- 'a22',
- 'a23',
- 'a24',
- 'a25',
- 'a26',
- 'a27',
- 'a28',
- 'a6',
- 'a7',
- 'a8',
- 'a9',
- 'a10',
- 'a29',
- 'a30',
- 'a31',
- 'a32',
- 'a33',
- 'a34',
- 'a35',
- 'a36',
- 'a37',
- 'a38',
- 'a39',
- 'a40',
- 'a41',
- 'a42',
- 'a43',
- 'a44',
- 'a45',
- 'a46',
- 'a47',
- 'a48',
- 'a49',
- 'a50',
- 'a51',
- 'a52',
- 'a53',
- 'a54',
- 'a55',
- 'a56',
- 'a57',
- 'a58',
- 'a59',
- 'a60',
- 'a61',
- 'a62',
- 'a63',
- 'a64',
- 'a65',
- 'a66',
- 'a67',
- 'a68',
- 'a69',
- 'a70',
- 'a71',
- 'a72',
- 'a73',
- 'a74',
- 'a203',
- 'a75',
- 'a204',
- 'a76',
- 'a77',
- 'a78',
- 'a79',
- 'a81',
- 'a82',
- 'a83',
- 'a84',
- 'a97',
- 'a98',
- 'a99',
- 'a100',
- '',
- 'a89',
- 'a90',
- 'a93',
- 'a94',
- 'a91',
- 'a92',
- 'a205',
- 'a85',
- 'a206',
- 'a86',
- 'a87',
- 'a88',
- 'a95',
- 'a96',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- 'a101',
- 'a102',
- 'a103',
- 'a104',
- 'a106',
- 'a107',
- 'a108',
- 'a112',
- 'a111',
- 'a110',
- 'a109',
- 'a120',
- 'a121',
- 'a122',
- 'a123',
- 'a124',
- 'a125',
- 'a126',
- 'a127',
- 'a128',
- 'a129',
- 'a130',
- 'a131',
- 'a132',
- 'a133',
- 'a134',
- 'a135',
- 'a136',
- 'a137',
- 'a138',
- 'a139',
- 'a140',
- 'a141',
- 'a142',
- 'a143',
- 'a144',
- 'a145',
- 'a146',
- 'a147',
- 'a148',
- 'a149',
- 'a150',
- 'a151',
- 'a152',
- 'a153',
- 'a154',
- 'a155',
- 'a156',
- 'a157',
- 'a158',
- 'a159',
- 'a160',
- 'a161',
- 'a163',
- 'a164',
- 'a196',
- 'a165',
- 'a192',
- 'a166',
- 'a167',
- 'a168',
- 'a169',
- 'a170',
- 'a171',
- 'a172',
- 'a173',
- 'a162',
- 'a174',
- 'a175',
- 'a176',
- 'a177',
- 'a178',
- 'a179',
- 'a193',
- 'a180',
- 'a199',
- 'a181',
- 'a200',
- 'a182',
- '',
- 'a201',
- 'a183',
- 'a184',
- 'a197',
- 'a185',
- 'a194',
- 'a198',
- 'a186',
- 'a195',
- 'a187',
- 'a188',
- 'a189',
- 'a190',
- 'a191'
- ];
- function getEncoding(encodingName) {
- switch (encodingName) {
- case 'WinAnsiEncoding':
- return WinAnsiEncoding;
- case 'StandardEncoding':
- return StandardEncoding;
- case 'MacRomanEncoding':
- return MacRomanEncoding;
- case 'SymbolSetEncoding':
- return SymbolSetEncoding;
- case 'ZapfDingbatsEncoding':
- return ZapfDingbatsEncoding;
- case 'ExpertEncoding':
- return ExpertEncoding;
- case 'MacExpertEncoding':
- return MacExpertEncoding;
- default:
- return null;
- }
- }
- exports.WinAnsiEncoding = WinAnsiEncoding;
- exports.StandardEncoding = StandardEncoding;
- exports.MacRomanEncoding = MacRomanEncoding;
- exports.SymbolSetEncoding = SymbolSetEncoding;
- exports.ZapfDingbatsEncoding = ZapfDingbatsEncoding;
- exports.ExpertEncoding = ExpertEncoding;
- exports.getEncoding = getEncoding;
- }));
- (function (root, factory) {
- factory(root.pdfjsSharedUtil = {});
- }(this, function (exports) {
- var globalScope = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this;
- var FONT_IDENTITY_MATRIX = [
- 0.001,
- 0,
- 0,
- 0.001,
- 0,
- 0
- ];
- var TextRenderingMode = {
- FILL: 0,
- STROKE: 1,
- FILL_STROKE: 2,
- INVISIBLE: 3,
- FILL_ADD_TO_PATH: 4,
- STROKE_ADD_TO_PATH: 5,
- FILL_STROKE_ADD_TO_PATH: 6,
- ADD_TO_PATH: 7,
- FILL_STROKE_MASK: 3,
- ADD_TO_PATH_FLAG: 4
- };
- var ImageKind = {
- GRAYSCALE_1BPP: 1,
- RGB_24BPP: 2,
- RGBA_32BPP: 3
- };
- var AnnotationType = {
- TEXT: 1,
- LINK: 2,
- FREETEXT: 3,
- LINE: 4,
- SQUARE: 5,
- CIRCLE: 6,
- POLYGON: 7,
- POLYLINE: 8,
- HIGHLIGHT: 9,
- UNDERLINE: 10,
- SQUIGGLY: 11,
- STRIKEOUT: 12,
- STAMP: 13,
- CARET: 14,
- INK: 15,
- POPUP: 16,
- FILEATTACHMENT: 17,
- SOUND: 18,
- MOVIE: 19,
- WIDGET: 20,
- SCREEN: 21,
- PRINTERMARK: 22,
- TRAPNET: 23,
- WATERMARK: 24,
- THREED: 25,
- REDACT: 26
- };
- var AnnotationFlag = {
- INVISIBLE: 0x01,
- HIDDEN: 0x02,
- PRINT: 0x04,
- NOZOOM: 0x08,
- NOROTATE: 0x10,
- NOVIEW: 0x20,
- READONLY: 0x40,
- LOCKED: 0x80,
- TOGGLENOVIEW: 0x100,
- LOCKEDCONTENTS: 0x200
- };
- var AnnotationFieldFlag = {
- READONLY: 0x0000001,
- REQUIRED: 0x0000002,
- NOEXPORT: 0x0000004,
- MULTILINE: 0x0001000,
- PASSWORD: 0x0002000,
- NOTOGGLETOOFF: 0x0004000,
- RADIO: 0x0008000,
- PUSHBUTTON: 0x0010000,
- COMBO: 0x0020000,
- EDIT: 0x0040000,
- SORT: 0x0080000,
- FILESELECT: 0x0100000,
- MULTISELECT: 0x0200000,
- DONOTSPELLCHECK: 0x0400000,
- DONOTSCROLL: 0x0800000,
- COMB: 0x1000000,
- RICHTEXT: 0x2000000,
- RADIOSINUNISON: 0x2000000,
- COMMITONSELCHANGE: 0x4000000
- };
- var AnnotationBorderStyleType = {
- SOLID: 1,
- DASHED: 2,
- BEVELED: 3,
- INSET: 4,
- UNDERLINE: 5
- };
- var StreamType = {
- UNKNOWN: 0,
- FLATE: 1,
- LZW: 2,
- DCT: 3,
- JPX: 4,
- JBIG: 5,
- A85: 6,
- AHX: 7,
- CCF: 8,
- RL: 9
- };
- var FontType = {
- UNKNOWN: 0,
- TYPE1: 1,
- TYPE1C: 2,
- CIDFONTTYPE0: 3,
- CIDFONTTYPE0C: 4,
- TRUETYPE: 5,
- CIDFONTTYPE2: 6,
- TYPE3: 7,
- OPENTYPE: 8,
- TYPE0: 9,
- MMTYPE1: 10
- };
- var VERBOSITY_LEVELS = {
- errors: 0,
- warnings: 1,
- infos: 5
- };
- // All the possible operations for an operator list.
- var OPS = {
- // Intentionally start from 1 so it is easy to spot bad operators that will be
- // 0's.
- dependency: 1,
- setLineWidth: 2,
- setLineCap: 3,
- setLineJoin: 4,
- setMiterLimit: 5,
- setDash: 6,
- setRenderingIntent: 7,
- setFlatness: 8,
- setGState: 9,
- save: 10,
- restore: 11,
- transform: 12,
- moveTo: 13,
- lineTo: 14,
- curveTo: 15,
- curveTo2: 16,
- curveTo3: 17,
- closePath: 18,
- rectangle: 19,
- stroke: 20,
- closeStroke: 21,
- fill: 22,
- eoFill: 23,
- fillStroke: 24,
- eoFillStroke: 25,
- closeFillStroke: 26,
- closeEOFillStroke: 27,
- endPath: 28,
- clip: 29,
- eoClip: 30,
- beginText: 31,
- endText: 32,
- setCharSpacing: 33,
- setWordSpacing: 34,
- setHScale: 35,
- setLeading: 36,
- setFont: 37,
- setTextRenderingMode: 38,
- setTextRise: 39,
- moveText: 40,
- setLeadingMoveText: 41,
- setTextMatrix: 42,
- nextLine: 43,
- showText: 44,
- showSpacedText: 45,
- nextLineShowText: 46,
- nextLineSetSpacingShowText: 47,
- setCharWidth: 48,
- setCharWidthAndBounds: 49,
- setStrokeColorSpace: 50,
- setFillColorSpace: 51,
- setStrokeColor: 52,
- setStrokeColorN: 53,
- setFillColor: 54,
- setFillColorN: 55,
- setStrokeGray: 56,
- setFillGray: 57,
- setStrokeRGBColor: 58,
- setFillRGBColor: 59,
- setStrokeCMYKColor: 60,
- setFillCMYKColor: 61,
- shadingFill: 62,
- beginInlineImage: 63,
- beginImageData: 64,
- endInlineImage: 65,
- paintXObject: 66,
- markPoint: 67,
- markPointProps: 68,
- beginMarkedContent: 69,
- beginMarkedContentProps: 70,
- endMarkedContent: 71,
- beginCompat: 72,
- endCompat: 73,
- paintFormXObjectBegin: 74,
- paintFormXObjectEnd: 75,
- beginGroup: 76,
- endGroup: 77,
- beginAnnotations: 78,
- endAnnotations: 79,
- beginAnnotation: 80,
- endAnnotation: 81,
- paintJpegXObject: 82,
- paintImageMaskXObject: 83,
- paintImageMaskXObjectGroup: 84,
- paintImageXObject: 85,
- paintInlineImageXObject: 86,
- paintInlineImageXObjectGroup: 87,
- paintImageXObjectRepeat: 88,
- paintImageMaskXObjectRepeat: 89,
- paintSolidColorImageMask: 90,
- constructPath: 91
- };
- var verbosity = VERBOSITY_LEVELS.warnings;
- function setVerbosityLevel(level) {
- verbosity = level;
- }
- function getVerbosityLevel() {
- return verbosity;
- }
- // A notice for devs. These are good for things that are helpful to devs, such
- // as warning that Workers were disabled, which is important to devs but not
- // end users.
- function info(msg) {
- if (verbosity >= VERBOSITY_LEVELS.infos) {
- console.log('Info: ' + msg);
- }
- }
- // Non-fatal warnings.
- function warn(msg) {
- if (verbosity >= VERBOSITY_LEVELS.warnings) {
- console.log('Warning: ' + msg);
- }
- }
- // Deprecated API function -- display regardless of the PDFJS.verbosity setting.
- function deprecated(details) {
- console.log('Deprecated API usage: ' + details);
- }
- // Fatal errors that should trigger the fallback UI and halt execution by
- // throwing an exception.
- function error(msg) {
- if (verbosity >= VERBOSITY_LEVELS.errors) {
- console.log('Error: ' + msg);
- console.log(backtrace());
- }
- throw new Error(msg);
- }
- function backtrace() {
- try {
- throw new Error();
- } catch (e) {
- return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
- }
- }
- function assert(cond, msg) {
- if (!cond) {
- error(msg);
- }
- }
- var UNSUPPORTED_FEATURES = {
- unknown: 'unknown',
- forms: 'forms',
- javaScript: 'javaScript',
- smask: 'smask',
- shadingPattern: 'shadingPattern',
- font: 'font'
- };
- // Checks if URLs have the same origin. For non-HTTP based URLs, returns false.
- function isSameOrigin(baseUrl, otherUrl) {
- try {
- var base = new URL(baseUrl);
- if (!base.origin || base.origin === 'null') {
- return false;
- }
- } // non-HTTP url
- catch (e) {
- return false;
- }
- var other = new URL(otherUrl, base);
- return base.origin === other.origin;
- }
- // Checks if URLs use one of the whitelisted protocols, e.g. to avoid XSS.
- function isValidProtocol(url) {
- if (!url) {
- return false;
- }
- switch (url.protocol) {
- case 'http:':
- case 'https:':
- case 'ftp:':
- case 'mailto:':
- case 'tel:':
- return true;
- default:
- return false;
- }
- }
- /**
- * Attempts to create a valid absolute URL (utilizing `isValidProtocol`).
- * @param {URL|string} url - An absolute, or relative, URL.
- * @param {URL|string} baseUrl - An absolute URL.
- * @returns Either a valid {URL}, or `null` otherwise.
- */
- function createValidAbsoluteUrl(url, baseUrl) {
- if (!url) {
- return null;
- }
- try {
- var absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url);
- if (isValidProtocol(absoluteUrl)) {
- return absoluteUrl;
- }
- } catch (ex) {
- }
- return null;
- }
- function shadow(obj, prop, value) {
- Object.defineProperty(obj, prop, {
- value: value,
- enumerable: true,
- configurable: true,
- writable: false
- });
- return value;
- }
- function getLookupTableFactory(initializer) {
- var lookup;
- return function () {
- if (initializer) {
- lookup = Object.create(null);
- initializer(lookup);
- initializer = null;
- }
- return lookup;
- };
- }
- var PasswordResponses = {
- NEED_PASSWORD: 1,
- INCORRECT_PASSWORD: 2
- };
- var PasswordException = function PasswordExceptionClosure() {
- function PasswordException(msg, code) {
- this.name = 'PasswordException';
- this.message = msg;
- this.code = code;
- }
- PasswordException.prototype = new Error();
- PasswordException.constructor = PasswordException;
- return PasswordException;
- }();
- var UnknownErrorException = function UnknownErrorExceptionClosure() {
- function UnknownErrorException(msg, details) {
- this.name = 'UnknownErrorException';
- this.message = msg;
- this.details = details;
- }
- UnknownErrorException.prototype = new Error();
- UnknownErrorException.constructor = UnknownErrorException;
- return UnknownErrorException;
- }();
- var InvalidPDFException = function InvalidPDFExceptionClosure() {
- function InvalidPDFException(msg) {
- this.name = 'InvalidPDFException';
- this.message = msg;
- }
- InvalidPDFException.prototype = new Error();
- InvalidPDFException.constructor = InvalidPDFException;
- return InvalidPDFException;
- }();
- var MissingPDFException = function MissingPDFExceptionClosure() {
- function MissingPDFException(msg) {
- this.name = 'MissingPDFException';
- this.message = msg;
- }
- MissingPDFException.prototype = new Error();
- MissingPDFException.constructor = MissingPDFException;
- return MissingPDFException;
- }();
- var UnexpectedResponseException = function UnexpectedResponseExceptionClosure() {
- function UnexpectedResponseException(msg, status) {
- this.name = 'UnexpectedResponseException';
- this.message = msg;
- this.status = status;
- }
- UnexpectedResponseException.prototype = new Error();
- UnexpectedResponseException.constructor = UnexpectedResponseException;
- return UnexpectedResponseException;
- }();
- var NotImplementedException = function NotImplementedExceptionClosure() {
- function NotImplementedException(msg) {
- this.message = msg;
- }
- NotImplementedException.prototype = new Error();
- NotImplementedException.prototype.name = 'NotImplementedException';
- NotImplementedException.constructor = NotImplementedException;
- return NotImplementedException;
- }();
- var MissingDataException = function MissingDataExceptionClosure() {
- function MissingDataException(begin, end) {
- this.begin = begin;
- this.end = end;
- this.message = 'Missing data [' + begin + ', ' + end + ')';
- }
- MissingDataException.prototype = new Error();
- MissingDataException.prototype.name = 'MissingDataException';
- MissingDataException.constructor = MissingDataException;
- return MissingDataException;
- }();
- var XRefParseException = function XRefParseExceptionClosure() {
- function XRefParseException(msg) {
- this.message = msg;
- }
- XRefParseException.prototype = new Error();
- XRefParseException.prototype.name = 'XRefParseException';
- XRefParseException.constructor = XRefParseException;
- return XRefParseException;
- }();
- var NullCharactersRegExp = /\x00/g;
- function removeNullCharacters(str) {
- if (typeof str !== 'string') {
- warn('The argument for removeNullCharacters must be a string.');
- return str;
- }
- return str.replace(NullCharactersRegExp, '');
- }
- function bytesToString(bytes) {
- assert(bytes !== null && typeof bytes === 'object' && bytes.length !== undefined, 'Invalid argument for bytesToString');
- var length = bytes.length;
- var MAX_ARGUMENT_COUNT = 8192;
- if (length < MAX_ARGUMENT_COUNT) {
- return String.fromCharCode.apply(null, bytes);
- }
- var strBuf = [];
- for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
- var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
- var chunk = bytes.subarray(i, chunkEnd);
- strBuf.push(String.fromCharCode.apply(null, chunk));
- }
- return strBuf.join('');
- }
- function stringToBytes(str) {
- assert(typeof str === 'string', 'Invalid argument for stringToBytes');
- var length = str.length;
- var bytes = new Uint8Array(length);
- for (var i = 0; i < length; ++i) {
- bytes[i] = str.charCodeAt(i) & 0xFF;
- }
- return bytes;
- }
- /**
- * Gets length of the array (Array, Uint8Array, or string) in bytes.
- * @param {Array|Uint8Array|string} arr
- * @returns {number}
- */
- function arrayByteLength(arr) {
- if (arr.length !== undefined) {
- return arr.length;
- }
- assert(arr.byteLength !== undefined);
- return arr.byteLength;
- }
- /**
- * Combines array items (arrays) into single Uint8Array object.
- * @param {Array} arr - the array of the arrays (Array, Uint8Array, or string).
- * @returns {Uint8Array}
- */
- function arraysToBytes(arr) {
- // Shortcut: if first and only item is Uint8Array, return it.
- if (arr.length === 1 && arr[0] instanceof Uint8Array) {
- return arr[0];
- }
- var resultLength = 0;
- var i, ii = arr.length;
- var item, itemLength;
- for (i = 0; i < ii; i++) {
- item = arr[i];
- itemLength = arrayByteLength(item);
- resultLength += itemLength;
- }
- var pos = 0;
- var data = new Uint8Array(resultLength);
- for (i = 0; i < ii; i++) {
- item = arr[i];
- if (!(item instanceof Uint8Array)) {
- if (typeof item === 'string') {
- item = stringToBytes(item);
- } else {
- item = new Uint8Array(item);
- }
- }
- itemLength = item.byteLength;
- data.set(item, pos);
- pos += itemLength;
- }
- return data;
- }
- function string32(value) {
- return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);
- }
- function log2(x) {
- var n = 1, i = 0;
- while (x > n) {
- n <<= 1;
- i++;
- }
- return i;
- }
- function readInt8(data, start) {
- return data[start] << 24 >> 24;
- }
- function readUint16(data, offset) {
- return data[offset] << 8 | data[offset + 1];
- }
- function readUint32(data, offset) {
- return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0;
- }
- // Lazy test the endianness of the platform
- // NOTE: This will be 'true' for simulated TypedArrays
- function isLittleEndian() {
- var buffer8 = new Uint8Array(2);
- buffer8[0] = 1;
- var buffer16 = new Uint16Array(buffer8.buffer);
- return buffer16[0] === 1;
- }
- // Checks if it's possible to eval JS expressions.
- function isEvalSupported() {
- try {
- new Function('');
- return true;
- } catch (e) {
- return false;
- }
- }
- var IDENTITY_MATRIX = [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0
- ];
- var Util = function UtilClosure() {
- function Util() {
- }
- var rgbBuf = [
- 'rgb(',
- 0,
- ',',
- 0,
- ',',
- 0,
- ')'
- ];
- // makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids
- // creating many intermediate strings.
- Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
- rgbBuf[1] = r;
- rgbBuf[3] = g;
- rgbBuf[5] = b;
- return rgbBuf.join('');
- };
- // Concatenates two transformation matrices together and returns the result.
- Util.transform = function Util_transform(m1, m2) {
- return [
- m1[0] * m2[0] + m1[2] * m2[1],
- m1[1] * m2[0] + m1[3] * m2[1],
- m1[0] * m2[2] + m1[2] * m2[3],
- m1[1] * m2[2] + m1[3] * m2[3],
- m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
- m1[1] * m2[4] + m1[3] * m2[5] + m1[5]
- ];
- };
- // For 2d affine transforms
- Util.applyTransform = function Util_applyTransform(p, m) {
- var xt = p[0] * m[0] + p[1] * m[2] + m[4];
- var yt = p[0] * m[1] + p[1] * m[3] + m[5];
- return [
- xt,
- yt
- ];
- };
- Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
- var d = m[0] * m[3] - m[1] * m[2];
- var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
- var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
- return [
- xt,
- yt
- ];
- };
- // Applies the transform to the rectangle and finds the minimum axially
- // aligned bounding box.
- Util.getAxialAlignedBoundingBox = function Util_getAxialAlignedBoundingBox(r, m) {
- var p1 = Util.applyTransform(r, m);
- var p2 = Util.applyTransform(r.slice(2, 4), m);
- var p3 = Util.applyTransform([
- r[0],
- r[3]
- ], m);
- var p4 = Util.applyTransform([
- r[2],
- r[1]
- ], m);
- return [
- Math.min(p1[0], p2[0], p3[0], p4[0]),
- Math.min(p1[1], p2[1], p3[1], p4[1]),
- Math.max(p1[0], p2[0], p3[0], p4[0]),
- Math.max(p1[1], p2[1], p3[1], p4[1])
- ];
- };
- Util.inverseTransform = function Util_inverseTransform(m) {
- var d = m[0] * m[3] - m[1] * m[2];
- return [
- m[3] / d,
- -m[1] / d,
- -m[2] / d,
- m[0] / d,
- (m[2] * m[5] - m[4] * m[3]) / d,
- (m[4] * m[1] - m[5] * m[0]) / d
- ];
- };
- // Apply a generic 3d matrix M on a 3-vector v:
- // | a b c | | X |
- // | d e f | x | Y |
- // | g h i | | Z |
- // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
- // with v as [X,Y,Z]
- Util.apply3dTransform = function Util_apply3dTransform(m, v) {
- return [
- m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
- m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
- m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
- ];
- };
- // This calculation uses Singular Value Decomposition.
- // The SVD can be represented with formula A = USV. We are interested in the
- // matrix S here because it represents the scale values.
- Util.singularValueDecompose2dScale = function Util_singularValueDecompose2dScale(m) {
- var transpose = [
- m[0],
- m[2],
- m[1],
- m[3]
- ];
- // Multiply matrix m with its transpose.
- var a = m[0] * transpose[0] + m[1] * transpose[2];
- var b = m[0] * transpose[1] + m[1] * transpose[3];
- var c = m[2] * transpose[0] + m[3] * transpose[2];
- var d = m[2] * transpose[1] + m[3] * transpose[3];
- // Solve the second degree polynomial to get roots.
- var first = (a + d) / 2;
- var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
- var sx = first + second || 1;
- var sy = first - second || 1;
- // Scale values are the square roots of the eigenvalues.
- return [
- Math.sqrt(sx),
- Math.sqrt(sy)
- ];
- };
- // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
- // For coordinate systems whose origin lies in the bottom-left, this
- // means normalization to (BL,TR) ordering. For systems with origin in the
- // top-left, this means (TL,BR) ordering.
- Util.normalizeRect = function Util_normalizeRect(rect) {
- var r = rect.slice(0);
- // clone rect
- if (rect[0] > rect[2]) {
- r[0] = rect[2];
- r[2] = rect[0];
- }
- if (rect[1] > rect[3]) {
- r[1] = rect[3];
- r[3] = rect[1];
- }
- return r;
- };
- // Returns a rectangle [x1, y1, x2, y2] corresponding to the
- // intersection of rect1 and rect2. If no intersection, returns 'false'
- // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
- Util.intersect = function Util_intersect(rect1, rect2) {
- function compare(a, b) {
- return a - b;
- }
- // Order points along the axes
- var orderedX = [
- rect1[0],
- rect1[2],
- rect2[0],
- rect2[2]
- ].sort(compare), orderedY = [
- rect1[1],
- rect1[3],
- rect2[1],
- rect2[3]
- ].sort(compare), result = [];
- rect1 = Util.normalizeRect(rect1);
- rect2 = Util.normalizeRect(rect2);
- // X: first and second points belong to different rectangles?
- if (orderedX[0] === rect1[0] && orderedX[1] === rect2[0] || orderedX[0] === rect2[0] && orderedX[1] === rect1[0]) {
- // Intersection must be between second and third points
- result[0] = orderedX[1];
- result[2] = orderedX[2];
- } else {
- return false;
- }
- // Y: first and second points belong to different rectangles?
- if (orderedY[0] === rect1[1] && orderedY[1] === rect2[1] || orderedY[0] === rect2[1] && orderedY[1] === rect1[1]) {
- // Intersection must be between second and third points
- result[1] = orderedY[1];
- result[3] = orderedY[2];
- } else {
- return false;
- }
- return result;
- };
- Util.sign = function Util_sign(num) {
- return num < 0 ? -1 : 1;
- };
- var ROMAN_NUMBER_MAP = [
- '',
- 'C',
- 'CC',
- 'CCC',
- 'CD',
- 'D',
- 'DC',
- 'DCC',
- 'DCCC',
- 'CM',
- '',
- 'X',
- 'XX',
- 'XXX',
- 'XL',
- 'L',
- 'LX',
- 'LXX',
- 'LXXX',
- 'XC',
- '',
- 'I',
- 'II',
- 'III',
- 'IV',
- 'V',
- 'VI',
- 'VII',
- 'VIII',
- 'IX'
- ];
- /**
- * Converts positive integers to (upper case) Roman numerals.
- * @param {integer} number - The number that should be converted.
- * @param {boolean} lowerCase - Indicates if the result should be converted
- * to lower case letters. The default is false.
- * @return {string} The resulting Roman number.
- */
- Util.toRoman = function Util_toRoman(number, lowerCase) {
- assert(isInt(number) && number > 0, 'The number should be a positive integer.');
- var pos, romanBuf = [];
- // Thousands
- while (number >= 1000) {
- number -= 1000;
- romanBuf.push('M');
- }
- // Hundreds
- pos = number / 100 | 0;
- number %= 100;
- romanBuf.push(ROMAN_NUMBER_MAP[pos]);
- // Tens
- pos = number / 10 | 0;
- number %= 10;
- romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
- // Ones
- romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
- var romanStr = romanBuf.join('');
- return lowerCase ? romanStr.toLowerCase() : romanStr;
- };
- Util.appendToArray = function Util_appendToArray(arr1, arr2) {
- Array.prototype.push.apply(arr1, arr2);
- };
- Util.prependToArray = function Util_prependToArray(arr1, arr2) {
- Array.prototype.unshift.apply(arr1, arr2);
- };
- Util.extendObj = function extendObj(obj1, obj2) {
- for (var key in obj2) {
- obj1[key] = obj2[key];
- }
- };
- Util.getInheritableProperty = function Util_getInheritableProperty(dict, name, getArray) {
- while (dict && !dict.has(name)) {
- dict = dict.get('Parent');
- }
- if (!dict) {
- return null;
- }
- return getArray ? dict.getArray(name) : dict.get(name);
- };
- Util.inherit = function Util_inherit(sub, base, prototype) {
- sub.prototype = Object.create(base.prototype);
- sub.prototype.constructor = sub;
- for (var prop in prototype) {
- sub.prototype[prop] = prototype[prop];
- }
- };
- Util.loadScript = function Util_loadScript(src, callback) {
- var script = document.createElement('script');
- var loaded = false;
- script.setAttribute('src', src);
- if (callback) {
- script.onload = function () {
- if (!loaded) {
- callback();
- }
- loaded = true;
- };
- }
- document.getElementsByTagName('head')[0].appendChild(script);
- };
- return Util;
- }();
- /**
- * PDF page viewport created based on scale, rotation and offset.
- * @class
- * @alias PageViewport
- */
- var PageViewport = function PageViewportClosure() {
- /**
- * @constructor
- * @private
- * @param viewBox {Array} xMin, yMin, xMax and yMax coordinates.
- * @param scale {number} scale of the viewport.
- * @param rotation {number} rotations of the viewport in degrees.
- * @param offsetX {number} offset X
- * @param offsetY {number} offset Y
- * @param dontFlip {boolean} if true, axis Y will not be flipped.
- */
- function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) {
- this.viewBox = viewBox;
- this.scale = scale;
- this.rotation = rotation;
- this.offsetX = offsetX;
- this.offsetY = offsetY;
- // creating transform to convert pdf coordinate system to the normal
- // canvas like coordinates taking in account scale and rotation
- var centerX = (viewBox[2] + viewBox[0]) / 2;
- var centerY = (viewBox[3] + viewBox[1]) / 2;
- var rotateA, rotateB, rotateC, rotateD;
- rotation = rotation % 360;
- rotation = rotation < 0 ? rotation + 360 : rotation;
- switch (rotation) {
- case 180:
- rotateA = -1;
- rotateB = 0;
- rotateC = 0;
- rotateD = 1;
- break;
- case 90:
- rotateA = 0;
- rotateB = 1;
- rotateC = 1;
- rotateD = 0;
- break;
- case 270:
- rotateA = 0;
- rotateB = -1;
- rotateC = -1;
- rotateD = 0;
- break;
- //case 0:
- default:
- rotateA = 1;
- rotateB = 0;
- rotateC = 0;
- rotateD = -1;
- break;
- }
- if (dontFlip) {
- rotateC = -rotateC;
- rotateD = -rotateD;
- }
- var offsetCanvasX, offsetCanvasY;
- var width, height;
- if (rotateA === 0) {
- offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
- offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
- width = Math.abs(viewBox[3] - viewBox[1]) * scale;
- height = Math.abs(viewBox[2] - viewBox[0]) * scale;
- } else {
- offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
- offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
- width = Math.abs(viewBox[2] - viewBox[0]) * scale;
- height = Math.abs(viewBox[3] - viewBox[1]) * scale;
- }
- // creating transform for the following operations:
- // translate(-centerX, -centerY), rotate and flip vertically,
- // scale, and translate(offsetCanvasX, offsetCanvasY)
- this.transform = [
- rotateA * scale,
- rotateB * scale,
- rotateC * scale,
- rotateD * scale,
- offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
- offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
- ];
- this.width = width;
- this.height = height;
- this.fontScale = scale;
- }
- PageViewport.prototype = /** @lends PageViewport.prototype */
- {
- /**
- * Clones viewport with additional properties.
- * @param args {Object} (optional) If specified, may contain the 'scale' or
- * 'rotation' properties to override the corresponding properties in
- * the cloned viewport.
- * @returns {PageViewport} Cloned viewport.
- */
- clone: function PageViewPort_clone(args) {
- args = args || {};
- var scale = 'scale' in args ? args.scale : this.scale;
- var rotation = 'rotation' in args ? args.rotation : this.rotation;
- return new PageViewport(this.viewBox.slice(), scale, rotation, this.offsetX, this.offsetY, args.dontFlip);
- },
- /**
- * Converts PDF point to the viewport coordinates. For examples, useful for
- * converting PDF location into canvas pixel coordinates.
- * @param x {number} X coordinate.
- * @param y {number} Y coordinate.
- * @returns {Object} Object that contains 'x' and 'y' properties of the
- * point in the viewport coordinate space.
- * @see {@link convertToPdfPoint}
- * @see {@link convertToViewportRectangle}
- */
- convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
- return Util.applyTransform([
- x,
- y
- ], this.transform);
- },
- /**
- * Converts PDF rectangle to the viewport coordinates.
- * @param rect {Array} xMin, yMin, xMax and yMax coordinates.
- * @returns {Array} Contains corresponding coordinates of the rectangle
- * in the viewport coordinate space.
- * @see {@link convertToViewportPoint}
- */
- convertToViewportRectangle: function PageViewport_convertToViewportRectangle(rect) {
- var tl = Util.applyTransform([
- rect[0],
- rect[1]
- ], this.transform);
- var br = Util.applyTransform([
- rect[2],
- rect[3]
- ], this.transform);
- return [
- tl[0],
- tl[1],
- br[0],
- br[1]
- ];
- },
- /**
- * Converts viewport coordinates to the PDF location. For examples, useful
- * for converting canvas pixel location into PDF one.
- * @param x {number} X coordinate.
- * @param y {number} Y coordinate.
- * @returns {Object} Object that contains 'x' and 'y' properties of the
- * point in the PDF coordinate space.
- * @see {@link convertToViewportPoint}
- */
- convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
- return Util.applyInverseTransform([
- x,
- y
- ], this.transform);
- }
- };
- return PageViewport;
- }();
- var PDFStringTranslateTable = [
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0x2D8,
- 0x2C7,
- 0x2C6,
- 0x2D9,
- 0x2DD,
- 0x2DB,
- 0x2DA,
- 0x2DC,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0x2022,
- 0x2020,
- 0x2021,
- 0x2026,
- 0x2014,
- 0x2013,
- 0x192,
- 0x2044,
- 0x2039,
- 0x203A,
- 0x2212,
- 0x2030,
- 0x201E,
- 0x201C,
- 0x201D,
- 0x2018,
- 0x2019,
- 0x201A,
- 0x2122,
- 0xFB01,
- 0xFB02,
- 0x141,
- 0x152,
- 0x160,
- 0x178,
- 0x17D,
- 0x131,
- 0x142,
- 0x153,
- 0x161,
- 0x17E,
- 0,
- 0x20AC
- ];
- function stringToPDFString(str) {
- var i, n = str.length, strBuf = [];
- if (str[0] === '\xFE' && str[1] === '\xFF') {
- // UTF16BE BOM
- for (i = 2; i < n; i += 2) {
- strBuf.push(String.fromCharCode(str.charCodeAt(i) << 8 | str.charCodeAt(i + 1)));
- }
- } else {
- for (i = 0; i < n; ++i) {
- var code = PDFStringTranslateTable[str.charCodeAt(i)];
- strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
- }
- }
- return strBuf.join('');
- }
- function stringToUTF8String(str) {
- return decodeURIComponent(escape(str));
- }
- function utf8StringToString(str) {
- return unescape(encodeURIComponent(str));
- }
- function isEmptyObj(obj) {
- for (var key in obj) {
- return false;
- }
- return true;
- }
- function isBool(v) {
- return typeof v === 'boolean';
- }
- function isInt(v) {
- return typeof v === 'number' && (v | 0) === v;
- }
- function isNum(v) {
- return typeof v === 'number';
- }
- function isString(v) {
- return typeof v === 'string';
- }
- function isArray(v) {
- return v instanceof Array;
- }
- function isArrayBuffer(v) {
- return typeof v === 'object' && v !== null && v.byteLength !== undefined;
- }
- // Checks if ch is one of the following characters: SPACE, TAB, CR or LF.
- function isSpace(ch) {
- return ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A;
- }
- /**
- * Promise Capability object.
- *
- * @typedef {Object} PromiseCapability
- * @property {Promise} promise - A promise object.
- * @property {function} resolve - Fulfills the promise.
- * @property {function} reject - Rejects the promise.
- */
- /**
- * Creates a promise capability object.
- * @alias createPromiseCapability
- *
- * @return {PromiseCapability} A capability object contains:
- * - a Promise, resolve and reject methods.
- */
- function createPromiseCapability() {
- var capability = {};
- capability.promise = new Promise(function (resolve, reject) {
- capability.resolve = resolve;
- capability.reject = reject;
- });
- return capability;
- }
- /**
- * Polyfill for Promises:
- * The following promise implementation tries to generally implement the
- * Promise/A+ spec. Some notable differences from other promise libraries are:
- * - There currently isn't a separate deferred and promise object.
- * - Unhandled rejections eventually show an error if they aren't handled.
- *
- * Based off of the work in:
- * https://bugzilla.mozilla.org/show_bug.cgi?id=810490
- */
- (function PromiseClosure() {
- if (globalScope.Promise) {
- // Promises existing in the DOM/Worker, checking presence of all/resolve
- if (typeof globalScope.Promise.all !== 'function') {
- globalScope.Promise.all = function (iterable) {
- var count = 0, results = [], resolve, reject;
- var promise = new globalScope.Promise(function (resolve_, reject_) {
- resolve = resolve_;
- reject = reject_;
- });
- iterable.forEach(function (p, i) {
- count++;
- p.then(function (result) {
- results[i] = result;
- count--;
- if (count === 0) {
- resolve(results);
- }
- }, reject);
- });
- if (count === 0) {
- resolve(results);
- }
- return promise;
- };
- }
- if (typeof globalScope.Promise.resolve !== 'function') {
- globalScope.Promise.resolve = function (value) {
- return new globalScope.Promise(function (resolve) {
- resolve(value);
- });
- };
- }
- if (typeof globalScope.Promise.reject !== 'function') {
- globalScope.Promise.reject = function (reason) {
- return new globalScope.Promise(function (resolve, reject) {
- reject(reason);
- });
- };
- }
- if (typeof globalScope.Promise.prototype.catch !== 'function') {
- globalScope.Promise.prototype.catch = function (onReject) {
- return globalScope.Promise.prototype.then(undefined, onReject);
- };
- }
- return;
- }
- throw new Error('DOM Promise is not present');
- }());
- var StatTimer = function StatTimerClosure() {
- function rpad(str, pad, length) {
- while (str.length < length) {
- str += pad;
- }
- return str;
- }
- function StatTimer() {
- this.started = Object.create(null);
- this.times = [];
- this.enabled = true;
- }
- StatTimer.prototype = {
- time: function StatTimer_time(name) {
- if (!this.enabled) {
- return;
- }
- if (name in this.started) {
- warn('Timer is already running for ' + name);
- }
- this.started[name] = Date.now();
- },
- timeEnd: function StatTimer_timeEnd(name) {
- if (!this.enabled) {
- return;
- }
- if (!(name in this.started)) {
- warn('Timer has not been started for ' + name);
- }
- this.times.push({
- 'name': name,
- 'start': this.started[name],
- 'end': Date.now()
- });
- // Remove timer from started so it can be called again.
- delete this.started[name];
- },
- toString: function StatTimer_toString() {
- var i, ii;
- var times = this.times;
- var out = '';
- // Find the longest name for padding purposes.
- var longest = 0;
- for (i = 0, ii = times.length; i < ii; ++i) {
- var name = times[i]['name'];
- if (name.length > longest) {
- longest = name.length;
- }
- }
- for (i = 0, ii = times.length; i < ii; ++i) {
- var span = times[i];
- var duration = span.end - span.start;
- out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
- }
- return out;
- }
- };
- return StatTimer;
- }();
- var createBlob = function createBlob(data, contentType) {
- if (typeof Blob !== 'undefined') {
- return new Blob([data], { type: contentType });
- }
- warn('The "Blob" constructor is not supported.');
- };
- var createObjectURL = function createObjectURLClosure() {
- // Blob/createObjectURL is not available, falling back to data schema.
- var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
- return function createObjectURL(data, contentType, forceDataSchema) {
- if (!forceDataSchema && typeof URL !== 'undefined' && URL.createObjectURL) {
- var blob = createBlob(data, contentType);
- return URL.createObjectURL(blob);
- }
- var buffer = 'data:' + contentType + ';base64,';
- for (var i = 0, ii = data.length; i < ii; i += 3) {
- var b1 = data[i] & 0xFF;
- var b2 = data[i + 1] & 0xFF;
- var b3 = data[i + 2] & 0xFF;
- var d1 = b1 >> 2, d2 = (b1 & 3) << 4 | b2 >> 4;
- var d3 = i + 1 < ii ? (b2 & 0xF) << 2 | b3 >> 6 : 64;
- var d4 = i + 2 < ii ? b3 & 0x3F : 64;
- buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
- }
- return buffer;
- };
- }();
- function MessageHandler(sourceName, targetName, comObj) {
- this.sourceName = sourceName;
- this.targetName = targetName;
- this.comObj = comObj;
- this.callbackIndex = 1;
- this.postMessageTransfers = true;
- var callbacksCapabilities = this.callbacksCapabilities = Object.create(null);
- var ah = this.actionHandler = Object.create(null);
- this._onComObjOnMessage = function messageHandlerComObjOnMessage(event) {
- var data = event.data;
- if (data.targetName !== this.sourceName) {
- return;
- }
- if (data.isReply) {
- var callbackId = data.callbackId;
- if (data.callbackId in callbacksCapabilities) {
- var callback = callbacksCapabilities[callbackId];
- delete callbacksCapabilities[callbackId];
- if ('error' in data) {
- callback.reject(data.error);
- } else {
- callback.resolve(data.data);
- }
- } else {
- error('Cannot resolve callback ' + callbackId);
- }
- } else if (data.action in ah) {
- var action = ah[data.action];
- if (data.callbackId) {
- var sourceName = this.sourceName;
- var targetName = data.sourceName;
- Promise.resolve().then(function () {
- return action[0].call(action[1], data.data);
- }).then(function (result) {
- comObj.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- isReply: true,
- callbackId: data.callbackId,
- data: result
- });
- }, function (reason) {
- if (reason instanceof Error) {
- // Serialize error to avoid "DataCloneError"
- reason = reason + '';
- }
- comObj.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- isReply: true,
- callbackId: data.callbackId,
- error: reason
- });
- });
- } else {
- action[0].call(action[1], data.data);
- }
- } else {
- error('Unknown action from worker: ' + data.action);
- }
- }.bind(this);
- comObj.addEventListener('message', this._onComObjOnMessage);
- }
- MessageHandler.prototype = {
- on: function messageHandlerOn(actionName, handler, scope) {
- var ah = this.actionHandler;
- if (ah[actionName]) {
- error('There is already an actionName called "' + actionName + '"');
- }
- ah[actionName] = [
- handler,
- scope
- ];
- },
- /**
- * Sends a message to the comObj to invoke the action with the supplied data.
- * @param {String} actionName Action to call.
- * @param {JSON} data JSON data to send.
- * @param {Array} [transfers] Optional list of transfers/ArrayBuffers
- */
- send: function messageHandlerSend(actionName, data, transfers) {
- var message = {
- sourceName: this.sourceName,
- targetName: this.targetName,
- action: actionName,
- data: data
- };
- this.postMessage(message, transfers);
- },
- /**
- * Sends a message to the comObj to invoke the action with the supplied data.
- * Expects that other side will callback with the response.
- * @param {String} actionName Action to call.
- * @param {JSON} data JSON data to send.
- * @param {Array} [transfers] Optional list of transfers/ArrayBuffers.
- * @returns {Promise} Promise to be resolved with response data.
- */
- sendWithPromise: function messageHandlerSendWithPromise(actionName, data, transfers) {
- var callbackId = this.callbackIndex++;
- var message = {
- sourceName: this.sourceName,
- targetName: this.targetName,
- action: actionName,
- data: data,
- callbackId: callbackId
- };
- var capability = createPromiseCapability();
- this.callbacksCapabilities[callbackId] = capability;
- try {
- this.postMessage(message, transfers);
- } catch (e) {
- capability.reject(e);
- }
- return capability.promise;
- },
- /**
- * Sends raw message to the comObj.
- * @private
- * @param message {Object} Raw message.
- * @param transfers List of transfers/ArrayBuffers, or undefined.
- */
- postMessage: function (message, transfers) {
- if (transfers && this.postMessageTransfers) {
- this.comObj.postMessage(message, transfers);
- } else {
- this.comObj.postMessage(message);
- }
- },
- destroy: function () {
- this.comObj.removeEventListener('message', this._onComObjOnMessage);
- }
- };
- function loadJpegStream(id, imageUrl, objs) {
- var img = new Image();
- img.onload = function loadJpegStream_onloadClosure() {
- objs.resolve(id, img);
- };
- img.onerror = function loadJpegStream_onerrorClosure() {
- objs.resolve(id, null);
- warn('Error during JPEG image loading');
- };
- img.src = imageUrl;
- }
- exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX;
- exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
- exports.OPS = OPS;
- exports.VERBOSITY_LEVELS = VERBOSITY_LEVELS;
- exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
- exports.AnnotationBorderStyleType = AnnotationBorderStyleType;
- exports.AnnotationFieldFlag = AnnotationFieldFlag;
- exports.AnnotationFlag = AnnotationFlag;
- exports.AnnotationType = AnnotationType;
- exports.FontType = FontType;
- exports.ImageKind = ImageKind;
- exports.InvalidPDFException = InvalidPDFException;
- exports.MessageHandler = MessageHandler;
- exports.MissingDataException = MissingDataException;
- exports.MissingPDFException = MissingPDFException;
- exports.NotImplementedException = NotImplementedException;
- exports.PageViewport = PageViewport;
- exports.PasswordException = PasswordException;
- exports.PasswordResponses = PasswordResponses;
- exports.StatTimer = StatTimer;
- exports.StreamType = StreamType;
- exports.TextRenderingMode = TextRenderingMode;
- exports.UnexpectedResponseException = UnexpectedResponseException;
- exports.UnknownErrorException = UnknownErrorException;
- exports.Util = Util;
- exports.XRefParseException = XRefParseException;
- exports.arrayByteLength = arrayByteLength;
- exports.arraysToBytes = arraysToBytes;
- exports.assert = assert;
- exports.bytesToString = bytesToString;
- exports.createBlob = createBlob;
- exports.createPromiseCapability = createPromiseCapability;
- exports.createObjectURL = createObjectURL;
- exports.deprecated = deprecated;
- exports.error = error;
- exports.getLookupTableFactory = getLookupTableFactory;
- exports.getVerbosityLevel = getVerbosityLevel;
- exports.globalScope = globalScope;
- exports.info = info;
- exports.isArray = isArray;
- exports.isArrayBuffer = isArrayBuffer;
- exports.isBool = isBool;
- exports.isEmptyObj = isEmptyObj;
- exports.isInt = isInt;
- exports.isNum = isNum;
- exports.isString = isString;
- exports.isSpace = isSpace;
- exports.isSameOrigin = isSameOrigin;
- exports.createValidAbsoluteUrl = createValidAbsoluteUrl;
- exports.isLittleEndian = isLittleEndian;
- exports.isEvalSupported = isEvalSupported;
- exports.loadJpegStream = loadJpegStream;
- exports.log2 = log2;
- exports.readInt8 = readInt8;
- exports.readUint16 = readUint16;
- exports.readUint32 = readUint32;
- exports.removeNullCharacters = removeNullCharacters;
- exports.setVerbosityLevel = setVerbosityLevel;
- exports.shadow = shadow;
- exports.string32 = string32;
- exports.stringToBytes = stringToBytes;
- exports.stringToPDFString = stringToPDFString;
- exports.stringToUTF8String = stringToUTF8String;
- exports.utf8StringToString = utf8StringToString;
- exports.warn = warn;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreCFFParser = {}, root.pdfjsSharedUtil, root.pdfjsCoreCharsets, root.pdfjsCoreEncodings);
- }(this, function (exports, sharedUtil, coreCharsets, coreEncodings) {
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var bytesToString = sharedUtil.bytesToString;
- var warn = sharedUtil.warn;
- var isArray = sharedUtil.isArray;
- var Util = sharedUtil.Util;
- var stringToBytes = sharedUtil.stringToBytes;
- var assert = sharedUtil.assert;
- var ISOAdobeCharset = coreCharsets.ISOAdobeCharset;
- var ExpertCharset = coreCharsets.ExpertCharset;
- var ExpertSubsetCharset = coreCharsets.ExpertSubsetCharset;
- var StandardEncoding = coreEncodings.StandardEncoding;
- var ExpertEncoding = coreEncodings.ExpertEncoding;
- // Maximum subroutine call depth of type 2 chartrings. Matches OTS.
- var MAX_SUBR_NESTING = 10;
- /**
- * The CFF class takes a Type1 file and wrap it into a
- * 'Compact Font Format' which itself embed Type2 charstrings.
- */
- var CFFStandardStrings = [
- '.notdef',
- 'space',
- 'exclam',
- 'quotedbl',
- 'numbersign',
- 'dollar',
- 'percent',
- 'ampersand',
- 'quoteright',
- 'parenleft',
- 'parenright',
- 'asterisk',
- 'plus',
- 'comma',
- 'hyphen',
- 'period',
- 'slash',
- 'zero',
- 'one',
- 'two',
- 'three',
- 'four',
- 'five',
- 'six',
- 'seven',
- 'eight',
- 'nine',
- 'colon',
- 'semicolon',
- 'less',
- 'equal',
- 'greater',
- 'question',
- 'at',
- 'A',
- 'B',
- 'C',
- 'D',
- 'E',
- 'F',
- 'G',
- 'H',
- 'I',
- 'J',
- 'K',
- 'L',
- 'M',
- 'N',
- 'O',
- 'P',
- 'Q',
- 'R',
- 'S',
- 'T',
- 'U',
- 'V',
- 'W',
- 'X',
- 'Y',
- 'Z',
- 'bracketleft',
- 'backslash',
- 'bracketright',
- 'asciicircum',
- 'underscore',
- 'quoteleft',
- 'a',
- 'b',
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i',
- 'j',
- 'k',
- 'l',
- 'm',
- 'n',
- 'o',
- 'p',
- 'q',
- 'r',
- 's',
- 't',
- 'u',
- 'v',
- 'w',
- 'x',
- 'y',
- 'z',
- 'braceleft',
- 'bar',
- 'braceright',
- 'asciitilde',
- 'exclamdown',
- 'cent',
- 'sterling',
- 'fraction',
- 'yen',
- 'florin',
- 'section',
- 'currency',
- 'quotesingle',
- 'quotedblleft',
- 'guillemotleft',
- 'guilsinglleft',
- 'guilsinglright',
- 'fi',
- 'fl',
- 'endash',
- 'dagger',
- 'daggerdbl',
- 'periodcentered',
- 'paragraph',
- 'bullet',
- 'quotesinglbase',
- 'quotedblbase',
- 'quotedblright',
- 'guillemotright',
- 'ellipsis',
- 'perthousand',
- 'questiondown',
- 'grave',
- 'acute',
- 'circumflex',
- 'tilde',
- 'macron',
- 'breve',
- 'dotaccent',
- 'dieresis',
- 'ring',
- 'cedilla',
- 'hungarumlaut',
- 'ogonek',
- 'caron',
- 'emdash',
- 'AE',
- 'ordfeminine',
- 'Lslash',
- 'Oslash',
- 'OE',
- 'ordmasculine',
- 'ae',
- 'dotlessi',
- 'lslash',
- 'oslash',
- 'oe',
- 'germandbls',
- 'onesuperior',
- 'logicalnot',
- 'mu',
- 'trademark',
- 'Eth',
- 'onehalf',
- 'plusminus',
- 'Thorn',
- 'onequarter',
- 'divide',
- 'brokenbar',
- 'degree',
- 'thorn',
- 'threequarters',
- 'twosuperior',
- 'registered',
- 'minus',
- 'eth',
- 'multiply',
- 'threesuperior',
- 'copyright',
- 'Aacute',
- 'Acircumflex',
- 'Adieresis',
- 'Agrave',
- 'Aring',
- 'Atilde',
- 'Ccedilla',
- 'Eacute',
- 'Ecircumflex',
- 'Edieresis',
- 'Egrave',
- 'Iacute',
- 'Icircumflex',
- 'Idieresis',
- 'Igrave',
- 'Ntilde',
- 'Oacute',
- 'Ocircumflex',
- 'Odieresis',
- 'Ograve',
- 'Otilde',
- 'Scaron',
- 'Uacute',
- 'Ucircumflex',
- 'Udieresis',
- 'Ugrave',
- 'Yacute',
- 'Ydieresis',
- 'Zcaron',
- 'aacute',
- 'acircumflex',
- 'adieresis',
- 'agrave',
- 'aring',
- 'atilde',
- 'ccedilla',
- 'eacute',
- 'ecircumflex',
- 'edieresis',
- 'egrave',
- 'iacute',
- 'icircumflex',
- 'idieresis',
- 'igrave',
- 'ntilde',
- 'oacute',
- 'ocircumflex',
- 'odieresis',
- 'ograve',
- 'otilde',
- 'scaron',
- 'uacute',
- 'ucircumflex',
- 'udieresis',
- 'ugrave',
- 'yacute',
- 'ydieresis',
- 'zcaron',
- 'exclamsmall',
- 'Hungarumlautsmall',
- 'dollaroldstyle',
- 'dollarsuperior',
- 'ampersandsmall',
- 'Acutesmall',
- 'parenleftsuperior',
- 'parenrightsuperior',
- 'twodotenleader',
- 'onedotenleader',
- 'zerooldstyle',
- 'oneoldstyle',
- 'twooldstyle',
- 'threeoldstyle',
- 'fouroldstyle',
- 'fiveoldstyle',
- 'sixoldstyle',
- 'sevenoldstyle',
- 'eightoldstyle',
- 'nineoldstyle',
- 'commasuperior',
- 'threequartersemdash',
- 'periodsuperior',
- 'questionsmall',
- 'asuperior',
- 'bsuperior',
- 'centsuperior',
- 'dsuperior',
- 'esuperior',
- 'isuperior',
- 'lsuperior',
- 'msuperior',
- 'nsuperior',
- 'osuperior',
- 'rsuperior',
- 'ssuperior',
- 'tsuperior',
- 'ff',
- 'ffi',
- 'ffl',
- 'parenleftinferior',
- 'parenrightinferior',
- 'Circumflexsmall',
- 'hyphensuperior',
- 'Gravesmall',
- 'Asmall',
- 'Bsmall',
- 'Csmall',
- 'Dsmall',
- 'Esmall',
- 'Fsmall',
- 'Gsmall',
- 'Hsmall',
- 'Ismall',
- 'Jsmall',
- 'Ksmall',
- 'Lsmall',
- 'Msmall',
- 'Nsmall',
- 'Osmall',
- 'Psmall',
- 'Qsmall',
- 'Rsmall',
- 'Ssmall',
- 'Tsmall',
- 'Usmall',
- 'Vsmall',
- 'Wsmall',
- 'Xsmall',
- 'Ysmall',
- 'Zsmall',
- 'colonmonetary',
- 'onefitted',
- 'rupiah',
- 'Tildesmall',
- 'exclamdownsmall',
- 'centoldstyle',
- 'Lslashsmall',
- 'Scaronsmall',
- 'Zcaronsmall',
- 'Dieresissmall',
- 'Brevesmall',
- 'Caronsmall',
- 'Dotaccentsmall',
- 'Macronsmall',
- 'figuredash',
- 'hypheninferior',
- 'Ogoneksmall',
- 'Ringsmall',
- 'Cedillasmall',
- 'questiondownsmall',
- 'oneeighth',
- 'threeeighths',
- 'fiveeighths',
- 'seveneighths',
- 'onethird',
- 'twothirds',
- 'zerosuperior',
- 'foursuperior',
- 'fivesuperior',
- 'sixsuperior',
- 'sevensuperior',
- 'eightsuperior',
- 'ninesuperior',
- 'zeroinferior',
- 'oneinferior',
- 'twoinferior',
- 'threeinferior',
- 'fourinferior',
- 'fiveinferior',
- 'sixinferior',
- 'seveninferior',
- 'eightinferior',
- 'nineinferior',
- 'centinferior',
- 'dollarinferior',
- 'periodinferior',
- 'commainferior',
- 'Agravesmall',
- 'Aacutesmall',
- 'Acircumflexsmall',
- 'Atildesmall',
- 'Adieresissmall',
- 'Aringsmall',
- 'AEsmall',
- 'Ccedillasmall',
- 'Egravesmall',
- 'Eacutesmall',
- 'Ecircumflexsmall',
- 'Edieresissmall',
- 'Igravesmall',
- 'Iacutesmall',
- 'Icircumflexsmall',
- 'Idieresissmall',
- 'Ethsmall',
- 'Ntildesmall',
- 'Ogravesmall',
- 'Oacutesmall',
- 'Ocircumflexsmall',
- 'Otildesmall',
- 'Odieresissmall',
- 'OEsmall',
- 'Oslashsmall',
- 'Ugravesmall',
- 'Uacutesmall',
- 'Ucircumflexsmall',
- 'Udieresissmall',
- 'Yacutesmall',
- 'Thornsmall',
- 'Ydieresissmall',
- '001.000',
- '001.001',
- '001.002',
- '001.003',
- 'Black',
- 'Bold',
- 'Book',
- 'Light',
- 'Medium',
- 'Regular',
- 'Roman',
- 'Semibold'
- ];
- var CFFParser = function CFFParserClosure() {
- var CharstringValidationData = [
- null,
- {
- id: 'hstem',
- min: 2,
- stackClearing: true,
- stem: true
- },
- null,
- {
- id: 'vstem',
- min: 2,
- stackClearing: true,
- stem: true
- },
- {
- id: 'vmoveto',
- min: 1,
- stackClearing: true
- },
- {
- id: 'rlineto',
- min: 2,
- resetStack: true
- },
- {
- id: 'hlineto',
- min: 1,
- resetStack: true
- },
- {
- id: 'vlineto',
- min: 1,
- resetStack: true
- },
- {
- id: 'rrcurveto',
- min: 6,
- resetStack: true
- },
- null,
- {
- id: 'callsubr',
- min: 1,
- undefStack: true
- },
- {
- id: 'return',
- min: 0,
- undefStack: true
- },
- null,
- // 12
- null,
- {
- id: 'endchar',
- min: 0,
- stackClearing: true
- },
- null,
- null,
- null,
- {
- id: 'hstemhm',
- min: 2,
- stackClearing: true,
- stem: true
- },
- {
- id: 'hintmask',
- min: 0,
- stackClearing: true
- },
- {
- id: 'cntrmask',
- min: 0,
- stackClearing: true
- },
- {
- id: 'rmoveto',
- min: 2,
- stackClearing: true
- },
- {
- id: 'hmoveto',
- min: 1,
- stackClearing: true
- },
- {
- id: 'vstemhm',
- min: 2,
- stackClearing: true,
- stem: true
- },
- {
- id: 'rcurveline',
- min: 8,
- resetStack: true
- },
- {
- id: 'rlinecurve',
- min: 8,
- resetStack: true
- },
- {
- id: 'vvcurveto',
- min: 4,
- resetStack: true
- },
- {
- id: 'hhcurveto',
- min: 4,
- resetStack: true
- },
- null,
- // shortint
- {
- id: 'callgsubr',
- min: 1,
- undefStack: true
- },
- {
- id: 'vhcurveto',
- min: 4,
- resetStack: true
- },
- {
- id: 'hvcurveto',
- min: 4,
- resetStack: true
- }
- ];
- var CharstringValidationData12 = [
- null,
- null,
- null,
- {
- id: 'and',
- min: 2,
- stackDelta: -1
- },
- {
- id: 'or',
- min: 2,
- stackDelta: -1
- },
- {
- id: 'not',
- min: 1,
- stackDelta: 0
- },
- null,
- null,
- null,
- {
- id: 'abs',
- min: 1,
- stackDelta: 0
- },
- {
- id: 'add',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] + stack[index - 1];
- }
- },
- {
- id: 'sub',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] - stack[index - 1];
- }
- },
- {
- id: 'div',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] / stack[index - 1];
- }
- },
- null,
- {
- id: 'neg',
- min: 1,
- stackDelta: 0,
- stackFn: function stack_div(stack, index) {
- stack[index - 1] = -stack[index - 1];
- }
- },
- {
- id: 'eq',
- min: 2,
- stackDelta: -1
- },
- null,
- null,
- {
- id: 'drop',
- min: 1,
- stackDelta: -1
- },
- null,
- {
- id: 'put',
- min: 2,
- stackDelta: -2
- },
- {
- id: 'get',
- min: 1,
- stackDelta: 0
- },
- {
- id: 'ifelse',
- min: 4,
- stackDelta: -3
- },
- {
- id: 'random',
- min: 0,
- stackDelta: 1
- },
- {
- id: 'mul',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] * stack[index - 1];
- }
- },
- null,
- {
- id: 'sqrt',
- min: 1,
- stackDelta: 0
- },
- {
- id: 'dup',
- min: 1,
- stackDelta: 1
- },
- {
- id: 'exch',
- min: 2,
- stackDelta: 0
- },
- {
- id: 'index',
- min: 2,
- stackDelta: 0
- },
- {
- id: 'roll',
- min: 3,
- stackDelta: -2
- },
- null,
- null,
- null,
- {
- id: 'hflex',
- min: 7,
- resetStack: true
- },
- {
- id: 'flex',
- min: 13,
- resetStack: true
- },
- {
- id: 'hflex1',
- min: 9,
- resetStack: true
- },
- {
- id: 'flex1',
- min: 11,
- resetStack: true
- }
- ];
- function CFFParser(file, properties, seacAnalysisEnabled) {
- this.bytes = file.getBytes();
- this.properties = properties;
- this.seacAnalysisEnabled = !!seacAnalysisEnabled;
- }
- CFFParser.prototype = {
- parse: function CFFParser_parse() {
- var properties = this.properties;
- var cff = new CFF();
- this.cff = cff;
- // The first five sections must be in order, all the others are reached
- // via offsets contained in one of the below.
- var header = this.parseHeader();
- var nameIndex = this.parseIndex(header.endPos);
- var topDictIndex = this.parseIndex(nameIndex.endPos);
- var stringIndex = this.parseIndex(topDictIndex.endPos);
- var globalSubrIndex = this.parseIndex(stringIndex.endPos);
- var topDictParsed = this.parseDict(topDictIndex.obj.get(0));
- var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings);
- cff.header = header.obj;
- cff.names = this.parseNameIndex(nameIndex.obj);
- cff.strings = this.parseStringIndex(stringIndex.obj);
- cff.topDict = topDict;
- cff.globalSubrIndex = globalSubrIndex.obj;
- this.parsePrivateDict(cff.topDict);
- cff.isCIDFont = topDict.hasName('ROS');
- var charStringOffset = topDict.getByName('CharStrings');
- var charStringIndex = this.parseIndex(charStringOffset).obj;
- var fontMatrix = topDict.getByName('FontMatrix');
- if (fontMatrix) {
- properties.fontMatrix = fontMatrix;
- }
- var fontBBox = topDict.getByName('FontBBox');
- if (fontBBox) {
- // adjusting ascent/descent
- properties.ascent = fontBBox[3];
- properties.descent = fontBBox[1];
- properties.ascentScaled = true;
- }
- var charset, encoding;
- if (cff.isCIDFont) {
- var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj;
- for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) {
- var dictRaw = fdArrayIndex.get(i);
- var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), cff.strings);
- this.parsePrivateDict(fontDict);
- cff.fdArray.push(fontDict);
- }
- // cid fonts don't have an encoding
- encoding = null;
- charset = this.parseCharsets(topDict.getByName('charset'), charStringIndex.count, cff.strings, true);
- cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'), charStringIndex.count);
- } else {
- charset = this.parseCharsets(topDict.getByName('charset'), charStringIndex.count, cff.strings, false);
- encoding = this.parseEncoding(topDict.getByName('Encoding'), properties, cff.strings, charset.charset);
- }
- cff.charset = charset;
- cff.encoding = encoding;
- var charStringsAndSeacs = this.parseCharStrings(charStringIndex, topDict.privateDict.subrsIndex, globalSubrIndex.obj, cff.fdSelect, cff.fdArray);
- cff.charStrings = charStringsAndSeacs.charStrings;
- cff.seacs = charStringsAndSeacs.seacs;
- cff.widths = charStringsAndSeacs.widths;
- return cff;
- },
- parseHeader: function CFFParser_parseHeader() {
- var bytes = this.bytes;
- var bytesLength = bytes.length;
- var offset = 0;
- // Prevent an infinite loop, by checking that the offset is within the
- // bounds of the bytes array. Necessary in empty, or invalid, font files.
- while (offset < bytesLength && bytes[offset] !== 1) {
- ++offset;
- }
- if (offset >= bytesLength) {
- error('Invalid CFF header');
- } else if (offset !== 0) {
- info('cff data is shifted');
- bytes = bytes.subarray(offset);
- this.bytes = bytes;
- }
- var major = bytes[0];
- var minor = bytes[1];
- var hdrSize = bytes[2];
- var offSize = bytes[3];
- var header = new CFFHeader(major, minor, hdrSize, offSize);
- return {
- obj: header,
- endPos: hdrSize
- };
- },
- parseDict: function CFFParser_parseDict(dict) {
- var pos = 0;
- function parseOperand() {
- var value = dict[pos++];
- if (value === 30) {
- return parseFloatOperand();
- } else if (value === 28) {
- value = dict[pos++];
- value = (value << 24 | dict[pos++] << 16) >> 16;
- return value;
- } else if (value === 29) {
- value = dict[pos++];
- value = value << 8 | dict[pos++];
- value = value << 8 | dict[pos++];
- value = value << 8 | dict[pos++];
- return value;
- } else if (value >= 32 && value <= 246) {
- return value - 139;
- } else if (value >= 247 && value <= 250) {
- return (value - 247) * 256 + dict[pos++] + 108;
- } else if (value >= 251 && value <= 254) {
- return -((value - 251) * 256) - dict[pos++] - 108;
- } else {
- warn('CFFParser_parseDict: "' + value + '" is a reserved command.');
- return NaN;
- }
- }
- function parseFloatOperand() {
- var str = '';
- var eof = 15;
- var lookup = [
- '0',
- '1',
- '2',
- '3',
- '4',
- '5',
- '6',
- '7',
- '8',
- '9',
- '.',
- 'E',
- 'E-',
- null,
- '-'
- ];
- var length = dict.length;
- while (pos < length) {
- var b = dict[pos++];
- var b1 = b >> 4;
- var b2 = b & 15;
- if (b1 === eof) {
- break;
- }
- str += lookup[b1];
- if (b2 === eof) {
- break;
- }
- str += lookup[b2];
- }
- return parseFloat(str);
- }
- var operands = [];
- var entries = [];
- pos = 0;
- var end = dict.length;
- while (pos < end) {
- var b = dict[pos];
- if (b <= 21) {
- if (b === 12) {
- b = b << 8 | dict[++pos];
- }
- entries.push([
- b,
- operands
- ]);
- operands = [];
- ++pos;
- } else {
- operands.push(parseOperand());
- }
- }
- return entries;
- },
- parseIndex: function CFFParser_parseIndex(pos) {
- var cffIndex = new CFFIndex();
- var bytes = this.bytes;
- var count = bytes[pos++] << 8 | bytes[pos++];
- var offsets = [];
- var end = pos;
- var i, ii;
- if (count !== 0) {
- var offsetSize = bytes[pos++];
- // add 1 for offset to determine size of last object
- var startPos = pos + (count + 1) * offsetSize - 1;
- for (i = 0, ii = count + 1; i < ii; ++i) {
- var offset = 0;
- for (var j = 0; j < offsetSize; ++j) {
- offset <<= 8;
- offset += bytes[pos++];
- }
- offsets.push(startPos + offset);
- }
- end = offsets[count];
- }
- for (i = 0, ii = offsets.length - 1; i < ii; ++i) {
- var offsetStart = offsets[i];
- var offsetEnd = offsets[i + 1];
- cffIndex.add(bytes.subarray(offsetStart, offsetEnd));
- }
- return {
- obj: cffIndex,
- endPos: end
- };
- },
- parseNameIndex: function CFFParser_parseNameIndex(index) {
- var names = [];
- for (var i = 0, ii = index.count; i < ii; ++i) {
- var name = index.get(i);
- // OTS doesn't allow names to be over 127 characters.
- var length = Math.min(name.length, 127);
- var data = [];
- // OTS also only permits certain characters in the name.
- for (var j = 0; j < length; ++j) {
- var c = name[j];
- if (j === 0 && c === 0) {
- data[j] = c;
- continue;
- }
- if (c < 33 || c > 126 || c === 91 || /* [ */
- c === 93 || /* ] */
- c === 40 || /* ( */
- c === 41 || /* ) */
- c === 123 || /* { */
- c === 125 || /* } */
- c === 60 || /* < */
- c === 62 || /* > */
- c === 47 || /* / */
- c === 37 || /* % */
- c === 35)
- /* # */
- {
- data[j] = 95;
- continue;
- }
- data[j] = c;
- }
- names.push(bytesToString(data));
- }
- return names;
- },
- parseStringIndex: function CFFParser_parseStringIndex(index) {
- var strings = new CFFStrings();
- for (var i = 0, ii = index.count; i < ii; ++i) {
- var data = index.get(i);
- strings.add(bytesToString(data));
- }
- return strings;
- },
- createDict: function CFFParser_createDict(Type, dict, strings) {
- var cffDict = new Type(strings);
- for (var i = 0, ii = dict.length; i < ii; ++i) {
- var pair = dict[i];
- var key = pair[0];
- var value = pair[1];
- cffDict.setByKey(key, value);
- }
- return cffDict;
- },
- parseCharString: function CFFParser_parseCharString(state, data, localSubrIndex, globalSubrIndex) {
- if (state.callDepth > MAX_SUBR_NESTING) {
- return false;
- }
- var stackSize = state.stackSize;
- var stack = state.stack;
- var length = data.length;
- for (var j = 0; j < length;) {
- var value = data[j++];
- var validationCommand = null;
- if (value === 12) {
- var q = data[j++];
- if (q === 0) {
- // The CFF specification state that the 'dotsection' command
- // (12, 0) is deprecated and treated as a no-op, but all Type2
- // charstrings processors should support them. Unfortunately
- // the font sanitizer don't. As a workaround the sequence (12, 0)
- // is replaced by a useless (0, hmoveto).
- data[j - 2] = 139;
- data[j - 1] = 22;
- stackSize = 0;
- } else {
- validationCommand = CharstringValidationData12[q];
- }
- } else if (value === 28) {
- // number (16 bit)
- stack[stackSize] = (data[j] << 24 | data[j + 1] << 16) >> 16;
- j += 2;
- stackSize++;
- } else if (value === 14) {
- if (stackSize >= 4) {
- stackSize -= 4;
- if (this.seacAnalysisEnabled) {
- state.seac = stack.slice(stackSize, stackSize + 4);
- return false;
- }
- }
- validationCommand = CharstringValidationData[value];
- } else if (value >= 32 && value <= 246) {
- // number
- stack[stackSize] = value - 139;
- stackSize++;
- } else if (value >= 247 && value <= 254) {
- // number (+1 bytes)
- stack[stackSize] = value < 251 ? (value - 247 << 8) + data[j] + 108 : -(value - 251 << 8) - data[j] - 108;
- j++;
- stackSize++;
- } else if (value === 255) {
- // number (32 bit)
- stack[stackSize] = (data[j] << 24 | data[j + 1] << 16 | data[j + 2] << 8 | data[j + 3]) / 65536;
- j += 4;
- stackSize++;
- } else if (value === 19 || value === 20) {
- state.hints += stackSize >> 1;
- // skipping right amount of hints flag data
- j += state.hints + 7 >> 3;
- stackSize %= 2;
- validationCommand = CharstringValidationData[value];
- } else if (value === 10 || value === 29) {
- var subrsIndex;
- if (value === 10) {
- subrsIndex = localSubrIndex;
- } else {
- subrsIndex = globalSubrIndex;
- }
- if (!subrsIndex) {
- validationCommand = CharstringValidationData[value];
- warn('Missing subrsIndex for ' + validationCommand.id);
- return false;
- }
- var bias = 32768;
- if (subrsIndex.count < 1240) {
- bias = 107;
- } else if (subrsIndex.count < 33900) {
- bias = 1131;
- }
- var subrNumber = stack[--stackSize] + bias;
- if (subrNumber < 0 || subrNumber >= subrsIndex.count) {
- validationCommand = CharstringValidationData[value];
- warn('Out of bounds subrIndex for ' + validationCommand.id);
- return false;
- }
- state.stackSize = stackSize;
- state.callDepth++;
- var valid = this.parseCharString(state, subrsIndex.get(subrNumber), localSubrIndex, globalSubrIndex);
- if (!valid) {
- return false;
- }
- state.callDepth--;
- stackSize = state.stackSize;
- continue;
- } else if (value === 11) {
- state.stackSize = stackSize;
- return true;
- } else {
- validationCommand = CharstringValidationData[value];
- }
- if (validationCommand) {
- if (validationCommand.stem) {
- state.hints += stackSize >> 1;
- }
- if ('min' in validationCommand) {
- if (!state.undefStack && stackSize < validationCommand.min) {
- warn('Not enough parameters for ' + validationCommand.id + '; actual: ' + stackSize + ', expected: ' + validationCommand.min);
- return false;
- }
- }
- if (state.firstStackClearing && validationCommand.stackClearing) {
- state.firstStackClearing = false;
- // the optional character width can be found before the first
- // stack-clearing command arguments
- stackSize -= validationCommand.min;
- if (stackSize >= 2 && validationCommand.stem) {
- // there are even amount of arguments for stem commands
- stackSize %= 2;
- } else if (stackSize > 1) {
- warn('Found too many parameters for stack-clearing command');
- }
- if (stackSize > 0 && stack[stackSize - 1] >= 0) {
- state.width = stack[stackSize - 1];
- }
- }
- if ('stackDelta' in validationCommand) {
- if ('stackFn' in validationCommand) {
- validationCommand.stackFn(stack, stackSize);
- }
- stackSize += validationCommand.stackDelta;
- } else if (validationCommand.stackClearing) {
- stackSize = 0;
- } else if (validationCommand.resetStack) {
- stackSize = 0;
- state.undefStack = false;
- } else if (validationCommand.undefStack) {
- stackSize = 0;
- state.undefStack = true;
- state.firstStackClearing = false;
- }
- }
- }
- state.stackSize = stackSize;
- return true;
- },
- parseCharStrings: function CFFParser_parseCharStrings(charStrings, localSubrIndex, globalSubrIndex, fdSelect, fdArray) {
- var seacs = [];
- var widths = [];
- var count = charStrings.count;
- for (var i = 0; i < count; i++) {
- var charstring = charStrings.get(i);
- var state = {
- callDepth: 0,
- stackSize: 0,
- stack: [],
- undefStack: true,
- hints: 0,
- firstStackClearing: true,
- seac: null,
- width: null
- };
- var valid = true;
- var localSubrToUse = null;
- if (fdSelect && fdArray.length) {
- var fdIndex = fdSelect.getFDIndex(i);
- if (fdIndex === -1) {
- warn('Glyph index is not in fd select.');
- valid = false;
- }
- if (fdIndex >= fdArray.length) {
- warn('Invalid fd index for glyph index.');
- valid = false;
- }
- if (valid) {
- localSubrToUse = fdArray[fdIndex].privateDict.subrsIndex;
- }
- } else if (localSubrIndex) {
- localSubrToUse = localSubrIndex;
- }
- if (valid) {
- valid = this.parseCharString(state, charstring, localSubrToUse, globalSubrIndex);
- }
- if (state.width !== null) {
- widths[i] = state.width;
- }
- if (state.seac !== null) {
- seacs[i] = state.seac;
- }
- if (!valid) {
- // resetting invalid charstring to single 'endchar'
- charStrings.set(i, new Uint8Array([14]));
- }
- }
- return {
- charStrings: charStrings,
- seacs: seacs,
- widths: widths
- };
- },
- emptyPrivateDictionary: function CFFParser_emptyPrivateDictionary(parentDict) {
- var privateDict = this.createDict(CFFPrivateDict, [], parentDict.strings);
- parentDict.setByKey(18, [
- 0,
- 0
- ]);
- parentDict.privateDict = privateDict;
- },
- parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) {
- // no private dict, do nothing
- if (!parentDict.hasName('Private')) {
- this.emptyPrivateDictionary(parentDict);
- return;
- }
- var privateOffset = parentDict.getByName('Private');
- // make sure the params are formatted correctly
- if (!isArray(privateOffset) || privateOffset.length !== 2) {
- parentDict.removeByName('Private');
- return;
- }
- var size = privateOffset[0];
- var offset = privateOffset[1];
- // remove empty dicts or ones that refer to invalid location
- if (size === 0 || offset >= this.bytes.length) {
- this.emptyPrivateDictionary(parentDict);
- return;
- }
- var privateDictEnd = offset + size;
- var dictData = this.bytes.subarray(offset, privateDictEnd);
- var dict = this.parseDict(dictData);
- var privateDict = this.createDict(CFFPrivateDict, dict, parentDict.strings);
- parentDict.privateDict = privateDict;
- // Parse the Subrs index also since it's relative to the private dict.
- if (!privateDict.getByName('Subrs')) {
- return;
- }
- var subrsOffset = privateDict.getByName('Subrs');
- var relativeOffset = offset + subrsOffset;
- // Validate the offset.
- if (subrsOffset === 0 || relativeOffset >= this.bytes.length) {
- this.emptyPrivateDictionary(parentDict);
- return;
- }
- var subrsIndex = this.parseIndex(relativeOffset);
- privateDict.subrsIndex = subrsIndex.obj;
- },
- parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) {
- if (pos === 0) {
- return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, ISOAdobeCharset);
- } else if (pos === 1) {
- return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, ExpertCharset);
- } else if (pos === 2) {
- return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, ExpertSubsetCharset);
- }
- var bytes = this.bytes;
- var start = pos;
- var format = bytes[pos++];
- var charset = ['.notdef'];
- var id, count, i;
- // subtract 1 for the .notdef glyph
- length -= 1;
- switch (format) {
- case 0:
- for (i = 0; i < length; i++) {
- id = bytes[pos++] << 8 | bytes[pos++];
- charset.push(cid ? id : strings.get(id));
- }
- break;
- case 1:
- while (charset.length <= length) {
- id = bytes[pos++] << 8 | bytes[pos++];
- count = bytes[pos++];
- for (i = 0; i <= count; i++) {
- charset.push(cid ? id++ : strings.get(id++));
- }
- }
- break;
- case 2:
- while (charset.length <= length) {
- id = bytes[pos++] << 8 | bytes[pos++];
- count = bytes[pos++] << 8 | bytes[pos++];
- for (i = 0; i <= count; i++) {
- charset.push(cid ? id++ : strings.get(id++));
- }
- }
- break;
- default:
- error('Unknown charset format');
- }
- // Raw won't be needed if we actually compile the charset.
- var end = pos;
- var raw = bytes.subarray(start, end);
- return new CFFCharset(false, format, charset, raw);
- },
- parseEncoding: function CFFParser_parseEncoding(pos, properties, strings, charset) {
- var encoding = Object.create(null);
- var bytes = this.bytes;
- var predefined = false;
- var hasSupplement = false;
- var format, i, ii;
- var raw = null;
- function readSupplement() {
- var supplementsCount = bytes[pos++];
- for (i = 0; i < supplementsCount; i++) {
- var code = bytes[pos++];
- var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
- encoding[code] = charset.indexOf(strings.get(sid));
- }
- }
- if (pos === 0 || pos === 1) {
- predefined = true;
- format = pos;
- var baseEncoding = pos ? ExpertEncoding : StandardEncoding;
- for (i = 0, ii = charset.length; i < ii; i++) {
- var index = baseEncoding.indexOf(charset[i]);
- if (index !== -1) {
- encoding[index] = i;
- }
- }
- } else {
- var dataStart = pos;
- format = bytes[pos++];
- switch (format & 0x7f) {
- case 0:
- var glyphsCount = bytes[pos++];
- for (i = 1; i <= glyphsCount; i++) {
- encoding[bytes[pos++]] = i;
- }
- break;
- case 1:
- var rangesCount = bytes[pos++];
- var gid = 1;
- for (i = 0; i < rangesCount; i++) {
- var start = bytes[pos++];
- var left = bytes[pos++];
- for (var j = start; j <= start + left; j++) {
- encoding[j] = gid++;
- }
- }
- break;
- default:
- error('Unknown encoding format: ' + format + ' in CFF');
- break;
- }
- var dataEnd = pos;
- if (format & 0x80) {
- // The font sanitizer does not support CFF encoding with a
- // supplement, since the encoding is not really used to map
- // between gid to glyph, let's overwrite what is declared in
- // the top dictionary to let the sanitizer think the font use
- // StandardEncoding, that's a lie but that's ok.
- bytes[dataStart] &= 0x7f;
- readSupplement();
- hasSupplement = true;
- }
- raw = bytes.subarray(dataStart, dataEnd);
- }
- format = format & 0x7f;
- return new CFFEncoding(predefined, format, encoding, raw);
- },
- parseFDSelect: function CFFParser_parseFDSelect(pos, length) {
- var start = pos;
- var bytes = this.bytes;
- var format = bytes[pos++];
- var fdSelect = [], rawBytes;
- var i, invalidFirstGID = false;
- switch (format) {
- case 0:
- for (i = 0; i < length; ++i) {
- var id = bytes[pos++];
- fdSelect.push(id);
- }
- rawBytes = bytes.subarray(start, pos);
- break;
- case 3:
- var rangesCount = bytes[pos++] << 8 | bytes[pos++];
- for (i = 0; i < rangesCount; ++i) {
- var first = bytes[pos++] << 8 | bytes[pos++];
- if (i === 0 && first !== 0) {
- warn('parseFDSelect: The first range must have a first GID of 0' + ' -- trying to recover.');
- invalidFirstGID = true;
- first = 0;
- }
- var fdIndex = bytes[pos++];
- var next = bytes[pos] << 8 | bytes[pos + 1];
- for (var j = first; j < next; ++j) {
- fdSelect.push(fdIndex);
- }
- }
- // Advance past the sentinel(next).
- pos += 2;
- rawBytes = bytes.subarray(start, pos);
- if (invalidFirstGID) {
- rawBytes[3] = rawBytes[4] = 0;
- }
- // Adjust the first range, first GID.
- break;
- default:
- error('parseFDSelect: Unknown format "' + format + '".');
- break;
- }
- assert(fdSelect.length === length, 'parseFDSelect: Invalid font data.');
- return new CFFFDSelect(fdSelect, rawBytes);
- }
- };
- return CFFParser;
- }();
- // Compact Font Format
- var CFF = function CFFClosure() {
- function CFF() {
- this.header = null;
- this.names = [];
- this.topDict = null;
- this.strings = new CFFStrings();
- this.globalSubrIndex = null;
- // The following could really be per font, but since we only have one font
- // store them here.
- this.encoding = null;
- this.charset = null;
- this.charStrings = null;
- this.fdArray = [];
- this.fdSelect = null;
- this.isCIDFont = false;
- }
- return CFF;
- }();
- var CFFHeader = function CFFHeaderClosure() {
- function CFFHeader(major, minor, hdrSize, offSize) {
- this.major = major;
- this.minor = minor;
- this.hdrSize = hdrSize;
- this.offSize = offSize;
- }
- return CFFHeader;
- }();
- var CFFStrings = function CFFStringsClosure() {
- function CFFStrings() {
- this.strings = [];
- }
- CFFStrings.prototype = {
- get: function CFFStrings_get(index) {
- if (index >= 0 && index <= 390) {
- return CFFStandardStrings[index];
- }
- if (index - 391 <= this.strings.length) {
- return this.strings[index - 391];
- }
- return CFFStandardStrings[0];
- },
- add: function CFFStrings_add(value) {
- this.strings.push(value);
- },
- get count() {
- return this.strings.length;
- }
- };
- return CFFStrings;
- }();
- var CFFIndex = function CFFIndexClosure() {
- function CFFIndex() {
- this.objects = [];
- this.length = 0;
- }
- CFFIndex.prototype = {
- add: function CFFIndex_add(data) {
- this.length += data.length;
- this.objects.push(data);
- },
- set: function CFFIndex_set(index, data) {
- this.length += data.length - this.objects[index].length;
- this.objects[index] = data;
- },
- get: function CFFIndex_get(index) {
- return this.objects[index];
- },
- get count() {
- return this.objects.length;
- }
- };
- return CFFIndex;
- }();
- var CFFDict = function CFFDictClosure() {
- function CFFDict(tables, strings) {
- this.keyToNameMap = tables.keyToNameMap;
- this.nameToKeyMap = tables.nameToKeyMap;
- this.defaults = tables.defaults;
- this.types = tables.types;
- this.opcodes = tables.opcodes;
- this.order = tables.order;
- this.strings = strings;
- this.values = Object.create(null);
- }
- CFFDict.prototype = {
- // value should always be an array
- setByKey: function CFFDict_setByKey(key, value) {
- if (!(key in this.keyToNameMap)) {
- return false;
- }
- var valueLength = value.length;
- // ignore empty values
- if (valueLength === 0) {
- return true;
- }
- // Ignore invalid values (fixes bug1068432.pdf and bug1308536.pdf).
- for (var i = 0; i < valueLength; i++) {
- if (isNaN(value[i])) {
- warn('Invalid CFFDict value: "' + value + '" for key "' + key + '".');
- return true;
- }
- }
- var type = this.types[key];
- // remove the array wrapping these types of values
- if (type === 'num' || type === 'sid' || type === 'offset') {
- value = value[0];
- }
- this.values[key] = value;
- return true;
- },
- setByName: function CFFDict_setByName(name, value) {
- if (!(name in this.nameToKeyMap)) {
- error('Invalid dictionary name "' + name + '"');
- }
- this.values[this.nameToKeyMap[name]] = value;
- },
- hasName: function CFFDict_hasName(name) {
- return this.nameToKeyMap[name] in this.values;
- },
- getByName: function CFFDict_getByName(name) {
- if (!(name in this.nameToKeyMap)) {
- error('Invalid dictionary name "' + name + '"');
- }
- var key = this.nameToKeyMap[name];
- if (!(key in this.values)) {
- return this.defaults[key];
- }
- return this.values[key];
- },
- removeByName: function CFFDict_removeByName(name) {
- delete this.values[this.nameToKeyMap[name]];
- }
- };
- CFFDict.createTables = function CFFDict_createTables(layout) {
- var tables = {
- keyToNameMap: {},
- nameToKeyMap: {},
- defaults: {},
- types: {},
- opcodes: {},
- order: []
- };
- for (var i = 0, ii = layout.length; i < ii; ++i) {
- var entry = layout[i];
- var key = isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0];
- tables.keyToNameMap[key] = entry[1];
- tables.nameToKeyMap[entry[1]] = key;
- tables.types[key] = entry[2];
- tables.defaults[key] = entry[3];
- tables.opcodes[key] = isArray(entry[0]) ? entry[0] : [entry[0]];
- tables.order.push(key);
- }
- return tables;
- };
- return CFFDict;
- }();
- var CFFTopDict = function CFFTopDictClosure() {
- var layout = [
- [
- [
- 12,
- 30
- ],
- 'ROS',
- [
- 'sid',
- 'sid',
- 'num'
- ],
- null
- ],
- [
- [
- 12,
- 20
- ],
- 'SyntheticBase',
- 'num',
- null
- ],
- [
- 0,
- 'version',
- 'sid',
- null
- ],
- [
- 1,
- 'Notice',
- 'sid',
- null
- ],
- [
- [
- 12,
- 0
- ],
- 'Copyright',
- 'sid',
- null
- ],
- [
- 2,
- 'FullName',
- 'sid',
- null
- ],
- [
- 3,
- 'FamilyName',
- 'sid',
- null
- ],
- [
- 4,
- 'Weight',
- 'sid',
- null
- ],
- [
- [
- 12,
- 1
- ],
- 'isFixedPitch',
- 'num',
- 0
- ],
- [
- [
- 12,
- 2
- ],
- 'ItalicAngle',
- 'num',
- 0
- ],
- [
- [
- 12,
- 3
- ],
- 'UnderlinePosition',
- 'num',
- -100
- ],
- [
- [
- 12,
- 4
- ],
- 'UnderlineThickness',
- 'num',
- 50
- ],
- [
- [
- 12,
- 5
- ],
- 'PaintType',
- 'num',
- 0
- ],
- [
- [
- 12,
- 6
- ],
- 'CharstringType',
- 'num',
- 2
- ],
- [
- [
- 12,
- 7
- ],
- 'FontMatrix',
- [
- 'num',
- 'num',
- 'num',
- 'num',
- 'num',
- 'num'
- ],
- [
- 0.001,
- 0,
- 0,
- 0.001,
- 0,
- 0
- ]
- ],
- [
- 13,
- 'UniqueID',
- 'num',
- null
- ],
- [
- 5,
- 'FontBBox',
- [
- 'num',
- 'num',
- 'num',
- 'num'
- ],
- [
- 0,
- 0,
- 0,
- 0
- ]
- ],
- [
- [
- 12,
- 8
- ],
- 'StrokeWidth',
- 'num',
- 0
- ],
- [
- 14,
- 'XUID',
- 'array',
- null
- ],
- [
- 15,
- 'charset',
- 'offset',
- 0
- ],
- [
- 16,
- 'Encoding',
- 'offset',
- 0
- ],
- [
- 17,
- 'CharStrings',
- 'offset',
- 0
- ],
- [
- 18,
- 'Private',
- [
- 'offset',
- 'offset'
- ],
- null
- ],
- [
- [
- 12,
- 21
- ],
- 'PostScript',
- 'sid',
- null
- ],
- [
- [
- 12,
- 22
- ],
- 'BaseFontName',
- 'sid',
- null
- ],
- [
- [
- 12,
- 23
- ],
- 'BaseFontBlend',
- 'delta',
- null
- ],
- [
- [
- 12,
- 31
- ],
- 'CIDFontVersion',
- 'num',
- 0
- ],
- [
- [
- 12,
- 32
- ],
- 'CIDFontRevision',
- 'num',
- 0
- ],
- [
- [
- 12,
- 33
- ],
- 'CIDFontType',
- 'num',
- 0
- ],
- [
- [
- 12,
- 34
- ],
- 'CIDCount',
- 'num',
- 8720
- ],
- [
- [
- 12,
- 35
- ],
- 'UIDBase',
- 'num',
- null
- ],
- // XXX: CID Fonts on DirectWrite 6.1 only seem to work if FDSelect comes
- // before FDArray.
- [
- [
- 12,
- 37
- ],
- 'FDSelect',
- 'offset',
- null
- ],
- [
- [
- 12,
- 36
- ],
- 'FDArray',
- 'offset',
- null
- ],
- [
- [
- 12,
- 38
- ],
- 'FontName',
- 'sid',
- null
- ]
- ];
- var tables = null;
- function CFFTopDict(strings) {
- if (tables === null) {
- tables = CFFDict.createTables(layout);
- }
- CFFDict.call(this, tables, strings);
- this.privateDict = null;
- }
- CFFTopDict.prototype = Object.create(CFFDict.prototype);
- return CFFTopDict;
- }();
- var CFFPrivateDict = function CFFPrivateDictClosure() {
- var layout = [
- [
- 6,
- 'BlueValues',
- 'delta',
- null
- ],
- [
- 7,
- 'OtherBlues',
- 'delta',
- null
- ],
- [
- 8,
- 'FamilyBlues',
- 'delta',
- null
- ],
- [
- 9,
- 'FamilyOtherBlues',
- 'delta',
- null
- ],
- [
- [
- 12,
- 9
- ],
- 'BlueScale',
- 'num',
- 0.039625
- ],
- [
- [
- 12,
- 10
- ],
- 'BlueShift',
- 'num',
- 7
- ],
- [
- [
- 12,
- 11
- ],
- 'BlueFuzz',
- 'num',
- 1
- ],
- [
- 10,
- 'StdHW',
- 'num',
- null
- ],
- [
- 11,
- 'StdVW',
- 'num',
- null
- ],
- [
- [
- 12,
- 12
- ],
- 'StemSnapH',
- 'delta',
- null
- ],
- [
- [
- 12,
- 13
- ],
- 'StemSnapV',
- 'delta',
- null
- ],
- [
- [
- 12,
- 14
- ],
- 'ForceBold',
- 'num',
- 0
- ],
- [
- [
- 12,
- 17
- ],
- 'LanguageGroup',
- 'num',
- 0
- ],
- [
- [
- 12,
- 18
- ],
- 'ExpansionFactor',
- 'num',
- 0.06
- ],
- [
- [
- 12,
- 19
- ],
- 'initialRandomSeed',
- 'num',
- 0
- ],
- [
- 20,
- 'defaultWidthX',
- 'num',
- 0
- ],
- [
- 21,
- 'nominalWidthX',
- 'num',
- 0
- ],
- [
- 19,
- 'Subrs',
- 'offset',
- null
- ]
- ];
- var tables = null;
- function CFFPrivateDict(strings) {
- if (tables === null) {
- tables = CFFDict.createTables(layout);
- }
- CFFDict.call(this, tables, strings);
- this.subrsIndex = null;
- }
- CFFPrivateDict.prototype = Object.create(CFFDict.prototype);
- return CFFPrivateDict;
- }();
- var CFFCharsetPredefinedTypes = {
- ISO_ADOBE: 0,
- EXPERT: 1,
- EXPERT_SUBSET: 2
- };
- var CFFCharset = function CFFCharsetClosure() {
- function CFFCharset(predefined, format, charset, raw) {
- this.predefined = predefined;
- this.format = format;
- this.charset = charset;
- this.raw = raw;
- }
- return CFFCharset;
- }();
- var CFFEncoding = function CFFEncodingClosure() {
- function CFFEncoding(predefined, format, encoding, raw) {
- this.predefined = predefined;
- this.format = format;
- this.encoding = encoding;
- this.raw = raw;
- }
- return CFFEncoding;
- }();
- var CFFFDSelect = function CFFFDSelectClosure() {
- function CFFFDSelect(fdSelect, raw) {
- this.fdSelect = fdSelect;
- this.raw = raw;
- }
- CFFFDSelect.prototype = {
- getFDIndex: function CFFFDSelect_get(glyphIndex) {
- if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) {
- return -1;
- }
- return this.fdSelect[glyphIndex];
- }
- };
- return CFFFDSelect;
- }();
- // Helper class to keep track of where an offset is within the data and helps
- // filling in that offset once it's known.
- var CFFOffsetTracker = function CFFOffsetTrackerClosure() {
- function CFFOffsetTracker() {
- this.offsets = Object.create(null);
- }
- CFFOffsetTracker.prototype = {
- isTracking: function CFFOffsetTracker_isTracking(key) {
- return key in this.offsets;
- },
- track: function CFFOffsetTracker_track(key, location) {
- if (key in this.offsets) {
- error('Already tracking location of ' + key);
- }
- this.offsets[key] = location;
- },
- offset: function CFFOffsetTracker_offset(value) {
- for (var key in this.offsets) {
- this.offsets[key] += value;
- }
- },
- setEntryLocation: function CFFOffsetTracker_setEntryLocation(key, values, output) {
- if (!(key in this.offsets)) {
- error('Not tracking location of ' + key);
- }
- var data = output.data;
- var dataOffset = this.offsets[key];
- var size = 5;
- for (var i = 0, ii = values.length; i < ii; ++i) {
- var offset0 = i * size + dataOffset;
- var offset1 = offset0 + 1;
- var offset2 = offset0 + 2;
- var offset3 = offset0 + 3;
- var offset4 = offset0 + 4;
- // It's easy to screw up offsets so perform this sanity check.
- if (data[offset0] !== 0x1d || data[offset1] !== 0 || data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) {
- error('writing to an offset that is not empty');
- }
- var value = values[i];
- data[offset0] = 0x1d;
- data[offset1] = value >> 24 & 0xFF;
- data[offset2] = value >> 16 & 0xFF;
- data[offset3] = value >> 8 & 0xFF;
- data[offset4] = value & 0xFF;
- }
- }
- };
- return CFFOffsetTracker;
- }();
- // Takes a CFF and converts it to the binary representation.
- var CFFCompiler = function CFFCompilerClosure() {
- function CFFCompiler(cff) {
- this.cff = cff;
- }
- CFFCompiler.prototype = {
- compile: function CFFCompiler_compile() {
- var cff = this.cff;
- var output = {
- data: [],
- length: 0,
- add: function CFFCompiler_add(data) {
- this.data = this.data.concat(data);
- this.length = this.data.length;
- }
- };
- // Compile the five entries that must be in order.
- var header = this.compileHeader(cff.header);
- output.add(header);
- var nameIndex = this.compileNameIndex(cff.names);
- output.add(nameIndex);
- if (cff.isCIDFont) {
- // The spec is unclear on how font matrices should relate to each other
- // when there is one in the main top dict and the sub top dicts.
- // Windows handles this differently than linux and osx so we have to
- // normalize to work on all.
- // Rules based off of some mailing list discussions:
- // - If main font has a matrix and subfont doesn't, use the main matrix.
- // - If no main font matrix and there is a subfont matrix, use the
- // subfont matrix.
- // - If both have matrices, concat together.
- // - If neither have matrices, use default.
- // To make this work on all platforms we move the top matrix into each
- // sub top dict and concat if necessary.
- if (cff.topDict.hasName('FontMatrix')) {
- var base = cff.topDict.getByName('FontMatrix');
- cff.topDict.removeByName('FontMatrix');
- for (var i = 0, ii = cff.fdArray.length; i < ii; i++) {
- var subDict = cff.fdArray[i];
- var matrix = base.slice(0);
- if (subDict.hasName('FontMatrix')) {
- matrix = Util.transform(matrix, subDict.getByName('FontMatrix'));
- }
- subDict.setByName('FontMatrix', matrix);
- }
- }
- }
- var compiled = this.compileTopDicts([cff.topDict], output.length, cff.isCIDFont);
- output.add(compiled.output);
- var topDictTracker = compiled.trackers[0];
- var stringIndex = this.compileStringIndex(cff.strings.strings);
- output.add(stringIndex);
- var globalSubrIndex = this.compileIndex(cff.globalSubrIndex);
- output.add(globalSubrIndex);
- // Now start on the other entries that have no specific order.
- if (cff.encoding && cff.topDict.hasName('Encoding')) {
- if (cff.encoding.predefined) {
- topDictTracker.setEntryLocation('Encoding', [cff.encoding.format], output);
- } else {
- var encoding = this.compileEncoding(cff.encoding);
- topDictTracker.setEntryLocation('Encoding', [output.length], output);
- output.add(encoding);
- }
- }
- if (cff.charset && cff.topDict.hasName('charset')) {
- if (cff.charset.predefined) {
- topDictTracker.setEntryLocation('charset', [cff.charset.format], output);
- } else {
- var charset = this.compileCharset(cff.charset);
- topDictTracker.setEntryLocation('charset', [output.length], output);
- output.add(charset);
- }
- }
- var charStrings = this.compileCharStrings(cff.charStrings);
- topDictTracker.setEntryLocation('CharStrings', [output.length], output);
- output.add(charStrings);
- if (cff.isCIDFont) {
- // For some reason FDSelect must be in front of FDArray on windows. OSX
- // and linux don't seem to care.
- topDictTracker.setEntryLocation('FDSelect', [output.length], output);
- var fdSelect = this.compileFDSelect(cff.fdSelect.raw);
- output.add(fdSelect);
- // It is unclear if the sub font dictionary can have CID related
- // dictionary keys, but the sanitizer doesn't like them so remove them.
- compiled = this.compileTopDicts(cff.fdArray, output.length, true);
- topDictTracker.setEntryLocation('FDArray', [output.length], output);
- output.add(compiled.output);
- var fontDictTrackers = compiled.trackers;
- this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output);
- }
- this.compilePrivateDicts([cff.topDict], [topDictTracker], output);
- // If the font data ends with INDEX whose object data is zero-length,
- // the sanitizer will bail out. Add a dummy byte to avoid that.
- output.add([0]);
- return output.data;
- },
- encodeNumber: function CFFCompiler_encodeNumber(value) {
- if (parseFloat(value) === parseInt(value, 10) && !isNaN(value)) {
- // isInt
- return this.encodeInteger(value);
- } else {
- return this.encodeFloat(value);
- }
- },
- encodeFloat: function CFFCompiler_encodeFloat(num) {
- var value = num.toString();
- // rounding inaccurate doubles
- var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
- if (m) {
- var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
- value = (Math.round(num * epsilon) / epsilon).toString();
- }
- var nibbles = '';
- var i, ii;
- for (i = 0, ii = value.length; i < ii; ++i) {
- var a = value[i];
- if (a === 'e') {
- nibbles += value[++i] === '-' ? 'c' : 'b';
- } else if (a === '.') {
- nibbles += 'a';
- } else if (a === '-') {
- nibbles += 'e';
- } else {
- nibbles += a;
- }
- }
- nibbles += nibbles.length & 1 ? 'f' : 'ff';
- var out = [30];
- for (i = 0, ii = nibbles.length; i < ii; i += 2) {
- out.push(parseInt(nibbles.substr(i, 2), 16));
- }
- return out;
- },
- encodeInteger: function CFFCompiler_encodeInteger(value) {
- var code;
- if (value >= -107 && value <= 107) {
- code = [value + 139];
- } else if (value >= 108 && value <= 1131) {
- value = value - 108;
- code = [
- (value >> 8) + 247,
- value & 0xFF
- ];
- } else if (value >= -1131 && value <= -108) {
- value = -value - 108;
- code = [
- (value >> 8) + 251,
- value & 0xFF
- ];
- } else if (value >= -32768 && value <= 32767) {
- code = [
- 0x1c,
- value >> 8 & 0xFF,
- value & 0xFF
- ];
- } else {
- code = [
- 0x1d,
- value >> 24 & 0xFF,
- value >> 16 & 0xFF,
- value >> 8 & 0xFF,
- value & 0xFF
- ];
- }
- return code;
- },
- compileHeader: function CFFCompiler_compileHeader(header) {
- return [
- header.major,
- header.minor,
- header.hdrSize,
- header.offSize
- ];
- },
- compileNameIndex: function CFFCompiler_compileNameIndex(names) {
- var nameIndex = new CFFIndex();
- for (var i = 0, ii = names.length; i < ii; ++i) {
- nameIndex.add(stringToBytes(names[i]));
- }
- return this.compileIndex(nameIndex);
- },
- compileTopDicts: function CFFCompiler_compileTopDicts(dicts, length, removeCidKeys) {
- var fontDictTrackers = [];
- var fdArrayIndex = new CFFIndex();
- for (var i = 0, ii = dicts.length; i < ii; ++i) {
- var fontDict = dicts[i];
- if (removeCidKeys) {
- fontDict.removeByName('CIDFontVersion');
- fontDict.removeByName('CIDFontRevision');
- fontDict.removeByName('CIDFontType');
- fontDict.removeByName('CIDCount');
- fontDict.removeByName('UIDBase');
- }
- var fontDictTracker = new CFFOffsetTracker();
- var fontDictData = this.compileDict(fontDict, fontDictTracker);
- fontDictTrackers.push(fontDictTracker);
- fdArrayIndex.add(fontDictData);
- fontDictTracker.offset(length);
- }
- fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers);
- return {
- trackers: fontDictTrackers,
- output: fdArrayIndex
- };
- },
- compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts, trackers, output) {
- for (var i = 0, ii = dicts.length; i < ii; ++i) {
- var fontDict = dicts[i];
- assert(fontDict.privateDict && fontDict.hasName('Private'), 'There must be an private dictionary.');
- var privateDict = fontDict.privateDict;
- var privateDictTracker = new CFFOffsetTracker();
- var privateDictData = this.compileDict(privateDict, privateDictTracker);
- var outputLength = output.length;
- privateDictTracker.offset(outputLength);
- if (!privateDictData.length) {
- // The private dictionary was empty, set the output length to zero to
- // ensure the offset length isn't out of bounds in the eyes of the
- // sanitizer.
- outputLength = 0;
- }
- trackers[i].setEntryLocation('Private', [
- privateDictData.length,
- outputLength
- ], output);
- output.add(privateDictData);
- if (privateDict.subrsIndex && privateDict.hasName('Subrs')) {
- var subrs = this.compileIndex(privateDict.subrsIndex);
- privateDictTracker.setEntryLocation('Subrs', [privateDictData.length], output);
- output.add(subrs);
- }
- }
- },
- compileDict: function CFFCompiler_compileDict(dict, offsetTracker) {
- var out = [];
- // The dictionary keys must be in a certain order.
- var order = dict.order;
- for (var i = 0; i < order.length; ++i) {
- var key = order[i];
- if (!(key in dict.values)) {
- continue;
- }
- var values = dict.values[key];
- var types = dict.types[key];
- if (!isArray(types)) {
- types = [types];
- }
- if (!isArray(values)) {
- values = [values];
- }
- // Remove any empty dict values.
- if (values.length === 0) {
- continue;
- }
- for (var j = 0, jj = types.length; j < jj; ++j) {
- var type = types[j];
- var value = values[j];
- switch (type) {
- case 'num':
- case 'sid':
- out = out.concat(this.encodeNumber(value));
- break;
- case 'offset':
- // For offsets we just insert a 32bit integer so we don't have to
- // deal with figuring out the length of the offset when it gets
- // replaced later on by the compiler.
- var name = dict.keyToNameMap[key];
- // Some offsets have the offset and the length, so just record the
- // position of the first one.
- if (!offsetTracker.isTracking(name)) {
- offsetTracker.track(name, out.length);
- }
- out = out.concat([
- 0x1d,
- 0,
- 0,
- 0,
- 0
- ]);
- break;
- case 'array':
- case 'delta':
- out = out.concat(this.encodeNumber(value));
- for (var k = 1, kk = values.length; k < kk; ++k) {
- out = out.concat(this.encodeNumber(values[k]));
- }
- break;
- default:
- error('Unknown data type of ' + type);
- break;
- }
- }
- out = out.concat(dict.opcodes[key]);
- }
- return out;
- },
- compileStringIndex: function CFFCompiler_compileStringIndex(strings) {
- var stringIndex = new CFFIndex();
- for (var i = 0, ii = strings.length; i < ii; ++i) {
- stringIndex.add(stringToBytes(strings[i]));
- }
- return this.compileIndex(stringIndex);
- },
- compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() {
- var globalSubrIndex = this.cff.globalSubrIndex;
- this.out.writeByteArray(this.compileIndex(globalSubrIndex));
- },
- compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) {
- return this.compileIndex(charStrings);
- },
- compileCharset: function CFFCompiler_compileCharset(charset) {
- return this.compileTypedArray(charset.raw);
- },
- compileEncoding: function CFFCompiler_compileEncoding(encoding) {
- return this.compileTypedArray(encoding.raw);
- },
- compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) {
- return this.compileTypedArray(fdSelect);
- },
- compileTypedArray: function CFFCompiler_compileTypedArray(data) {
- var out = [];
- for (var i = 0, ii = data.length; i < ii; ++i) {
- out[i] = data[i];
- }
- return out;
- },
- compileIndex: function CFFCompiler_compileIndex(index, trackers) {
- trackers = trackers || [];
- var objects = index.objects;
- // First 2 bytes contains the number of objects contained into this index
- var count = objects.length;
- // If there is no object, just create an index. This technically
- // should just be [0, 0] but OTS has an issue with that.
- if (count === 0) {
- return [
- 0,
- 0,
- 0
- ];
- }
- var data = [
- count >> 8 & 0xFF,
- count & 0xff
- ];
- var lastOffset = 1, i;
- for (i = 0; i < count; ++i) {
- lastOffset += objects[i].length;
- }
- var offsetSize;
- if (lastOffset < 0x100) {
- offsetSize = 1;
- } else if (lastOffset < 0x10000) {
- offsetSize = 2;
- } else if (lastOffset < 0x1000000) {
- offsetSize = 3;
- } else {
- offsetSize = 4;
- }
- // Next byte contains the offset size use to reference object in the file
- data.push(offsetSize);
- // Add another offset after this one because we need a new offset
- var relativeOffset = 1;
- for (i = 0; i < count + 1; i++) {
- if (offsetSize === 1) {
- data.push(relativeOffset & 0xFF);
- } else if (offsetSize === 2) {
- data.push(relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
- } else if (offsetSize === 3) {
- data.push(relativeOffset >> 16 & 0xFF, relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
- } else {
- data.push(relativeOffset >>> 24 & 0xFF, relativeOffset >> 16 & 0xFF, relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
- }
- if (objects[i]) {
- relativeOffset += objects[i].length;
- }
- }
- for (i = 0; i < count; i++) {
- // Notify the tracker where the object will be offset in the data.
- if (trackers[i]) {
- trackers[i].offset(data.length);
- }
- for (var j = 0, jj = objects[i].length; j < jj; j++) {
- data.push(objects[i][j]);
- }
- }
- return data;
- }
- };
- return CFFCompiler;
- }();
- exports.CFFStandardStrings = CFFStandardStrings;
- exports.CFFParser = CFFParser;
- exports.CFF = CFF;
- exports.CFFHeader = CFFHeader;
- exports.CFFStrings = CFFStrings;
- exports.CFFIndex = CFFIndex;
- exports.CFFCharset = CFFCharset;
- exports.CFFTopDict = CFFTopDict;
- exports.CFFPrivateDict = CFFPrivateDict;
- exports.CFFCompiler = CFFCompiler;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreChunkedStream = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- var MissingDataException = sharedUtil.MissingDataException;
- var arrayByteLength = sharedUtil.arrayByteLength;
- var arraysToBytes = sharedUtil.arraysToBytes;
- var assert = sharedUtil.assert;
- var createPromiseCapability = sharedUtil.createPromiseCapability;
- var isInt = sharedUtil.isInt;
- var isEmptyObj = sharedUtil.isEmptyObj;
- var ChunkedStream = function ChunkedStreamClosure() {
- function ChunkedStream(length, chunkSize, manager) {
- this.bytes = new Uint8Array(length);
- this.start = 0;
- this.pos = 0;
- this.end = length;
- this.chunkSize = chunkSize;
- this.loadedChunks = [];
- this.numChunksLoaded = 0;
- this.numChunks = Math.ceil(length / chunkSize);
- this.manager = manager;
- this.progressiveDataLength = 0;
- this.lastSuccessfulEnsureByteChunk = -1;
- }
- // a single-entry cache
- // required methods for a stream. if a particular stream does not
- // implement these, an error should be thrown
- ChunkedStream.prototype = {
- getMissingChunks: function ChunkedStream_getMissingChunks() {
- var chunks = [];
- for (var chunk = 0, n = this.numChunks; chunk < n; ++chunk) {
- if (!this.loadedChunks[chunk]) {
- chunks.push(chunk);
- }
- }
- return chunks;
- },
- getBaseStreams: function ChunkedStream_getBaseStreams() {
- return [this];
- },
- allChunksLoaded: function ChunkedStream_allChunksLoaded() {
- return this.numChunksLoaded === this.numChunks;
- },
- onReceiveData: function ChunkedStream_onReceiveData(begin, chunk) {
- var end = begin + chunk.byteLength;
- assert(begin % this.chunkSize === 0, 'Bad begin offset: ' + begin);
- // Using this.length is inaccurate here since this.start can be moved
- // See ChunkedStream.moveStart()
- var length = this.bytes.length;
- assert(end % this.chunkSize === 0 || end === length, 'Bad end offset: ' + end);
- this.bytes.set(new Uint8Array(chunk), begin);
- var chunkSize = this.chunkSize;
- var beginChunk = Math.floor(begin / chunkSize);
- var endChunk = Math.floor((end - 1) / chunkSize) + 1;
- var curChunk;
- for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
- if (!this.loadedChunks[curChunk]) {
- this.loadedChunks[curChunk] = true;
- ++this.numChunksLoaded;
- }
- }
- },
- onReceiveProgressiveData: function ChunkedStream_onReceiveProgressiveData(data) {
- var position = this.progressiveDataLength;
- var beginChunk = Math.floor(position / this.chunkSize);
- this.bytes.set(new Uint8Array(data), position);
- position += data.byteLength;
- this.progressiveDataLength = position;
- var endChunk = position >= this.end ? this.numChunks : Math.floor(position / this.chunkSize);
- var curChunk;
- for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
- if (!this.loadedChunks[curChunk]) {
- this.loadedChunks[curChunk] = true;
- ++this.numChunksLoaded;
- }
- }
- },
- ensureByte: function ChunkedStream_ensureByte(pos) {
- var chunk = Math.floor(pos / this.chunkSize);
- if (chunk === this.lastSuccessfulEnsureByteChunk) {
- return;
- }
- if (!this.loadedChunks[chunk]) {
- throw new MissingDataException(pos, pos + 1);
- }
- this.lastSuccessfulEnsureByteChunk = chunk;
- },
- ensureRange: function ChunkedStream_ensureRange(begin, end) {
- if (begin >= end) {
- return;
- }
- if (end <= this.progressiveDataLength) {
- return;
- }
- var chunkSize = this.chunkSize;
- var beginChunk = Math.floor(begin / chunkSize);
- var endChunk = Math.floor((end - 1) / chunkSize) + 1;
- for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
- if (!this.loadedChunks[chunk]) {
- throw new MissingDataException(begin, end);
- }
- }
- },
- nextEmptyChunk: function ChunkedStream_nextEmptyChunk(beginChunk) {
- var chunk, numChunks = this.numChunks;
- for (var i = 0; i < numChunks; ++i) {
- chunk = (beginChunk + i) % numChunks;
- // Wrap around to beginning
- if (!this.loadedChunks[chunk]) {
- return chunk;
- }
- }
- return null;
- },
- hasChunk: function ChunkedStream_hasChunk(chunk) {
- return !!this.loadedChunks[chunk];
- },
- get length() {
- return this.end - this.start;
- },
- get isEmpty() {
- return this.length === 0;
- },
- getByte: function ChunkedStream_getByte() {
- var pos = this.pos;
- if (pos >= this.end) {
- return -1;
- }
- this.ensureByte(pos);
- return this.bytes[this.pos++];
- },
- getUint16: function ChunkedStream_getUint16() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- if (b0 === -1 || b1 === -1) {
- return -1;
- }
- return (b0 << 8) + b1;
- },
- getInt32: function ChunkedStream_getInt32() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- var b2 = this.getByte();
- var b3 = this.getByte();
- return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
- },
- // returns subarray of original buffer
- // should only be read
- getBytes: function ChunkedStream_getBytes(length) {
- var bytes = this.bytes;
- var pos = this.pos;
- var strEnd = this.end;
- if (!length) {
- this.ensureRange(pos, strEnd);
- return bytes.subarray(pos, strEnd);
- }
- var end = pos + length;
- if (end > strEnd) {
- end = strEnd;
- }
- this.ensureRange(pos, end);
- this.pos = end;
- return bytes.subarray(pos, end);
- },
- peekByte: function ChunkedStream_peekByte() {
- var peekedByte = this.getByte();
- this.pos--;
- return peekedByte;
- },
- peekBytes: function ChunkedStream_peekBytes(length) {
- var bytes = this.getBytes(length);
- this.pos -= bytes.length;
- return bytes;
- },
- getByteRange: function ChunkedStream_getBytes(begin, end) {
- this.ensureRange(begin, end);
- return this.bytes.subarray(begin, end);
- },
- skip: function ChunkedStream_skip(n) {
- if (!n) {
- n = 1;
- }
- this.pos += n;
- },
- reset: function ChunkedStream_reset() {
- this.pos = this.start;
- },
- moveStart: function ChunkedStream_moveStart() {
- this.start = this.pos;
- },
- makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) {
- this.ensureRange(start, start + length);
- function ChunkedStreamSubstream() {
- }
- ChunkedStreamSubstream.prototype = Object.create(this);
- ChunkedStreamSubstream.prototype.getMissingChunks = function () {
- var chunkSize = this.chunkSize;
- var beginChunk = Math.floor(this.start / chunkSize);
- var endChunk = Math.floor((this.end - 1) / chunkSize) + 1;
- var missingChunks = [];
- for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
- if (!this.loadedChunks[chunk]) {
- missingChunks.push(chunk);
- }
- }
- return missingChunks;
- };
- var subStream = new ChunkedStreamSubstream();
- subStream.pos = subStream.start = start;
- subStream.end = start + length || this.end;
- subStream.dict = dict;
- return subStream;
- },
- isStream: true
- };
- return ChunkedStream;
- }();
- var ChunkedStreamManager = function ChunkedStreamManagerClosure() {
- function ChunkedStreamManager(pdfNetworkStream, args) {
- var chunkSize = args.rangeChunkSize;
- var length = args.length;
- this.stream = new ChunkedStream(length, chunkSize, this);
- this.length = length;
- this.chunkSize = chunkSize;
- this.pdfNetworkStream = pdfNetworkStream;
- this.url = args.url;
- this.disableAutoFetch = args.disableAutoFetch;
- this.msgHandler = args.msgHandler;
- this.currRequestId = 0;
- this.chunksNeededByRequest = Object.create(null);
- this.requestsByChunk = Object.create(null);
- this.promisesByRequest = Object.create(null);
- this.progressiveDataLength = 0;
- this.aborted = false;
- this._loadedStreamCapability = createPromiseCapability();
- }
- ChunkedStreamManager.prototype = {
- onLoadedStream: function ChunkedStreamManager_getLoadedStream() {
- return this._loadedStreamCapability.promise;
- },
- sendRequest: function ChunkedStreamManager_sendRequest(begin, end) {
- var rangeReader = this.pdfNetworkStream.getRangeReader(begin, end);
- if (!rangeReader.isStreamingSupported) {
- rangeReader.onProgress = this.onProgress.bind(this);
- }
- var chunks = [], loaded = 0;
- var manager = this;
- var promise = new Promise(function (resolve, reject) {
- var readChunk = function (chunk) {
- try {
- if (!chunk.done) {
- var data = chunk.value;
- chunks.push(data);
- loaded += arrayByteLength(data);
- if (rangeReader.isStreamingSupported) {
- manager.onProgress({ loaded: loaded });
- }
- rangeReader.read().then(readChunk, reject);
- return;
- }
- var chunkData = arraysToBytes(chunks);
- chunks = null;
- resolve(chunkData);
- } catch (e) {
- reject(e);
- }
- };
- rangeReader.read().then(readChunk, reject);
- });
- promise.then(function (data) {
- if (this.aborted) {
- return;
- }
- // ignoring any data after abort
- this.onReceiveData({
- chunk: data,
- begin: begin
- });
- }.bind(this));
- },
- // TODO check errors
- // Get all the chunks that are not yet loaded and groups them into
- // contiguous ranges to load in as few requests as possible
- requestAllChunks: function ChunkedStreamManager_requestAllChunks() {
- var missingChunks = this.stream.getMissingChunks();
- this._requestChunks(missingChunks);
- return this._loadedStreamCapability.promise;
- },
- _requestChunks: function ChunkedStreamManager_requestChunks(chunks) {
- var requestId = this.currRequestId++;
- var i, ii;
- var chunksNeeded = Object.create(null);
- this.chunksNeededByRequest[requestId] = chunksNeeded;
- for (i = 0, ii = chunks.length; i < ii; i++) {
- if (!this.stream.hasChunk(chunks[i])) {
- chunksNeeded[chunks[i]] = true;
- }
- }
- if (isEmptyObj(chunksNeeded)) {
- return Promise.resolve();
- }
- var capability = createPromiseCapability();
- this.promisesByRequest[requestId] = capability;
- var chunksToRequest = [];
- for (var chunk in chunksNeeded) {
- chunk = chunk | 0;
- if (!(chunk in this.requestsByChunk)) {
- this.requestsByChunk[chunk] = [];
- chunksToRequest.push(chunk);
- }
- this.requestsByChunk[chunk].push(requestId);
- }
- if (!chunksToRequest.length) {
- return capability.promise;
- }
- var groupedChunksToRequest = this.groupChunks(chunksToRequest);
- for (i = 0; i < groupedChunksToRequest.length; ++i) {
- var groupedChunk = groupedChunksToRequest[i];
- var begin = groupedChunk.beginChunk * this.chunkSize;
- var end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length);
- this.sendRequest(begin, end);
- }
- return capability.promise;
- },
- getStream: function ChunkedStreamManager_getStream() {
- return this.stream;
- },
- // Loads any chunks in the requested range that are not yet loaded
- requestRange: function ChunkedStreamManager_requestRange(begin, end) {
- end = Math.min(end, this.length);
- var beginChunk = this.getBeginChunk(begin);
- var endChunk = this.getEndChunk(end);
- var chunks = [];
- for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
- chunks.push(chunk);
- }
- return this._requestChunks(chunks);
- },
- requestRanges: function ChunkedStreamManager_requestRanges(ranges) {
- ranges = ranges || [];
- var chunksToRequest = [];
- for (var i = 0; i < ranges.length; i++) {
- var beginChunk = this.getBeginChunk(ranges[i].begin);
- var endChunk = this.getEndChunk(ranges[i].end);
- for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
- if (chunksToRequest.indexOf(chunk) < 0) {
- chunksToRequest.push(chunk);
- }
- }
- }
- chunksToRequest.sort(function (a, b) {
- return a - b;
- });
- return this._requestChunks(chunksToRequest);
- },
- // Groups a sorted array of chunks into as few contiguous larger
- // chunks as possible
- groupChunks: function ChunkedStreamManager_groupChunks(chunks) {
- var groupedChunks = [];
- var beginChunk = -1;
- var prevChunk = -1;
- for (var i = 0; i < chunks.length; ++i) {
- var chunk = chunks[i];
- if (beginChunk < 0) {
- beginChunk = chunk;
- }
- if (prevChunk >= 0 && prevChunk + 1 !== chunk) {
- groupedChunks.push({
- beginChunk: beginChunk,
- endChunk: prevChunk + 1
- });
- beginChunk = chunk;
- }
- if (i + 1 === chunks.length) {
- groupedChunks.push({
- beginChunk: beginChunk,
- endChunk: chunk + 1
- });
- }
- prevChunk = chunk;
- }
- return groupedChunks;
- },
- onProgress: function ChunkedStreamManager_onProgress(args) {
- var bytesLoaded = this.stream.numChunksLoaded * this.chunkSize + args.loaded;
- this.msgHandler.send('DocProgress', {
- loaded: bytesLoaded,
- total: this.length
- });
- },
- onReceiveData: function ChunkedStreamManager_onReceiveData(args) {
- var chunk = args.chunk;
- var isProgressive = args.begin === undefined;
- var begin = isProgressive ? this.progressiveDataLength : args.begin;
- var end = begin + chunk.byteLength;
- var beginChunk = Math.floor(begin / this.chunkSize);
- var endChunk = end < this.length ? Math.floor(end / this.chunkSize) : Math.ceil(end / this.chunkSize);
- if (isProgressive) {
- this.stream.onReceiveProgressiveData(chunk);
- this.progressiveDataLength = end;
- } else {
- this.stream.onReceiveData(begin, chunk);
- }
- if (this.stream.allChunksLoaded()) {
- this._loadedStreamCapability.resolve(this.stream);
- }
- var loadedRequests = [];
- var i, requestId;
- for (chunk = beginChunk; chunk < endChunk; ++chunk) {
- // The server might return more chunks than requested
- var requestIds = this.requestsByChunk[chunk] || [];
- delete this.requestsByChunk[chunk];
- for (i = 0; i < requestIds.length; ++i) {
- requestId = requestIds[i];
- var chunksNeeded = this.chunksNeededByRequest[requestId];
- if (chunk in chunksNeeded) {
- delete chunksNeeded[chunk];
- }
- if (!isEmptyObj(chunksNeeded)) {
- continue;
- }
- loadedRequests.push(requestId);
- }
- }
- // If there are no pending requests, automatically fetch the next
- // unfetched chunk of the PDF
- if (!this.disableAutoFetch && isEmptyObj(this.requestsByChunk)) {
- var nextEmptyChunk;
- if (this.stream.numChunksLoaded === 1) {
- // This is a special optimization so that after fetching the first
- // chunk, rather than fetching the second chunk, we fetch the last
- // chunk.
- var lastChunk = this.stream.numChunks - 1;
- if (!this.stream.hasChunk(lastChunk)) {
- nextEmptyChunk = lastChunk;
- }
- } else {
- nextEmptyChunk = this.stream.nextEmptyChunk(endChunk);
- }
- if (isInt(nextEmptyChunk)) {
- this._requestChunks([nextEmptyChunk]);
- }
- }
- for (i = 0; i < loadedRequests.length; ++i) {
- requestId = loadedRequests[i];
- var capability = this.promisesByRequest[requestId];
- delete this.promisesByRequest[requestId];
- capability.resolve();
- }
- this.msgHandler.send('DocProgress', {
- loaded: this.stream.numChunksLoaded * this.chunkSize,
- total: this.length
- });
- },
- onError: function ChunkedStreamManager_onError(err) {
- this._loadedStreamCapability.reject(err);
- },
- getBeginChunk: function ChunkedStreamManager_getBeginChunk(begin) {
- var chunk = Math.floor(begin / this.chunkSize);
- return chunk;
- },
- getEndChunk: function ChunkedStreamManager_getEndChunk(end) {
- var chunk = Math.floor((end - 1) / this.chunkSize) + 1;
- return chunk;
- },
- abort: function ChunkedStreamManager_abort() {
- this.aborted = true;
- if (this.pdfNetworkStream) {
- this.pdfNetworkStream.cancelAllRequests('abort');
- }
- for (var requestId in this.promisesByRequest) {
- var capability = this.promisesByRequest[requestId];
- capability.reject(new Error('Request was aborted'));
- }
- }
- };
- return ChunkedStreamManager;
- }();
- exports.ChunkedStream = ChunkedStream;
- exports.ChunkedStreamManager = ChunkedStreamManager;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreGlyphList = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- var getLookupTableFactory = sharedUtil.getLookupTableFactory;
- var getGlyphsUnicode = getLookupTableFactory(function (t) {
- t['A'] = 0x0041;
- t['AE'] = 0x00C6;
- t['AEacute'] = 0x01FC;
- t['AEmacron'] = 0x01E2;
- t['AEsmall'] = 0xF7E6;
- t['Aacute'] = 0x00C1;
- t['Aacutesmall'] = 0xF7E1;
- t['Abreve'] = 0x0102;
- t['Abreveacute'] = 0x1EAE;
- t['Abrevecyrillic'] = 0x04D0;
- t['Abrevedotbelow'] = 0x1EB6;
- t['Abrevegrave'] = 0x1EB0;
- t['Abrevehookabove'] = 0x1EB2;
- t['Abrevetilde'] = 0x1EB4;
- t['Acaron'] = 0x01CD;
- t['Acircle'] = 0x24B6;
- t['Acircumflex'] = 0x00C2;
- t['Acircumflexacute'] = 0x1EA4;
- t['Acircumflexdotbelow'] = 0x1EAC;
- t['Acircumflexgrave'] = 0x1EA6;
- t['Acircumflexhookabove'] = 0x1EA8;
- t['Acircumflexsmall'] = 0xF7E2;
- t['Acircumflextilde'] = 0x1EAA;
- t['Acute'] = 0xF6C9;
- t['Acutesmall'] = 0xF7B4;
- t['Acyrillic'] = 0x0410;
- t['Adblgrave'] = 0x0200;
- t['Adieresis'] = 0x00C4;
- t['Adieresiscyrillic'] = 0x04D2;
- t['Adieresismacron'] = 0x01DE;
- t['Adieresissmall'] = 0xF7E4;
- t['Adotbelow'] = 0x1EA0;
- t['Adotmacron'] = 0x01E0;
- t['Agrave'] = 0x00C0;
- t['Agravesmall'] = 0xF7E0;
- t['Ahookabove'] = 0x1EA2;
- t['Aiecyrillic'] = 0x04D4;
- t['Ainvertedbreve'] = 0x0202;
- t['Alpha'] = 0x0391;
- t['Alphatonos'] = 0x0386;
- t['Amacron'] = 0x0100;
- t['Amonospace'] = 0xFF21;
- t['Aogonek'] = 0x0104;
- t['Aring'] = 0x00C5;
- t['Aringacute'] = 0x01FA;
- t['Aringbelow'] = 0x1E00;
- t['Aringsmall'] = 0xF7E5;
- t['Asmall'] = 0xF761;
- t['Atilde'] = 0x00C3;
- t['Atildesmall'] = 0xF7E3;
- t['Aybarmenian'] = 0x0531;
- t['B'] = 0x0042;
- t['Bcircle'] = 0x24B7;
- t['Bdotaccent'] = 0x1E02;
- t['Bdotbelow'] = 0x1E04;
- t['Becyrillic'] = 0x0411;
- t['Benarmenian'] = 0x0532;
- t['Beta'] = 0x0392;
- t['Bhook'] = 0x0181;
- t['Blinebelow'] = 0x1E06;
- t['Bmonospace'] = 0xFF22;
- t['Brevesmall'] = 0xF6F4;
- t['Bsmall'] = 0xF762;
- t['Btopbar'] = 0x0182;
- t['C'] = 0x0043;
- t['Caarmenian'] = 0x053E;
- t['Cacute'] = 0x0106;
- t['Caron'] = 0xF6CA;
- t['Caronsmall'] = 0xF6F5;
- t['Ccaron'] = 0x010C;
- t['Ccedilla'] = 0x00C7;
- t['Ccedillaacute'] = 0x1E08;
- t['Ccedillasmall'] = 0xF7E7;
- t['Ccircle'] = 0x24B8;
- t['Ccircumflex'] = 0x0108;
- t['Cdot'] = 0x010A;
- t['Cdotaccent'] = 0x010A;
- t['Cedillasmall'] = 0xF7B8;
- t['Chaarmenian'] = 0x0549;
- t['Cheabkhasiancyrillic'] = 0x04BC;
- t['Checyrillic'] = 0x0427;
- t['Chedescenderabkhasiancyrillic'] = 0x04BE;
- t['Chedescendercyrillic'] = 0x04B6;
- t['Chedieresiscyrillic'] = 0x04F4;
- t['Cheharmenian'] = 0x0543;
- t['Chekhakassiancyrillic'] = 0x04CB;
- t['Cheverticalstrokecyrillic'] = 0x04B8;
- t['Chi'] = 0x03A7;
- t['Chook'] = 0x0187;
- t['Circumflexsmall'] = 0xF6F6;
- t['Cmonospace'] = 0xFF23;
- t['Coarmenian'] = 0x0551;
- t['Csmall'] = 0xF763;
- t['D'] = 0x0044;
- t['DZ'] = 0x01F1;
- t['DZcaron'] = 0x01C4;
- t['Daarmenian'] = 0x0534;
- t['Dafrican'] = 0x0189;
- t['Dcaron'] = 0x010E;
- t['Dcedilla'] = 0x1E10;
- t['Dcircle'] = 0x24B9;
- t['Dcircumflexbelow'] = 0x1E12;
- t['Dcroat'] = 0x0110;
- t['Ddotaccent'] = 0x1E0A;
- t['Ddotbelow'] = 0x1E0C;
- t['Decyrillic'] = 0x0414;
- t['Deicoptic'] = 0x03EE;
- t['Delta'] = 0x2206;
- t['Deltagreek'] = 0x0394;
- t['Dhook'] = 0x018A;
- t['Dieresis'] = 0xF6CB;
- t['DieresisAcute'] = 0xF6CC;
- t['DieresisGrave'] = 0xF6CD;
- t['Dieresissmall'] = 0xF7A8;
- t['Digammagreek'] = 0x03DC;
- t['Djecyrillic'] = 0x0402;
- t['Dlinebelow'] = 0x1E0E;
- t['Dmonospace'] = 0xFF24;
- t['Dotaccentsmall'] = 0xF6F7;
- t['Dslash'] = 0x0110;
- t['Dsmall'] = 0xF764;
- t['Dtopbar'] = 0x018B;
- t['Dz'] = 0x01F2;
- t['Dzcaron'] = 0x01C5;
- t['Dzeabkhasiancyrillic'] = 0x04E0;
- t['Dzecyrillic'] = 0x0405;
- t['Dzhecyrillic'] = 0x040F;
- t['E'] = 0x0045;
- t['Eacute'] = 0x00C9;
- t['Eacutesmall'] = 0xF7E9;
- t['Ebreve'] = 0x0114;
- t['Ecaron'] = 0x011A;
- t['Ecedillabreve'] = 0x1E1C;
- t['Echarmenian'] = 0x0535;
- t['Ecircle'] = 0x24BA;
- t['Ecircumflex'] = 0x00CA;
- t['Ecircumflexacute'] = 0x1EBE;
- t['Ecircumflexbelow'] = 0x1E18;
- t['Ecircumflexdotbelow'] = 0x1EC6;
- t['Ecircumflexgrave'] = 0x1EC0;
- t['Ecircumflexhookabove'] = 0x1EC2;
- t['Ecircumflexsmall'] = 0xF7EA;
- t['Ecircumflextilde'] = 0x1EC4;
- t['Ecyrillic'] = 0x0404;
- t['Edblgrave'] = 0x0204;
- t['Edieresis'] = 0x00CB;
- t['Edieresissmall'] = 0xF7EB;
- t['Edot'] = 0x0116;
- t['Edotaccent'] = 0x0116;
- t['Edotbelow'] = 0x1EB8;
- t['Efcyrillic'] = 0x0424;
- t['Egrave'] = 0x00C8;
- t['Egravesmall'] = 0xF7E8;
- t['Eharmenian'] = 0x0537;
- t['Ehookabove'] = 0x1EBA;
- t['Eightroman'] = 0x2167;
- t['Einvertedbreve'] = 0x0206;
- t['Eiotifiedcyrillic'] = 0x0464;
- t['Elcyrillic'] = 0x041B;
- t['Elevenroman'] = 0x216A;
- t['Emacron'] = 0x0112;
- t['Emacronacute'] = 0x1E16;
- t['Emacrongrave'] = 0x1E14;
- t['Emcyrillic'] = 0x041C;
- t['Emonospace'] = 0xFF25;
- t['Encyrillic'] = 0x041D;
- t['Endescendercyrillic'] = 0x04A2;
- t['Eng'] = 0x014A;
- t['Enghecyrillic'] = 0x04A4;
- t['Enhookcyrillic'] = 0x04C7;
- t['Eogonek'] = 0x0118;
- t['Eopen'] = 0x0190;
- t['Epsilon'] = 0x0395;
- t['Epsilontonos'] = 0x0388;
- t['Ercyrillic'] = 0x0420;
- t['Ereversed'] = 0x018E;
- t['Ereversedcyrillic'] = 0x042D;
- t['Escyrillic'] = 0x0421;
- t['Esdescendercyrillic'] = 0x04AA;
- t['Esh'] = 0x01A9;
- t['Esmall'] = 0xF765;
- t['Eta'] = 0x0397;
- t['Etarmenian'] = 0x0538;
- t['Etatonos'] = 0x0389;
- t['Eth'] = 0x00D0;
- t['Ethsmall'] = 0xF7F0;
- t['Etilde'] = 0x1EBC;
- t['Etildebelow'] = 0x1E1A;
- t['Euro'] = 0x20AC;
- t['Ezh'] = 0x01B7;
- t['Ezhcaron'] = 0x01EE;
- t['Ezhreversed'] = 0x01B8;
- t['F'] = 0x0046;
- t['Fcircle'] = 0x24BB;
- t['Fdotaccent'] = 0x1E1E;
- t['Feharmenian'] = 0x0556;
- t['Feicoptic'] = 0x03E4;
- t['Fhook'] = 0x0191;
- t['Fitacyrillic'] = 0x0472;
- t['Fiveroman'] = 0x2164;
- t['Fmonospace'] = 0xFF26;
- t['Fourroman'] = 0x2163;
- t['Fsmall'] = 0xF766;
- t['G'] = 0x0047;
- t['GBsquare'] = 0x3387;
- t['Gacute'] = 0x01F4;
- t['Gamma'] = 0x0393;
- t['Gammaafrican'] = 0x0194;
- t['Gangiacoptic'] = 0x03EA;
- t['Gbreve'] = 0x011E;
- t['Gcaron'] = 0x01E6;
- t['Gcedilla'] = 0x0122;
- t['Gcircle'] = 0x24BC;
- t['Gcircumflex'] = 0x011C;
- t['Gcommaaccent'] = 0x0122;
- t['Gdot'] = 0x0120;
- t['Gdotaccent'] = 0x0120;
- t['Gecyrillic'] = 0x0413;
- t['Ghadarmenian'] = 0x0542;
- t['Ghemiddlehookcyrillic'] = 0x0494;
- t['Ghestrokecyrillic'] = 0x0492;
- t['Gheupturncyrillic'] = 0x0490;
- t['Ghook'] = 0x0193;
- t['Gimarmenian'] = 0x0533;
- t['Gjecyrillic'] = 0x0403;
- t['Gmacron'] = 0x1E20;
- t['Gmonospace'] = 0xFF27;
- t['Grave'] = 0xF6CE;
- t['Gravesmall'] = 0xF760;
- t['Gsmall'] = 0xF767;
- t['Gsmallhook'] = 0x029B;
- t['Gstroke'] = 0x01E4;
- t['H'] = 0x0048;
- t['H18533'] = 0x25CF;
- t['H18543'] = 0x25AA;
- t['H18551'] = 0x25AB;
- t['H22073'] = 0x25A1;
- t['HPsquare'] = 0x33CB;
- t['Haabkhasiancyrillic'] = 0x04A8;
- t['Hadescendercyrillic'] = 0x04B2;
- t['Hardsigncyrillic'] = 0x042A;
- t['Hbar'] = 0x0126;
- t['Hbrevebelow'] = 0x1E2A;
- t['Hcedilla'] = 0x1E28;
- t['Hcircle'] = 0x24BD;
- t['Hcircumflex'] = 0x0124;
- t['Hdieresis'] = 0x1E26;
- t['Hdotaccent'] = 0x1E22;
- t['Hdotbelow'] = 0x1E24;
- t['Hmonospace'] = 0xFF28;
- t['Hoarmenian'] = 0x0540;
- t['Horicoptic'] = 0x03E8;
- t['Hsmall'] = 0xF768;
- t['Hungarumlaut'] = 0xF6CF;
- t['Hungarumlautsmall'] = 0xF6F8;
- t['Hzsquare'] = 0x3390;
- t['I'] = 0x0049;
- t['IAcyrillic'] = 0x042F;
- t['IJ'] = 0x0132;
- t['IUcyrillic'] = 0x042E;
- t['Iacute'] = 0x00CD;
- t['Iacutesmall'] = 0xF7ED;
- t['Ibreve'] = 0x012C;
- t['Icaron'] = 0x01CF;
- t['Icircle'] = 0x24BE;
- t['Icircumflex'] = 0x00CE;
- t['Icircumflexsmall'] = 0xF7EE;
- t['Icyrillic'] = 0x0406;
- t['Idblgrave'] = 0x0208;
- t['Idieresis'] = 0x00CF;
- t['Idieresisacute'] = 0x1E2E;
- t['Idieresiscyrillic'] = 0x04E4;
- t['Idieresissmall'] = 0xF7EF;
- t['Idot'] = 0x0130;
- t['Idotaccent'] = 0x0130;
- t['Idotbelow'] = 0x1ECA;
- t['Iebrevecyrillic'] = 0x04D6;
- t['Iecyrillic'] = 0x0415;
- t['Ifraktur'] = 0x2111;
- t['Igrave'] = 0x00CC;
- t['Igravesmall'] = 0xF7EC;
- t['Ihookabove'] = 0x1EC8;
- t['Iicyrillic'] = 0x0418;
- t['Iinvertedbreve'] = 0x020A;
- t['Iishortcyrillic'] = 0x0419;
- t['Imacron'] = 0x012A;
- t['Imacroncyrillic'] = 0x04E2;
- t['Imonospace'] = 0xFF29;
- t['Iniarmenian'] = 0x053B;
- t['Iocyrillic'] = 0x0401;
- t['Iogonek'] = 0x012E;
- t['Iota'] = 0x0399;
- t['Iotaafrican'] = 0x0196;
- t['Iotadieresis'] = 0x03AA;
- t['Iotatonos'] = 0x038A;
- t['Ismall'] = 0xF769;
- t['Istroke'] = 0x0197;
- t['Itilde'] = 0x0128;
- t['Itildebelow'] = 0x1E2C;
- t['Izhitsacyrillic'] = 0x0474;
- t['Izhitsadblgravecyrillic'] = 0x0476;
- t['J'] = 0x004A;
- t['Jaarmenian'] = 0x0541;
- t['Jcircle'] = 0x24BF;
- t['Jcircumflex'] = 0x0134;
- t['Jecyrillic'] = 0x0408;
- t['Jheharmenian'] = 0x054B;
- t['Jmonospace'] = 0xFF2A;
- t['Jsmall'] = 0xF76A;
- t['K'] = 0x004B;
- t['KBsquare'] = 0x3385;
- t['KKsquare'] = 0x33CD;
- t['Kabashkircyrillic'] = 0x04A0;
- t['Kacute'] = 0x1E30;
- t['Kacyrillic'] = 0x041A;
- t['Kadescendercyrillic'] = 0x049A;
- t['Kahookcyrillic'] = 0x04C3;
- t['Kappa'] = 0x039A;
- t['Kastrokecyrillic'] = 0x049E;
- t['Kaverticalstrokecyrillic'] = 0x049C;
- t['Kcaron'] = 0x01E8;
- t['Kcedilla'] = 0x0136;
- t['Kcircle'] = 0x24C0;
- t['Kcommaaccent'] = 0x0136;
- t['Kdotbelow'] = 0x1E32;
- t['Keharmenian'] = 0x0554;
- t['Kenarmenian'] = 0x053F;
- t['Khacyrillic'] = 0x0425;
- t['Kheicoptic'] = 0x03E6;
- t['Khook'] = 0x0198;
- t['Kjecyrillic'] = 0x040C;
- t['Klinebelow'] = 0x1E34;
- t['Kmonospace'] = 0xFF2B;
- t['Koppacyrillic'] = 0x0480;
- t['Koppagreek'] = 0x03DE;
- t['Ksicyrillic'] = 0x046E;
- t['Ksmall'] = 0xF76B;
- t['L'] = 0x004C;
- t['LJ'] = 0x01C7;
- t['LL'] = 0xF6BF;
- t['Lacute'] = 0x0139;
- t['Lambda'] = 0x039B;
- t['Lcaron'] = 0x013D;
- t['Lcedilla'] = 0x013B;
- t['Lcircle'] = 0x24C1;
- t['Lcircumflexbelow'] = 0x1E3C;
- t['Lcommaaccent'] = 0x013B;
- t['Ldot'] = 0x013F;
- t['Ldotaccent'] = 0x013F;
- t['Ldotbelow'] = 0x1E36;
- t['Ldotbelowmacron'] = 0x1E38;
- t['Liwnarmenian'] = 0x053C;
- t['Lj'] = 0x01C8;
- t['Ljecyrillic'] = 0x0409;
- t['Llinebelow'] = 0x1E3A;
- t['Lmonospace'] = 0xFF2C;
- t['Lslash'] = 0x0141;
- t['Lslashsmall'] = 0xF6F9;
- t['Lsmall'] = 0xF76C;
- t['M'] = 0x004D;
- t['MBsquare'] = 0x3386;
- t['Macron'] = 0xF6D0;
- t['Macronsmall'] = 0xF7AF;
- t['Macute'] = 0x1E3E;
- t['Mcircle'] = 0x24C2;
- t['Mdotaccent'] = 0x1E40;
- t['Mdotbelow'] = 0x1E42;
- t['Menarmenian'] = 0x0544;
- t['Mmonospace'] = 0xFF2D;
- t['Msmall'] = 0xF76D;
- t['Mturned'] = 0x019C;
- t['Mu'] = 0x039C;
- t['N'] = 0x004E;
- t['NJ'] = 0x01CA;
- t['Nacute'] = 0x0143;
- t['Ncaron'] = 0x0147;
- t['Ncedilla'] = 0x0145;
- t['Ncircle'] = 0x24C3;
- t['Ncircumflexbelow'] = 0x1E4A;
- t['Ncommaaccent'] = 0x0145;
- t['Ndotaccent'] = 0x1E44;
- t['Ndotbelow'] = 0x1E46;
- t['Nhookleft'] = 0x019D;
- t['Nineroman'] = 0x2168;
- t['Nj'] = 0x01CB;
- t['Njecyrillic'] = 0x040A;
- t['Nlinebelow'] = 0x1E48;
- t['Nmonospace'] = 0xFF2E;
- t['Nowarmenian'] = 0x0546;
- t['Nsmall'] = 0xF76E;
- t['Ntilde'] = 0x00D1;
- t['Ntildesmall'] = 0xF7F1;
- t['Nu'] = 0x039D;
- t['O'] = 0x004F;
- t['OE'] = 0x0152;
- t['OEsmall'] = 0xF6FA;
- t['Oacute'] = 0x00D3;
- t['Oacutesmall'] = 0xF7F3;
- t['Obarredcyrillic'] = 0x04E8;
- t['Obarreddieresiscyrillic'] = 0x04EA;
- t['Obreve'] = 0x014E;
- t['Ocaron'] = 0x01D1;
- t['Ocenteredtilde'] = 0x019F;
- t['Ocircle'] = 0x24C4;
- t['Ocircumflex'] = 0x00D4;
- t['Ocircumflexacute'] = 0x1ED0;
- t['Ocircumflexdotbelow'] = 0x1ED8;
- t['Ocircumflexgrave'] = 0x1ED2;
- t['Ocircumflexhookabove'] = 0x1ED4;
- t['Ocircumflexsmall'] = 0xF7F4;
- t['Ocircumflextilde'] = 0x1ED6;
- t['Ocyrillic'] = 0x041E;
- t['Odblacute'] = 0x0150;
- t['Odblgrave'] = 0x020C;
- t['Odieresis'] = 0x00D6;
- t['Odieresiscyrillic'] = 0x04E6;
- t['Odieresissmall'] = 0xF7F6;
- t['Odotbelow'] = 0x1ECC;
- t['Ogoneksmall'] = 0xF6FB;
- t['Ograve'] = 0x00D2;
- t['Ogravesmall'] = 0xF7F2;
- t['Oharmenian'] = 0x0555;
- t['Ohm'] = 0x2126;
- t['Ohookabove'] = 0x1ECE;
- t['Ohorn'] = 0x01A0;
- t['Ohornacute'] = 0x1EDA;
- t['Ohorndotbelow'] = 0x1EE2;
- t['Ohorngrave'] = 0x1EDC;
- t['Ohornhookabove'] = 0x1EDE;
- t['Ohorntilde'] = 0x1EE0;
- t['Ohungarumlaut'] = 0x0150;
- t['Oi'] = 0x01A2;
- t['Oinvertedbreve'] = 0x020E;
- t['Omacron'] = 0x014C;
- t['Omacronacute'] = 0x1E52;
- t['Omacrongrave'] = 0x1E50;
- t['Omega'] = 0x2126;
- t['Omegacyrillic'] = 0x0460;
- t['Omegagreek'] = 0x03A9;
- t['Omegaroundcyrillic'] = 0x047A;
- t['Omegatitlocyrillic'] = 0x047C;
- t['Omegatonos'] = 0x038F;
- t['Omicron'] = 0x039F;
- t['Omicrontonos'] = 0x038C;
- t['Omonospace'] = 0xFF2F;
- t['Oneroman'] = 0x2160;
- t['Oogonek'] = 0x01EA;
- t['Oogonekmacron'] = 0x01EC;
- t['Oopen'] = 0x0186;
- t['Oslash'] = 0x00D8;
- t['Oslashacute'] = 0x01FE;
- t['Oslashsmall'] = 0xF7F8;
- t['Osmall'] = 0xF76F;
- t['Ostrokeacute'] = 0x01FE;
- t['Otcyrillic'] = 0x047E;
- t['Otilde'] = 0x00D5;
- t['Otildeacute'] = 0x1E4C;
- t['Otildedieresis'] = 0x1E4E;
- t['Otildesmall'] = 0xF7F5;
- t['P'] = 0x0050;
- t['Pacute'] = 0x1E54;
- t['Pcircle'] = 0x24C5;
- t['Pdotaccent'] = 0x1E56;
- t['Pecyrillic'] = 0x041F;
- t['Peharmenian'] = 0x054A;
- t['Pemiddlehookcyrillic'] = 0x04A6;
- t['Phi'] = 0x03A6;
- t['Phook'] = 0x01A4;
- t['Pi'] = 0x03A0;
- t['Piwrarmenian'] = 0x0553;
- t['Pmonospace'] = 0xFF30;
- t['Psi'] = 0x03A8;
- t['Psicyrillic'] = 0x0470;
- t['Psmall'] = 0xF770;
- t['Q'] = 0x0051;
- t['Qcircle'] = 0x24C6;
- t['Qmonospace'] = 0xFF31;
- t['Qsmall'] = 0xF771;
- t['R'] = 0x0052;
- t['Raarmenian'] = 0x054C;
- t['Racute'] = 0x0154;
- t['Rcaron'] = 0x0158;
- t['Rcedilla'] = 0x0156;
- t['Rcircle'] = 0x24C7;
- t['Rcommaaccent'] = 0x0156;
- t['Rdblgrave'] = 0x0210;
- t['Rdotaccent'] = 0x1E58;
- t['Rdotbelow'] = 0x1E5A;
- t['Rdotbelowmacron'] = 0x1E5C;
- t['Reharmenian'] = 0x0550;
- t['Rfraktur'] = 0x211C;
- t['Rho'] = 0x03A1;
- t['Ringsmall'] = 0xF6FC;
- t['Rinvertedbreve'] = 0x0212;
- t['Rlinebelow'] = 0x1E5E;
- t['Rmonospace'] = 0xFF32;
- t['Rsmall'] = 0xF772;
- t['Rsmallinverted'] = 0x0281;
- t['Rsmallinvertedsuperior'] = 0x02B6;
- t['S'] = 0x0053;
- t['SF010000'] = 0x250C;
- t['SF020000'] = 0x2514;
- t['SF030000'] = 0x2510;
- t['SF040000'] = 0x2518;
- t['SF050000'] = 0x253C;
- t['SF060000'] = 0x252C;
- t['SF070000'] = 0x2534;
- t['SF080000'] = 0x251C;
- t['SF090000'] = 0x2524;
- t['SF100000'] = 0x2500;
- t['SF110000'] = 0x2502;
- t['SF190000'] = 0x2561;
- t['SF200000'] = 0x2562;
- t['SF210000'] = 0x2556;
- t['SF220000'] = 0x2555;
- t['SF230000'] = 0x2563;
- t['SF240000'] = 0x2551;
- t['SF250000'] = 0x2557;
- t['SF260000'] = 0x255D;
- t['SF270000'] = 0x255C;
- t['SF280000'] = 0x255B;
- t['SF360000'] = 0x255E;
- t['SF370000'] = 0x255F;
- t['SF380000'] = 0x255A;
- t['SF390000'] = 0x2554;
- t['SF400000'] = 0x2569;
- t['SF410000'] = 0x2566;
- t['SF420000'] = 0x2560;
- t['SF430000'] = 0x2550;
- t['SF440000'] = 0x256C;
- t['SF450000'] = 0x2567;
- t['SF460000'] = 0x2568;
- t['SF470000'] = 0x2564;
- t['SF480000'] = 0x2565;
- t['SF490000'] = 0x2559;
- t['SF500000'] = 0x2558;
- t['SF510000'] = 0x2552;
- t['SF520000'] = 0x2553;
- t['SF530000'] = 0x256B;
- t['SF540000'] = 0x256A;
- t['Sacute'] = 0x015A;
- t['Sacutedotaccent'] = 0x1E64;
- t['Sampigreek'] = 0x03E0;
- t['Scaron'] = 0x0160;
- t['Scarondotaccent'] = 0x1E66;
- t['Scaronsmall'] = 0xF6FD;
- t['Scedilla'] = 0x015E;
- t['Schwa'] = 0x018F;
- t['Schwacyrillic'] = 0x04D8;
- t['Schwadieresiscyrillic'] = 0x04DA;
- t['Scircle'] = 0x24C8;
- t['Scircumflex'] = 0x015C;
- t['Scommaaccent'] = 0x0218;
- t['Sdotaccent'] = 0x1E60;
- t['Sdotbelow'] = 0x1E62;
- t['Sdotbelowdotaccent'] = 0x1E68;
- t['Seharmenian'] = 0x054D;
- t['Sevenroman'] = 0x2166;
- t['Shaarmenian'] = 0x0547;
- t['Shacyrillic'] = 0x0428;
- t['Shchacyrillic'] = 0x0429;
- t['Sheicoptic'] = 0x03E2;
- t['Shhacyrillic'] = 0x04BA;
- t['Shimacoptic'] = 0x03EC;
- t['Sigma'] = 0x03A3;
- t['Sixroman'] = 0x2165;
- t['Smonospace'] = 0xFF33;
- t['Softsigncyrillic'] = 0x042C;
- t['Ssmall'] = 0xF773;
- t['Stigmagreek'] = 0x03DA;
- t['T'] = 0x0054;
- t['Tau'] = 0x03A4;
- t['Tbar'] = 0x0166;
- t['Tcaron'] = 0x0164;
- t['Tcedilla'] = 0x0162;
- t['Tcircle'] = 0x24C9;
- t['Tcircumflexbelow'] = 0x1E70;
- t['Tcommaaccent'] = 0x0162;
- t['Tdotaccent'] = 0x1E6A;
- t['Tdotbelow'] = 0x1E6C;
- t['Tecyrillic'] = 0x0422;
- t['Tedescendercyrillic'] = 0x04AC;
- t['Tenroman'] = 0x2169;
- t['Tetsecyrillic'] = 0x04B4;
- t['Theta'] = 0x0398;
- t['Thook'] = 0x01AC;
- t['Thorn'] = 0x00DE;
- t['Thornsmall'] = 0xF7FE;
- t['Threeroman'] = 0x2162;
- t['Tildesmall'] = 0xF6FE;
- t['Tiwnarmenian'] = 0x054F;
- t['Tlinebelow'] = 0x1E6E;
- t['Tmonospace'] = 0xFF34;
- t['Toarmenian'] = 0x0539;
- t['Tonefive'] = 0x01BC;
- t['Tonesix'] = 0x0184;
- t['Tonetwo'] = 0x01A7;
- t['Tretroflexhook'] = 0x01AE;
- t['Tsecyrillic'] = 0x0426;
- t['Tshecyrillic'] = 0x040B;
- t['Tsmall'] = 0xF774;
- t['Twelveroman'] = 0x216B;
- t['Tworoman'] = 0x2161;
- t['U'] = 0x0055;
- t['Uacute'] = 0x00DA;
- t['Uacutesmall'] = 0xF7FA;
- t['Ubreve'] = 0x016C;
- t['Ucaron'] = 0x01D3;
- t['Ucircle'] = 0x24CA;
- t['Ucircumflex'] = 0x00DB;
- t['Ucircumflexbelow'] = 0x1E76;
- t['Ucircumflexsmall'] = 0xF7FB;
- t['Ucyrillic'] = 0x0423;
- t['Udblacute'] = 0x0170;
- t['Udblgrave'] = 0x0214;
- t['Udieresis'] = 0x00DC;
- t['Udieresisacute'] = 0x01D7;
- t['Udieresisbelow'] = 0x1E72;
- t['Udieresiscaron'] = 0x01D9;
- t['Udieresiscyrillic'] = 0x04F0;
- t['Udieresisgrave'] = 0x01DB;
- t['Udieresismacron'] = 0x01D5;
- t['Udieresissmall'] = 0xF7FC;
- t['Udotbelow'] = 0x1EE4;
- t['Ugrave'] = 0x00D9;
- t['Ugravesmall'] = 0xF7F9;
- t['Uhookabove'] = 0x1EE6;
- t['Uhorn'] = 0x01AF;
- t['Uhornacute'] = 0x1EE8;
- t['Uhorndotbelow'] = 0x1EF0;
- t['Uhorngrave'] = 0x1EEA;
- t['Uhornhookabove'] = 0x1EEC;
- t['Uhorntilde'] = 0x1EEE;
- t['Uhungarumlaut'] = 0x0170;
- t['Uhungarumlautcyrillic'] = 0x04F2;
- t['Uinvertedbreve'] = 0x0216;
- t['Ukcyrillic'] = 0x0478;
- t['Umacron'] = 0x016A;
- t['Umacroncyrillic'] = 0x04EE;
- t['Umacrondieresis'] = 0x1E7A;
- t['Umonospace'] = 0xFF35;
- t['Uogonek'] = 0x0172;
- t['Upsilon'] = 0x03A5;
- t['Upsilon1'] = 0x03D2;
- t['Upsilonacutehooksymbolgreek'] = 0x03D3;
- t['Upsilonafrican'] = 0x01B1;
- t['Upsilondieresis'] = 0x03AB;
- t['Upsilondieresishooksymbolgreek'] = 0x03D4;
- t['Upsilonhooksymbol'] = 0x03D2;
- t['Upsilontonos'] = 0x038E;
- t['Uring'] = 0x016E;
- t['Ushortcyrillic'] = 0x040E;
- t['Usmall'] = 0xF775;
- t['Ustraightcyrillic'] = 0x04AE;
- t['Ustraightstrokecyrillic'] = 0x04B0;
- t['Utilde'] = 0x0168;
- t['Utildeacute'] = 0x1E78;
- t['Utildebelow'] = 0x1E74;
- t['V'] = 0x0056;
- t['Vcircle'] = 0x24CB;
- t['Vdotbelow'] = 0x1E7E;
- t['Vecyrillic'] = 0x0412;
- t['Vewarmenian'] = 0x054E;
- t['Vhook'] = 0x01B2;
- t['Vmonospace'] = 0xFF36;
- t['Voarmenian'] = 0x0548;
- t['Vsmall'] = 0xF776;
- t['Vtilde'] = 0x1E7C;
- t['W'] = 0x0057;
- t['Wacute'] = 0x1E82;
- t['Wcircle'] = 0x24CC;
- t['Wcircumflex'] = 0x0174;
- t['Wdieresis'] = 0x1E84;
- t['Wdotaccent'] = 0x1E86;
- t['Wdotbelow'] = 0x1E88;
- t['Wgrave'] = 0x1E80;
- t['Wmonospace'] = 0xFF37;
- t['Wsmall'] = 0xF777;
- t['X'] = 0x0058;
- t['Xcircle'] = 0x24CD;
- t['Xdieresis'] = 0x1E8C;
- t['Xdotaccent'] = 0x1E8A;
- t['Xeharmenian'] = 0x053D;
- t['Xi'] = 0x039E;
- t['Xmonospace'] = 0xFF38;
- t['Xsmall'] = 0xF778;
- t['Y'] = 0x0059;
- t['Yacute'] = 0x00DD;
- t['Yacutesmall'] = 0xF7FD;
- t['Yatcyrillic'] = 0x0462;
- t['Ycircle'] = 0x24CE;
- t['Ycircumflex'] = 0x0176;
- t['Ydieresis'] = 0x0178;
- t['Ydieresissmall'] = 0xF7FF;
- t['Ydotaccent'] = 0x1E8E;
- t['Ydotbelow'] = 0x1EF4;
- t['Yericyrillic'] = 0x042B;
- t['Yerudieresiscyrillic'] = 0x04F8;
- t['Ygrave'] = 0x1EF2;
- t['Yhook'] = 0x01B3;
- t['Yhookabove'] = 0x1EF6;
- t['Yiarmenian'] = 0x0545;
- t['Yicyrillic'] = 0x0407;
- t['Yiwnarmenian'] = 0x0552;
- t['Ymonospace'] = 0xFF39;
- t['Ysmall'] = 0xF779;
- t['Ytilde'] = 0x1EF8;
- t['Yusbigcyrillic'] = 0x046A;
- t['Yusbigiotifiedcyrillic'] = 0x046C;
- t['Yuslittlecyrillic'] = 0x0466;
- t['Yuslittleiotifiedcyrillic'] = 0x0468;
- t['Z'] = 0x005A;
- t['Zaarmenian'] = 0x0536;
- t['Zacute'] = 0x0179;
- t['Zcaron'] = 0x017D;
- t['Zcaronsmall'] = 0xF6FF;
- t['Zcircle'] = 0x24CF;
- t['Zcircumflex'] = 0x1E90;
- t['Zdot'] = 0x017B;
- t['Zdotaccent'] = 0x017B;
- t['Zdotbelow'] = 0x1E92;
- t['Zecyrillic'] = 0x0417;
- t['Zedescendercyrillic'] = 0x0498;
- t['Zedieresiscyrillic'] = 0x04DE;
- t['Zeta'] = 0x0396;
- t['Zhearmenian'] = 0x053A;
- t['Zhebrevecyrillic'] = 0x04C1;
- t['Zhecyrillic'] = 0x0416;
- t['Zhedescendercyrillic'] = 0x0496;
- t['Zhedieresiscyrillic'] = 0x04DC;
- t['Zlinebelow'] = 0x1E94;
- t['Zmonospace'] = 0xFF3A;
- t['Zsmall'] = 0xF77A;
- t['Zstroke'] = 0x01B5;
- t['a'] = 0x0061;
- t['aabengali'] = 0x0986;
- t['aacute'] = 0x00E1;
- t['aadeva'] = 0x0906;
- t['aagujarati'] = 0x0A86;
- t['aagurmukhi'] = 0x0A06;
- t['aamatragurmukhi'] = 0x0A3E;
- t['aarusquare'] = 0x3303;
- t['aavowelsignbengali'] = 0x09BE;
- t['aavowelsigndeva'] = 0x093E;
- t['aavowelsigngujarati'] = 0x0ABE;
- t['abbreviationmarkarmenian'] = 0x055F;
- t['abbreviationsigndeva'] = 0x0970;
- t['abengali'] = 0x0985;
- t['abopomofo'] = 0x311A;
- t['abreve'] = 0x0103;
- t['abreveacute'] = 0x1EAF;
- t['abrevecyrillic'] = 0x04D1;
- t['abrevedotbelow'] = 0x1EB7;
- t['abrevegrave'] = 0x1EB1;
- t['abrevehookabove'] = 0x1EB3;
- t['abrevetilde'] = 0x1EB5;
- t['acaron'] = 0x01CE;
- t['acircle'] = 0x24D0;
- t['acircumflex'] = 0x00E2;
- t['acircumflexacute'] = 0x1EA5;
- t['acircumflexdotbelow'] = 0x1EAD;
- t['acircumflexgrave'] = 0x1EA7;
- t['acircumflexhookabove'] = 0x1EA9;
- t['acircumflextilde'] = 0x1EAB;
- t['acute'] = 0x00B4;
- t['acutebelowcmb'] = 0x0317;
- t['acutecmb'] = 0x0301;
- t['acutecomb'] = 0x0301;
- t['acutedeva'] = 0x0954;
- t['acutelowmod'] = 0x02CF;
- t['acutetonecmb'] = 0x0341;
- t['acyrillic'] = 0x0430;
- t['adblgrave'] = 0x0201;
- t['addakgurmukhi'] = 0x0A71;
- t['adeva'] = 0x0905;
- t['adieresis'] = 0x00E4;
- t['adieresiscyrillic'] = 0x04D3;
- t['adieresismacron'] = 0x01DF;
- t['adotbelow'] = 0x1EA1;
- t['adotmacron'] = 0x01E1;
- t['ae'] = 0x00E6;
- t['aeacute'] = 0x01FD;
- t['aekorean'] = 0x3150;
- t['aemacron'] = 0x01E3;
- t['afii00208'] = 0x2015;
- t['afii08941'] = 0x20A4;
- t['afii10017'] = 0x0410;
- t['afii10018'] = 0x0411;
- t['afii10019'] = 0x0412;
- t['afii10020'] = 0x0413;
- t['afii10021'] = 0x0414;
- t['afii10022'] = 0x0415;
- t['afii10023'] = 0x0401;
- t['afii10024'] = 0x0416;
- t['afii10025'] = 0x0417;
- t['afii10026'] = 0x0418;
- t['afii10027'] = 0x0419;
- t['afii10028'] = 0x041A;
- t['afii10029'] = 0x041B;
- t['afii10030'] = 0x041C;
- t['afii10031'] = 0x041D;
- t['afii10032'] = 0x041E;
- t['afii10033'] = 0x041F;
- t['afii10034'] = 0x0420;
- t['afii10035'] = 0x0421;
- t['afii10036'] = 0x0422;
- t['afii10037'] = 0x0423;
- t['afii10038'] = 0x0424;
- t['afii10039'] = 0x0425;
- t['afii10040'] = 0x0426;
- t['afii10041'] = 0x0427;
- t['afii10042'] = 0x0428;
- t['afii10043'] = 0x0429;
- t['afii10044'] = 0x042A;
- t['afii10045'] = 0x042B;
- t['afii10046'] = 0x042C;
- t['afii10047'] = 0x042D;
- t['afii10048'] = 0x042E;
- t['afii10049'] = 0x042F;
- t['afii10050'] = 0x0490;
- t['afii10051'] = 0x0402;
- t['afii10052'] = 0x0403;
- t['afii10053'] = 0x0404;
- t['afii10054'] = 0x0405;
- t['afii10055'] = 0x0406;
- t['afii10056'] = 0x0407;
- t['afii10057'] = 0x0408;
- t['afii10058'] = 0x0409;
- t['afii10059'] = 0x040A;
- t['afii10060'] = 0x040B;
- t['afii10061'] = 0x040C;
- t['afii10062'] = 0x040E;
- t['afii10063'] = 0xF6C4;
- t['afii10064'] = 0xF6C5;
- t['afii10065'] = 0x0430;
- t['afii10066'] = 0x0431;
- t['afii10067'] = 0x0432;
- t['afii10068'] = 0x0433;
- t['afii10069'] = 0x0434;
- t['afii10070'] = 0x0435;
- t['afii10071'] = 0x0451;
- t['afii10072'] = 0x0436;
- t['afii10073'] = 0x0437;
- t['afii10074'] = 0x0438;
- t['afii10075'] = 0x0439;
- t['afii10076'] = 0x043A;
- t['afii10077'] = 0x043B;
- t['afii10078'] = 0x043C;
- t['afii10079'] = 0x043D;
- t['afii10080'] = 0x043E;
- t['afii10081'] = 0x043F;
- t['afii10082'] = 0x0440;
- t['afii10083'] = 0x0441;
- t['afii10084'] = 0x0442;
- t['afii10085'] = 0x0443;
- t['afii10086'] = 0x0444;
- t['afii10087'] = 0x0445;
- t['afii10088'] = 0x0446;
- t['afii10089'] = 0x0447;
- t['afii10090'] = 0x0448;
- t['afii10091'] = 0x0449;
- t['afii10092'] = 0x044A;
- t['afii10093'] = 0x044B;
- t['afii10094'] = 0x044C;
- t['afii10095'] = 0x044D;
- t['afii10096'] = 0x044E;
- t['afii10097'] = 0x044F;
- t['afii10098'] = 0x0491;
- t['afii10099'] = 0x0452;
- t['afii10100'] = 0x0453;
- t['afii10101'] = 0x0454;
- t['afii10102'] = 0x0455;
- t['afii10103'] = 0x0456;
- t['afii10104'] = 0x0457;
- t['afii10105'] = 0x0458;
- t['afii10106'] = 0x0459;
- t['afii10107'] = 0x045A;
- t['afii10108'] = 0x045B;
- t['afii10109'] = 0x045C;
- t['afii10110'] = 0x045E;
- t['afii10145'] = 0x040F;
- t['afii10146'] = 0x0462;
- t['afii10147'] = 0x0472;
- t['afii10148'] = 0x0474;
- t['afii10192'] = 0xF6C6;
- t['afii10193'] = 0x045F;
- t['afii10194'] = 0x0463;
- t['afii10195'] = 0x0473;
- t['afii10196'] = 0x0475;
- t['afii10831'] = 0xF6C7;
- t['afii10832'] = 0xF6C8;
- t['afii10846'] = 0x04D9;
- t['afii299'] = 0x200E;
- t['afii300'] = 0x200F;
- t['afii301'] = 0x200D;
- t['afii57381'] = 0x066A;
- t['afii57388'] = 0x060C;
- t['afii57392'] = 0x0660;
- t['afii57393'] = 0x0661;
- t['afii57394'] = 0x0662;
- t['afii57395'] = 0x0663;
- t['afii57396'] = 0x0664;
- t['afii57397'] = 0x0665;
- t['afii57398'] = 0x0666;
- t['afii57399'] = 0x0667;
- t['afii57400'] = 0x0668;
- t['afii57401'] = 0x0669;
- t['afii57403'] = 0x061B;
- t['afii57407'] = 0x061F;
- t['afii57409'] = 0x0621;
- t['afii57410'] = 0x0622;
- t['afii57411'] = 0x0623;
- t['afii57412'] = 0x0624;
- t['afii57413'] = 0x0625;
- t['afii57414'] = 0x0626;
- t['afii57415'] = 0x0627;
- t['afii57416'] = 0x0628;
- t['afii57417'] = 0x0629;
- t['afii57418'] = 0x062A;
- t['afii57419'] = 0x062B;
- t['afii57420'] = 0x062C;
- t['afii57421'] = 0x062D;
- t['afii57422'] = 0x062E;
- t['afii57423'] = 0x062F;
- t['afii57424'] = 0x0630;
- t['afii57425'] = 0x0631;
- t['afii57426'] = 0x0632;
- t['afii57427'] = 0x0633;
- t['afii57428'] = 0x0634;
- t['afii57429'] = 0x0635;
- t['afii57430'] = 0x0636;
- t['afii57431'] = 0x0637;
- t['afii57432'] = 0x0638;
- t['afii57433'] = 0x0639;
- t['afii57434'] = 0x063A;
- t['afii57440'] = 0x0640;
- t['afii57441'] = 0x0641;
- t['afii57442'] = 0x0642;
- t['afii57443'] = 0x0643;
- t['afii57444'] = 0x0644;
- t['afii57445'] = 0x0645;
- t['afii57446'] = 0x0646;
- t['afii57448'] = 0x0648;
- t['afii57449'] = 0x0649;
- t['afii57450'] = 0x064A;
- t['afii57451'] = 0x064B;
- t['afii57452'] = 0x064C;
- t['afii57453'] = 0x064D;
- t['afii57454'] = 0x064E;
- t['afii57455'] = 0x064F;
- t['afii57456'] = 0x0650;
- t['afii57457'] = 0x0651;
- t['afii57458'] = 0x0652;
- t['afii57470'] = 0x0647;
- t['afii57505'] = 0x06A4;
- t['afii57506'] = 0x067E;
- t['afii57507'] = 0x0686;
- t['afii57508'] = 0x0698;
- t['afii57509'] = 0x06AF;
- t['afii57511'] = 0x0679;
- t['afii57512'] = 0x0688;
- t['afii57513'] = 0x0691;
- t['afii57514'] = 0x06BA;
- t['afii57519'] = 0x06D2;
- t['afii57534'] = 0x06D5;
- t['afii57636'] = 0x20AA;
- t['afii57645'] = 0x05BE;
- t['afii57658'] = 0x05C3;
- t['afii57664'] = 0x05D0;
- t['afii57665'] = 0x05D1;
- t['afii57666'] = 0x05D2;
- t['afii57667'] = 0x05D3;
- t['afii57668'] = 0x05D4;
- t['afii57669'] = 0x05D5;
- t['afii57670'] = 0x05D6;
- t['afii57671'] = 0x05D7;
- t['afii57672'] = 0x05D8;
- t['afii57673'] = 0x05D9;
- t['afii57674'] = 0x05DA;
- t['afii57675'] = 0x05DB;
- t['afii57676'] = 0x05DC;
- t['afii57677'] = 0x05DD;
- t['afii57678'] = 0x05DE;
- t['afii57679'] = 0x05DF;
- t['afii57680'] = 0x05E0;
- t['afii57681'] = 0x05E1;
- t['afii57682'] = 0x05E2;
- t['afii57683'] = 0x05E3;
- t['afii57684'] = 0x05E4;
- t['afii57685'] = 0x05E5;
- t['afii57686'] = 0x05E6;
- t['afii57687'] = 0x05E7;
- t['afii57688'] = 0x05E8;
- t['afii57689'] = 0x05E9;
- t['afii57690'] = 0x05EA;
- t['afii57694'] = 0xFB2A;
- t['afii57695'] = 0xFB2B;
- t['afii57700'] = 0xFB4B;
- t['afii57705'] = 0xFB1F;
- t['afii57716'] = 0x05F0;
- t['afii57717'] = 0x05F1;
- t['afii57718'] = 0x05F2;
- t['afii57723'] = 0xFB35;
- t['afii57793'] = 0x05B4;
- t['afii57794'] = 0x05B5;
- t['afii57795'] = 0x05B6;
- t['afii57796'] = 0x05BB;
- t['afii57797'] = 0x05B8;
- t['afii57798'] = 0x05B7;
- t['afii57799'] = 0x05B0;
- t['afii57800'] = 0x05B2;
- t['afii57801'] = 0x05B1;
- t['afii57802'] = 0x05B3;
- t['afii57803'] = 0x05C2;
- t['afii57804'] = 0x05C1;
- t['afii57806'] = 0x05B9;
- t['afii57807'] = 0x05BC;
- t['afii57839'] = 0x05BD;
- t['afii57841'] = 0x05BF;
- t['afii57842'] = 0x05C0;
- t['afii57929'] = 0x02BC;
- t['afii61248'] = 0x2105;
- t['afii61289'] = 0x2113;
- t['afii61352'] = 0x2116;
- t['afii61573'] = 0x202C;
- t['afii61574'] = 0x202D;
- t['afii61575'] = 0x202E;
- t['afii61664'] = 0x200C;
- t['afii63167'] = 0x066D;
- t['afii64937'] = 0x02BD;
- t['agrave'] = 0x00E0;
- t['agujarati'] = 0x0A85;
- t['agurmukhi'] = 0x0A05;
- t['ahiragana'] = 0x3042;
- t['ahookabove'] = 0x1EA3;
- t['aibengali'] = 0x0990;
- t['aibopomofo'] = 0x311E;
- t['aideva'] = 0x0910;
- t['aiecyrillic'] = 0x04D5;
- t['aigujarati'] = 0x0A90;
- t['aigurmukhi'] = 0x0A10;
- t['aimatragurmukhi'] = 0x0A48;
- t['ainarabic'] = 0x0639;
- t['ainfinalarabic'] = 0xFECA;
- t['aininitialarabic'] = 0xFECB;
- t['ainmedialarabic'] = 0xFECC;
- t['ainvertedbreve'] = 0x0203;
- t['aivowelsignbengali'] = 0x09C8;
- t['aivowelsigndeva'] = 0x0948;
- t['aivowelsigngujarati'] = 0x0AC8;
- t['akatakana'] = 0x30A2;
- t['akatakanahalfwidth'] = 0xFF71;
- t['akorean'] = 0x314F;
- t['alef'] = 0x05D0;
- t['alefarabic'] = 0x0627;
- t['alefdageshhebrew'] = 0xFB30;
- t['aleffinalarabic'] = 0xFE8E;
- t['alefhamzaabovearabic'] = 0x0623;
- t['alefhamzaabovefinalarabic'] = 0xFE84;
- t['alefhamzabelowarabic'] = 0x0625;
- t['alefhamzabelowfinalarabic'] = 0xFE88;
- t['alefhebrew'] = 0x05D0;
- t['aleflamedhebrew'] = 0xFB4F;
- t['alefmaddaabovearabic'] = 0x0622;
- t['alefmaddaabovefinalarabic'] = 0xFE82;
- t['alefmaksuraarabic'] = 0x0649;
- t['alefmaksurafinalarabic'] = 0xFEF0;
- t['alefmaksurainitialarabic'] = 0xFEF3;
- t['alefmaksuramedialarabic'] = 0xFEF4;
- t['alefpatahhebrew'] = 0xFB2E;
- t['alefqamatshebrew'] = 0xFB2F;
- t['aleph'] = 0x2135;
- t['allequal'] = 0x224C;
- t['alpha'] = 0x03B1;
- t['alphatonos'] = 0x03AC;
- t['amacron'] = 0x0101;
- t['amonospace'] = 0xFF41;
- t['ampersand'] = 0x0026;
- t['ampersandmonospace'] = 0xFF06;
- t['ampersandsmall'] = 0xF726;
- t['amsquare'] = 0x33C2;
- t['anbopomofo'] = 0x3122;
- t['angbopomofo'] = 0x3124;
- t['angbracketleft'] = 0x3008;
- // Glyph is missing from Adobe's original list.
- t['angbracketright'] = 0x3009;
- // Glyph is missing from Adobe's original list.
- t['angkhankhuthai'] = 0x0E5A;
- t['angle'] = 0x2220;
- t['anglebracketleft'] = 0x3008;
- t['anglebracketleftvertical'] = 0xFE3F;
- t['anglebracketright'] = 0x3009;
- t['anglebracketrightvertical'] = 0xFE40;
- t['angleleft'] = 0x2329;
- t['angleright'] = 0x232A;
- t['angstrom'] = 0x212B;
- t['anoteleia'] = 0x0387;
- t['anudattadeva'] = 0x0952;
- t['anusvarabengali'] = 0x0982;
- t['anusvaradeva'] = 0x0902;
- t['anusvaragujarati'] = 0x0A82;
- t['aogonek'] = 0x0105;
- t['apaatosquare'] = 0x3300;
- t['aparen'] = 0x249C;
- t['apostrophearmenian'] = 0x055A;
- t['apostrophemod'] = 0x02BC;
- t['apple'] = 0xF8FF;
- t['approaches'] = 0x2250;
- t['approxequal'] = 0x2248;
- t['approxequalorimage'] = 0x2252;
- t['approximatelyequal'] = 0x2245;
- t['araeaekorean'] = 0x318E;
- t['araeakorean'] = 0x318D;
- t['arc'] = 0x2312;
- t['arighthalfring'] = 0x1E9A;
- t['aring'] = 0x00E5;
- t['aringacute'] = 0x01FB;
- t['aringbelow'] = 0x1E01;
- t['arrowboth'] = 0x2194;
- t['arrowdashdown'] = 0x21E3;
- t['arrowdashleft'] = 0x21E0;
- t['arrowdashright'] = 0x21E2;
- t['arrowdashup'] = 0x21E1;
- t['arrowdblboth'] = 0x21D4;
- t['arrowdbldown'] = 0x21D3;
- t['arrowdblleft'] = 0x21D0;
- t['arrowdblright'] = 0x21D2;
- t['arrowdblup'] = 0x21D1;
- t['arrowdown'] = 0x2193;
- t['arrowdownleft'] = 0x2199;
- t['arrowdownright'] = 0x2198;
- t['arrowdownwhite'] = 0x21E9;
- t['arrowheaddownmod'] = 0x02C5;
- t['arrowheadleftmod'] = 0x02C2;
- t['arrowheadrightmod'] = 0x02C3;
- t['arrowheadupmod'] = 0x02C4;
- t['arrowhorizex'] = 0xF8E7;
- t['arrowleft'] = 0x2190;
- t['arrowleftdbl'] = 0x21D0;
- t['arrowleftdblstroke'] = 0x21CD;
- t['arrowleftoverright'] = 0x21C6;
- t['arrowleftwhite'] = 0x21E6;
- t['arrowright'] = 0x2192;
- t['arrowrightdblstroke'] = 0x21CF;
- t['arrowrightheavy'] = 0x279E;
- t['arrowrightoverleft'] = 0x21C4;
- t['arrowrightwhite'] = 0x21E8;
- t['arrowtableft'] = 0x21E4;
- t['arrowtabright'] = 0x21E5;
- t['arrowup'] = 0x2191;
- t['arrowupdn'] = 0x2195;
- t['arrowupdnbse'] = 0x21A8;
- t['arrowupdownbase'] = 0x21A8;
- t['arrowupleft'] = 0x2196;
- t['arrowupleftofdown'] = 0x21C5;
- t['arrowupright'] = 0x2197;
- t['arrowupwhite'] = 0x21E7;
- t['arrowvertex'] = 0xF8E6;
- t['asciicircum'] = 0x005E;
- t['asciicircummonospace'] = 0xFF3E;
- t['asciitilde'] = 0x007E;
- t['asciitildemonospace'] = 0xFF5E;
- t['ascript'] = 0x0251;
- t['ascriptturned'] = 0x0252;
- t['asmallhiragana'] = 0x3041;
- t['asmallkatakana'] = 0x30A1;
- t['asmallkatakanahalfwidth'] = 0xFF67;
- t['asterisk'] = 0x002A;
- t['asteriskaltonearabic'] = 0x066D;
- t['asteriskarabic'] = 0x066D;
- t['asteriskmath'] = 0x2217;
- t['asteriskmonospace'] = 0xFF0A;
- t['asterisksmall'] = 0xFE61;
- t['asterism'] = 0x2042;
- t['asuperior'] = 0xF6E9;
- t['asymptoticallyequal'] = 0x2243;
- t['at'] = 0x0040;
- t['atilde'] = 0x00E3;
- t['atmonospace'] = 0xFF20;
- t['atsmall'] = 0xFE6B;
- t['aturned'] = 0x0250;
- t['aubengali'] = 0x0994;
- t['aubopomofo'] = 0x3120;
- t['audeva'] = 0x0914;
- t['augujarati'] = 0x0A94;
- t['augurmukhi'] = 0x0A14;
- t['aulengthmarkbengali'] = 0x09D7;
- t['aumatragurmukhi'] = 0x0A4C;
- t['auvowelsignbengali'] = 0x09CC;
- t['auvowelsigndeva'] = 0x094C;
- t['auvowelsigngujarati'] = 0x0ACC;
- t['avagrahadeva'] = 0x093D;
- t['aybarmenian'] = 0x0561;
- t['ayin'] = 0x05E2;
- t['ayinaltonehebrew'] = 0xFB20;
- t['ayinhebrew'] = 0x05E2;
- t['b'] = 0x0062;
- t['babengali'] = 0x09AC;
- t['backslash'] = 0x005C;
- t['backslashmonospace'] = 0xFF3C;
- t['badeva'] = 0x092C;
- t['bagujarati'] = 0x0AAC;
- t['bagurmukhi'] = 0x0A2C;
- t['bahiragana'] = 0x3070;
- t['bahtthai'] = 0x0E3F;
- t['bakatakana'] = 0x30D0;
- t['bar'] = 0x007C;
- t['barmonospace'] = 0xFF5C;
- t['bbopomofo'] = 0x3105;
- t['bcircle'] = 0x24D1;
- t['bdotaccent'] = 0x1E03;
- t['bdotbelow'] = 0x1E05;
- t['beamedsixteenthnotes'] = 0x266C;
- t['because'] = 0x2235;
- t['becyrillic'] = 0x0431;
- t['beharabic'] = 0x0628;
- t['behfinalarabic'] = 0xFE90;
- t['behinitialarabic'] = 0xFE91;
- t['behiragana'] = 0x3079;
- t['behmedialarabic'] = 0xFE92;
- t['behmeeminitialarabic'] = 0xFC9F;
- t['behmeemisolatedarabic'] = 0xFC08;
- t['behnoonfinalarabic'] = 0xFC6D;
- t['bekatakana'] = 0x30D9;
- t['benarmenian'] = 0x0562;
- t['bet'] = 0x05D1;
- t['beta'] = 0x03B2;
- t['betasymbolgreek'] = 0x03D0;
- t['betdagesh'] = 0xFB31;
- t['betdageshhebrew'] = 0xFB31;
- t['bethebrew'] = 0x05D1;
- t['betrafehebrew'] = 0xFB4C;
- t['bhabengali'] = 0x09AD;
- t['bhadeva'] = 0x092D;
- t['bhagujarati'] = 0x0AAD;
- t['bhagurmukhi'] = 0x0A2D;
- t['bhook'] = 0x0253;
- t['bihiragana'] = 0x3073;
- t['bikatakana'] = 0x30D3;
- t['bilabialclick'] = 0x0298;
- t['bindigurmukhi'] = 0x0A02;
- t['birusquare'] = 0x3331;
- t['blackcircle'] = 0x25CF;
- t['blackdiamond'] = 0x25C6;
- t['blackdownpointingtriangle'] = 0x25BC;
- t['blackleftpointingpointer'] = 0x25C4;
- t['blackleftpointingtriangle'] = 0x25C0;
- t['blacklenticularbracketleft'] = 0x3010;
- t['blacklenticularbracketleftvertical'] = 0xFE3B;
- t['blacklenticularbracketright'] = 0x3011;
- t['blacklenticularbracketrightvertical'] = 0xFE3C;
- t['blacklowerlefttriangle'] = 0x25E3;
- t['blacklowerrighttriangle'] = 0x25E2;
- t['blackrectangle'] = 0x25AC;
- t['blackrightpointingpointer'] = 0x25BA;
- t['blackrightpointingtriangle'] = 0x25B6;
- t['blacksmallsquare'] = 0x25AA;
- t['blacksmilingface'] = 0x263B;
- t['blacksquare'] = 0x25A0;
- t['blackstar'] = 0x2605;
- t['blackupperlefttriangle'] = 0x25E4;
- t['blackupperrighttriangle'] = 0x25E5;
- t['blackuppointingsmalltriangle'] = 0x25B4;
- t['blackuppointingtriangle'] = 0x25B2;
- t['blank'] = 0x2423;
- t['blinebelow'] = 0x1E07;
- t['block'] = 0x2588;
- t['bmonospace'] = 0xFF42;
- t['bobaimaithai'] = 0x0E1A;
- t['bohiragana'] = 0x307C;
- t['bokatakana'] = 0x30DC;
- t['bparen'] = 0x249D;
- t['bqsquare'] = 0x33C3;
- t['braceex'] = 0xF8F4;
- t['braceleft'] = 0x007B;
- t['braceleftbt'] = 0xF8F3;
- t['braceleftmid'] = 0xF8F2;
- t['braceleftmonospace'] = 0xFF5B;
- t['braceleftsmall'] = 0xFE5B;
- t['bracelefttp'] = 0xF8F1;
- t['braceleftvertical'] = 0xFE37;
- t['braceright'] = 0x007D;
- t['bracerightbt'] = 0xF8FE;
- t['bracerightmid'] = 0xF8FD;
- t['bracerightmonospace'] = 0xFF5D;
- t['bracerightsmall'] = 0xFE5C;
- t['bracerighttp'] = 0xF8FC;
- t['bracerightvertical'] = 0xFE38;
- t['bracketleft'] = 0x005B;
- t['bracketleftbt'] = 0xF8F0;
- t['bracketleftex'] = 0xF8EF;
- t['bracketleftmonospace'] = 0xFF3B;
- t['bracketlefttp'] = 0xF8EE;
- t['bracketright'] = 0x005D;
- t['bracketrightbt'] = 0xF8FB;
- t['bracketrightex'] = 0xF8FA;
- t['bracketrightmonospace'] = 0xFF3D;
- t['bracketrighttp'] = 0xF8F9;
- t['breve'] = 0x02D8;
- t['brevebelowcmb'] = 0x032E;
- t['brevecmb'] = 0x0306;
- t['breveinvertedbelowcmb'] = 0x032F;
- t['breveinvertedcmb'] = 0x0311;
- t['breveinverteddoublecmb'] = 0x0361;
- t['bridgebelowcmb'] = 0x032A;
- t['bridgeinvertedbelowcmb'] = 0x033A;
- t['brokenbar'] = 0x00A6;
- t['bstroke'] = 0x0180;
- t['bsuperior'] = 0xF6EA;
- t['btopbar'] = 0x0183;
- t['buhiragana'] = 0x3076;
- t['bukatakana'] = 0x30D6;
- t['bullet'] = 0x2022;
- t['bulletinverse'] = 0x25D8;
- t['bulletoperator'] = 0x2219;
- t['bullseye'] = 0x25CE;
- t['c'] = 0x0063;
- t['caarmenian'] = 0x056E;
- t['cabengali'] = 0x099A;
- t['cacute'] = 0x0107;
- t['cadeva'] = 0x091A;
- t['cagujarati'] = 0x0A9A;
- t['cagurmukhi'] = 0x0A1A;
- t['calsquare'] = 0x3388;
- t['candrabindubengali'] = 0x0981;
- t['candrabinducmb'] = 0x0310;
- t['candrabindudeva'] = 0x0901;
- t['candrabindugujarati'] = 0x0A81;
- t['capslock'] = 0x21EA;
- t['careof'] = 0x2105;
- t['caron'] = 0x02C7;
- t['caronbelowcmb'] = 0x032C;
- t['caroncmb'] = 0x030C;
- t['carriagereturn'] = 0x21B5;
- t['cbopomofo'] = 0x3118;
- t['ccaron'] = 0x010D;
- t['ccedilla'] = 0x00E7;
- t['ccedillaacute'] = 0x1E09;
- t['ccircle'] = 0x24D2;
- t['ccircumflex'] = 0x0109;
- t['ccurl'] = 0x0255;
- t['cdot'] = 0x010B;
- t['cdotaccent'] = 0x010B;
- t['cdsquare'] = 0x33C5;
- t['cedilla'] = 0x00B8;
- t['cedillacmb'] = 0x0327;
- t['cent'] = 0x00A2;
- t['centigrade'] = 0x2103;
- t['centinferior'] = 0xF6DF;
- t['centmonospace'] = 0xFFE0;
- t['centoldstyle'] = 0xF7A2;
- t['centsuperior'] = 0xF6E0;
- t['chaarmenian'] = 0x0579;
- t['chabengali'] = 0x099B;
- t['chadeva'] = 0x091B;
- t['chagujarati'] = 0x0A9B;
- t['chagurmukhi'] = 0x0A1B;
- t['chbopomofo'] = 0x3114;
- t['cheabkhasiancyrillic'] = 0x04BD;
- t['checkmark'] = 0x2713;
- t['checyrillic'] = 0x0447;
- t['chedescenderabkhasiancyrillic'] = 0x04BF;
- t['chedescendercyrillic'] = 0x04B7;
- t['chedieresiscyrillic'] = 0x04F5;
- t['cheharmenian'] = 0x0573;
- t['chekhakassiancyrillic'] = 0x04CC;
- t['cheverticalstrokecyrillic'] = 0x04B9;
- t['chi'] = 0x03C7;
- t['chieuchacirclekorean'] = 0x3277;
- t['chieuchaparenkorean'] = 0x3217;
- t['chieuchcirclekorean'] = 0x3269;
- t['chieuchkorean'] = 0x314A;
- t['chieuchparenkorean'] = 0x3209;
- t['chochangthai'] = 0x0E0A;
- t['chochanthai'] = 0x0E08;
- t['chochingthai'] = 0x0E09;
- t['chochoethai'] = 0x0E0C;
- t['chook'] = 0x0188;
- t['cieucacirclekorean'] = 0x3276;
- t['cieucaparenkorean'] = 0x3216;
- t['cieuccirclekorean'] = 0x3268;
- t['cieuckorean'] = 0x3148;
- t['cieucparenkorean'] = 0x3208;
- t['cieucuparenkorean'] = 0x321C;
- t['circle'] = 0x25CB;
- t['circlecopyrt'] = 0x00A9;
- // Glyph is missing from Adobe's original list.
- t['circlemultiply'] = 0x2297;
- t['circleot'] = 0x2299;
- t['circleplus'] = 0x2295;
- t['circlepostalmark'] = 0x3036;
- t['circlewithlefthalfblack'] = 0x25D0;
- t['circlewithrighthalfblack'] = 0x25D1;
- t['circumflex'] = 0x02C6;
- t['circumflexbelowcmb'] = 0x032D;
- t['circumflexcmb'] = 0x0302;
- t['clear'] = 0x2327;
- t['clickalveolar'] = 0x01C2;
- t['clickdental'] = 0x01C0;
- t['clicklateral'] = 0x01C1;
- t['clickretroflex'] = 0x01C3;
- t['club'] = 0x2663;
- t['clubsuitblack'] = 0x2663;
- t['clubsuitwhite'] = 0x2667;
- t['cmcubedsquare'] = 0x33A4;
- t['cmonospace'] = 0xFF43;
- t['cmsquaredsquare'] = 0x33A0;
- t['coarmenian'] = 0x0581;
- t['colon'] = 0x003A;
- t['colonmonetary'] = 0x20A1;
- t['colonmonospace'] = 0xFF1A;
- t['colonsign'] = 0x20A1;
- t['colonsmall'] = 0xFE55;
- t['colontriangularhalfmod'] = 0x02D1;
- t['colontriangularmod'] = 0x02D0;
- t['comma'] = 0x002C;
- t['commaabovecmb'] = 0x0313;
- t['commaaboverightcmb'] = 0x0315;
- t['commaaccent'] = 0xF6C3;
- t['commaarabic'] = 0x060C;
- t['commaarmenian'] = 0x055D;
- t['commainferior'] = 0xF6E1;
- t['commamonospace'] = 0xFF0C;
- t['commareversedabovecmb'] = 0x0314;
- t['commareversedmod'] = 0x02BD;
- t['commasmall'] = 0xFE50;
- t['commasuperior'] = 0xF6E2;
- t['commaturnedabovecmb'] = 0x0312;
- t['commaturnedmod'] = 0x02BB;
- t['compass'] = 0x263C;
- t['congruent'] = 0x2245;
- t['contourintegral'] = 0x222E;
- t['control'] = 0x2303;
- t['controlACK'] = 0x0006;
- t['controlBEL'] = 0x0007;
- t['controlBS'] = 0x0008;
- t['controlCAN'] = 0x0018;
- t['controlCR'] = 0x000D;
- t['controlDC1'] = 0x0011;
- t['controlDC2'] = 0x0012;
- t['controlDC3'] = 0x0013;
- t['controlDC4'] = 0x0014;
- t['controlDEL'] = 0x007F;
- t['controlDLE'] = 0x0010;
- t['controlEM'] = 0x0019;
- t['controlENQ'] = 0x0005;
- t['controlEOT'] = 0x0004;
- t['controlESC'] = 0x001B;
- t['controlETB'] = 0x0017;
- t['controlETX'] = 0x0003;
- t['controlFF'] = 0x000C;
- t['controlFS'] = 0x001C;
- t['controlGS'] = 0x001D;
- t['controlHT'] = 0x0009;
- t['controlLF'] = 0x000A;
- t['controlNAK'] = 0x0015;
- t['controlRS'] = 0x001E;
- t['controlSI'] = 0x000F;
- t['controlSO'] = 0x000E;
- t['controlSOT'] = 0x0002;
- t['controlSTX'] = 0x0001;
- t['controlSUB'] = 0x001A;
- t['controlSYN'] = 0x0016;
- t['controlUS'] = 0x001F;
- t['controlVT'] = 0x000B;
- t['copyright'] = 0x00A9;
- t['copyrightsans'] = 0xF8E9;
- t['copyrightserif'] = 0xF6D9;
- t['cornerbracketleft'] = 0x300C;
- t['cornerbracketlefthalfwidth'] = 0xFF62;
- t['cornerbracketleftvertical'] = 0xFE41;
- t['cornerbracketright'] = 0x300D;
- t['cornerbracketrighthalfwidth'] = 0xFF63;
- t['cornerbracketrightvertical'] = 0xFE42;
- t['corporationsquare'] = 0x337F;
- t['cosquare'] = 0x33C7;
- t['coverkgsquare'] = 0x33C6;
- t['cparen'] = 0x249E;
- t['cruzeiro'] = 0x20A2;
- t['cstretched'] = 0x0297;
- t['curlyand'] = 0x22CF;
- t['curlyor'] = 0x22CE;
- t['currency'] = 0x00A4;
- t['cyrBreve'] = 0xF6D1;
- t['cyrFlex'] = 0xF6D2;
- t['cyrbreve'] = 0xF6D4;
- t['cyrflex'] = 0xF6D5;
- t['d'] = 0x0064;
- t['daarmenian'] = 0x0564;
- t['dabengali'] = 0x09A6;
- t['dadarabic'] = 0x0636;
- t['dadeva'] = 0x0926;
- t['dadfinalarabic'] = 0xFEBE;
- t['dadinitialarabic'] = 0xFEBF;
- t['dadmedialarabic'] = 0xFEC0;
- t['dagesh'] = 0x05BC;
- t['dageshhebrew'] = 0x05BC;
- t['dagger'] = 0x2020;
- t['daggerdbl'] = 0x2021;
- t['dagujarati'] = 0x0AA6;
- t['dagurmukhi'] = 0x0A26;
- t['dahiragana'] = 0x3060;
- t['dakatakana'] = 0x30C0;
- t['dalarabic'] = 0x062F;
- t['dalet'] = 0x05D3;
- t['daletdagesh'] = 0xFB33;
- t['daletdageshhebrew'] = 0xFB33;
- t['dalethebrew'] = 0x05D3;
- t['dalfinalarabic'] = 0xFEAA;
- t['dammaarabic'] = 0x064F;
- t['dammalowarabic'] = 0x064F;
- t['dammatanaltonearabic'] = 0x064C;
- t['dammatanarabic'] = 0x064C;
- t['danda'] = 0x0964;
- t['dargahebrew'] = 0x05A7;
- t['dargalefthebrew'] = 0x05A7;
- t['dasiapneumatacyrilliccmb'] = 0x0485;
- t['dblGrave'] = 0xF6D3;
- t['dblanglebracketleft'] = 0x300A;
- t['dblanglebracketleftvertical'] = 0xFE3D;
- t['dblanglebracketright'] = 0x300B;
- t['dblanglebracketrightvertical'] = 0xFE3E;
- t['dblarchinvertedbelowcmb'] = 0x032B;
- t['dblarrowleft'] = 0x21D4;
- t['dblarrowright'] = 0x21D2;
- t['dbldanda'] = 0x0965;
- t['dblgrave'] = 0xF6D6;
- t['dblgravecmb'] = 0x030F;
- t['dblintegral'] = 0x222C;
- t['dbllowline'] = 0x2017;
- t['dbllowlinecmb'] = 0x0333;
- t['dbloverlinecmb'] = 0x033F;
- t['dblprimemod'] = 0x02BA;
- t['dblverticalbar'] = 0x2016;
- t['dblverticallineabovecmb'] = 0x030E;
- t['dbopomofo'] = 0x3109;
- t['dbsquare'] = 0x33C8;
- t['dcaron'] = 0x010F;
- t['dcedilla'] = 0x1E11;
- t['dcircle'] = 0x24D3;
- t['dcircumflexbelow'] = 0x1E13;
- t['dcroat'] = 0x0111;
- t['ddabengali'] = 0x09A1;
- t['ddadeva'] = 0x0921;
- t['ddagujarati'] = 0x0AA1;
- t['ddagurmukhi'] = 0x0A21;
- t['ddalarabic'] = 0x0688;
- t['ddalfinalarabic'] = 0xFB89;
- t['dddhadeva'] = 0x095C;
- t['ddhabengali'] = 0x09A2;
- t['ddhadeva'] = 0x0922;
- t['ddhagujarati'] = 0x0AA2;
- t['ddhagurmukhi'] = 0x0A22;
- t['ddotaccent'] = 0x1E0B;
- t['ddotbelow'] = 0x1E0D;
- t['decimalseparatorarabic'] = 0x066B;
- t['decimalseparatorpersian'] = 0x066B;
- t['decyrillic'] = 0x0434;
- t['degree'] = 0x00B0;
- t['dehihebrew'] = 0x05AD;
- t['dehiragana'] = 0x3067;
- t['deicoptic'] = 0x03EF;
- t['dekatakana'] = 0x30C7;
- t['deleteleft'] = 0x232B;
- t['deleteright'] = 0x2326;
- t['delta'] = 0x03B4;
- t['deltaturned'] = 0x018D;
- t['denominatorminusonenumeratorbengali'] = 0x09F8;
- t['dezh'] = 0x02A4;
- t['dhabengali'] = 0x09A7;
- t['dhadeva'] = 0x0927;
- t['dhagujarati'] = 0x0AA7;
- t['dhagurmukhi'] = 0x0A27;
- t['dhook'] = 0x0257;
- t['dialytikatonos'] = 0x0385;
- t['dialytikatonoscmb'] = 0x0344;
- t['diamond'] = 0x2666;
- t['diamondsuitwhite'] = 0x2662;
- t['dieresis'] = 0x00A8;
- t['dieresisacute'] = 0xF6D7;
- t['dieresisbelowcmb'] = 0x0324;
- t['dieresiscmb'] = 0x0308;
- t['dieresisgrave'] = 0xF6D8;
- t['dieresistonos'] = 0x0385;
- t['dihiragana'] = 0x3062;
- t['dikatakana'] = 0x30C2;
- t['dittomark'] = 0x3003;
- t['divide'] = 0x00F7;
- t['divides'] = 0x2223;
- t['divisionslash'] = 0x2215;
- t['djecyrillic'] = 0x0452;
- t['dkshade'] = 0x2593;
- t['dlinebelow'] = 0x1E0F;
- t['dlsquare'] = 0x3397;
- t['dmacron'] = 0x0111;
- t['dmonospace'] = 0xFF44;
- t['dnblock'] = 0x2584;
- t['dochadathai'] = 0x0E0E;
- t['dodekthai'] = 0x0E14;
- t['dohiragana'] = 0x3069;
- t['dokatakana'] = 0x30C9;
- t['dollar'] = 0x0024;
- t['dollarinferior'] = 0xF6E3;
- t['dollarmonospace'] = 0xFF04;
- t['dollaroldstyle'] = 0xF724;
- t['dollarsmall'] = 0xFE69;
- t['dollarsuperior'] = 0xF6E4;
- t['dong'] = 0x20AB;
- t['dorusquare'] = 0x3326;
- t['dotaccent'] = 0x02D9;
- t['dotaccentcmb'] = 0x0307;
- t['dotbelowcmb'] = 0x0323;
- t['dotbelowcomb'] = 0x0323;
- t['dotkatakana'] = 0x30FB;
- t['dotlessi'] = 0x0131;
- t['dotlessj'] = 0xF6BE;
- t['dotlessjstrokehook'] = 0x0284;
- t['dotmath'] = 0x22C5;
- t['dottedcircle'] = 0x25CC;
- t['doubleyodpatah'] = 0xFB1F;
- t['doubleyodpatahhebrew'] = 0xFB1F;
- t['downtackbelowcmb'] = 0x031E;
- t['downtackmod'] = 0x02D5;
- t['dparen'] = 0x249F;
- t['dsuperior'] = 0xF6EB;
- t['dtail'] = 0x0256;
- t['dtopbar'] = 0x018C;
- t['duhiragana'] = 0x3065;
- t['dukatakana'] = 0x30C5;
- t['dz'] = 0x01F3;
- t['dzaltone'] = 0x02A3;
- t['dzcaron'] = 0x01C6;
- t['dzcurl'] = 0x02A5;
- t['dzeabkhasiancyrillic'] = 0x04E1;
- t['dzecyrillic'] = 0x0455;
- t['dzhecyrillic'] = 0x045F;
- t['e'] = 0x0065;
- t['eacute'] = 0x00E9;
- t['earth'] = 0x2641;
- t['ebengali'] = 0x098F;
- t['ebopomofo'] = 0x311C;
- t['ebreve'] = 0x0115;
- t['ecandradeva'] = 0x090D;
- t['ecandragujarati'] = 0x0A8D;
- t['ecandravowelsigndeva'] = 0x0945;
- t['ecandravowelsigngujarati'] = 0x0AC5;
- t['ecaron'] = 0x011B;
- t['ecedillabreve'] = 0x1E1D;
- t['echarmenian'] = 0x0565;
- t['echyiwnarmenian'] = 0x0587;
- t['ecircle'] = 0x24D4;
- t['ecircumflex'] = 0x00EA;
- t['ecircumflexacute'] = 0x1EBF;
- t['ecircumflexbelow'] = 0x1E19;
- t['ecircumflexdotbelow'] = 0x1EC7;
- t['ecircumflexgrave'] = 0x1EC1;
- t['ecircumflexhookabove'] = 0x1EC3;
- t['ecircumflextilde'] = 0x1EC5;
- t['ecyrillic'] = 0x0454;
- t['edblgrave'] = 0x0205;
- t['edeva'] = 0x090F;
- t['edieresis'] = 0x00EB;
- t['edot'] = 0x0117;
- t['edotaccent'] = 0x0117;
- t['edotbelow'] = 0x1EB9;
- t['eegurmukhi'] = 0x0A0F;
- t['eematragurmukhi'] = 0x0A47;
- t['efcyrillic'] = 0x0444;
- t['egrave'] = 0x00E8;
- t['egujarati'] = 0x0A8F;
- t['eharmenian'] = 0x0567;
- t['ehbopomofo'] = 0x311D;
- t['ehiragana'] = 0x3048;
- t['ehookabove'] = 0x1EBB;
- t['eibopomofo'] = 0x311F;
- t['eight'] = 0x0038;
- t['eightarabic'] = 0x0668;
- t['eightbengali'] = 0x09EE;
- t['eightcircle'] = 0x2467;
- t['eightcircleinversesansserif'] = 0x2791;
- t['eightdeva'] = 0x096E;
- t['eighteencircle'] = 0x2471;
- t['eighteenparen'] = 0x2485;
- t['eighteenperiod'] = 0x2499;
- t['eightgujarati'] = 0x0AEE;
- t['eightgurmukhi'] = 0x0A6E;
- t['eighthackarabic'] = 0x0668;
- t['eighthangzhou'] = 0x3028;
- t['eighthnotebeamed'] = 0x266B;
- t['eightideographicparen'] = 0x3227;
- t['eightinferior'] = 0x2088;
- t['eightmonospace'] = 0xFF18;
- t['eightoldstyle'] = 0xF738;
- t['eightparen'] = 0x247B;
- t['eightperiod'] = 0x248F;
- t['eightpersian'] = 0x06F8;
- t['eightroman'] = 0x2177;
- t['eightsuperior'] = 0x2078;
- t['eightthai'] = 0x0E58;
- t['einvertedbreve'] = 0x0207;
- t['eiotifiedcyrillic'] = 0x0465;
- t['ekatakana'] = 0x30A8;
- t['ekatakanahalfwidth'] = 0xFF74;
- t['ekonkargurmukhi'] = 0x0A74;
- t['ekorean'] = 0x3154;
- t['elcyrillic'] = 0x043B;
- t['element'] = 0x2208;
- t['elevencircle'] = 0x246A;
- t['elevenparen'] = 0x247E;
- t['elevenperiod'] = 0x2492;
- t['elevenroman'] = 0x217A;
- t['ellipsis'] = 0x2026;
- t['ellipsisvertical'] = 0x22EE;
- t['emacron'] = 0x0113;
- t['emacronacute'] = 0x1E17;
- t['emacrongrave'] = 0x1E15;
- t['emcyrillic'] = 0x043C;
- t['emdash'] = 0x2014;
- t['emdashvertical'] = 0xFE31;
- t['emonospace'] = 0xFF45;
- t['emphasismarkarmenian'] = 0x055B;
- t['emptyset'] = 0x2205;
- t['enbopomofo'] = 0x3123;
- t['encyrillic'] = 0x043D;
- t['endash'] = 0x2013;
- t['endashvertical'] = 0xFE32;
- t['endescendercyrillic'] = 0x04A3;
- t['eng'] = 0x014B;
- t['engbopomofo'] = 0x3125;
- t['enghecyrillic'] = 0x04A5;
- t['enhookcyrillic'] = 0x04C8;
- t['enspace'] = 0x2002;
- t['eogonek'] = 0x0119;
- t['eokorean'] = 0x3153;
- t['eopen'] = 0x025B;
- t['eopenclosed'] = 0x029A;
- t['eopenreversed'] = 0x025C;
- t['eopenreversedclosed'] = 0x025E;
- t['eopenreversedhook'] = 0x025D;
- t['eparen'] = 0x24A0;
- t['epsilon'] = 0x03B5;
- t['epsilontonos'] = 0x03AD;
- t['equal'] = 0x003D;
- t['equalmonospace'] = 0xFF1D;
- t['equalsmall'] = 0xFE66;
- t['equalsuperior'] = 0x207C;
- t['equivalence'] = 0x2261;
- t['erbopomofo'] = 0x3126;
- t['ercyrillic'] = 0x0440;
- t['ereversed'] = 0x0258;
- t['ereversedcyrillic'] = 0x044D;
- t['escyrillic'] = 0x0441;
- t['esdescendercyrillic'] = 0x04AB;
- t['esh'] = 0x0283;
- t['eshcurl'] = 0x0286;
- t['eshortdeva'] = 0x090E;
- t['eshortvowelsigndeva'] = 0x0946;
- t['eshreversedloop'] = 0x01AA;
- t['eshsquatreversed'] = 0x0285;
- t['esmallhiragana'] = 0x3047;
- t['esmallkatakana'] = 0x30A7;
- t['esmallkatakanahalfwidth'] = 0xFF6A;
- t['estimated'] = 0x212E;
- t['esuperior'] = 0xF6EC;
- t['eta'] = 0x03B7;
- t['etarmenian'] = 0x0568;
- t['etatonos'] = 0x03AE;
- t['eth'] = 0x00F0;
- t['etilde'] = 0x1EBD;
- t['etildebelow'] = 0x1E1B;
- t['etnahtafoukhhebrew'] = 0x0591;
- t['etnahtafoukhlefthebrew'] = 0x0591;
- t['etnahtahebrew'] = 0x0591;
- t['etnahtalefthebrew'] = 0x0591;
- t['eturned'] = 0x01DD;
- t['eukorean'] = 0x3161;
- t['euro'] = 0x20AC;
- t['evowelsignbengali'] = 0x09C7;
- t['evowelsigndeva'] = 0x0947;
- t['evowelsigngujarati'] = 0x0AC7;
- t['exclam'] = 0x0021;
- t['exclamarmenian'] = 0x055C;
- t['exclamdbl'] = 0x203C;
- t['exclamdown'] = 0x00A1;
- t['exclamdownsmall'] = 0xF7A1;
- t['exclammonospace'] = 0xFF01;
- t['exclamsmall'] = 0xF721;
- t['existential'] = 0x2203;
- t['ezh'] = 0x0292;
- t['ezhcaron'] = 0x01EF;
- t['ezhcurl'] = 0x0293;
- t['ezhreversed'] = 0x01B9;
- t['ezhtail'] = 0x01BA;
- t['f'] = 0x0066;
- t['fadeva'] = 0x095E;
- t['fagurmukhi'] = 0x0A5E;
- t['fahrenheit'] = 0x2109;
- t['fathaarabic'] = 0x064E;
- t['fathalowarabic'] = 0x064E;
- t['fathatanarabic'] = 0x064B;
- t['fbopomofo'] = 0x3108;
- t['fcircle'] = 0x24D5;
- t['fdotaccent'] = 0x1E1F;
- t['feharabic'] = 0x0641;
- t['feharmenian'] = 0x0586;
- t['fehfinalarabic'] = 0xFED2;
- t['fehinitialarabic'] = 0xFED3;
- t['fehmedialarabic'] = 0xFED4;
- t['feicoptic'] = 0x03E5;
- t['female'] = 0x2640;
- t['ff'] = 0xFB00;
- t['ffi'] = 0xFB03;
- t['ffl'] = 0xFB04;
- t['fi'] = 0xFB01;
- t['fifteencircle'] = 0x246E;
- t['fifteenparen'] = 0x2482;
- t['fifteenperiod'] = 0x2496;
- t['figuredash'] = 0x2012;
- t['filledbox'] = 0x25A0;
- t['filledrect'] = 0x25AC;
- t['finalkaf'] = 0x05DA;
- t['finalkafdagesh'] = 0xFB3A;
- t['finalkafdageshhebrew'] = 0xFB3A;
- t['finalkafhebrew'] = 0x05DA;
- t['finalmem'] = 0x05DD;
- t['finalmemhebrew'] = 0x05DD;
- t['finalnun'] = 0x05DF;
- t['finalnunhebrew'] = 0x05DF;
- t['finalpe'] = 0x05E3;
- t['finalpehebrew'] = 0x05E3;
- t['finaltsadi'] = 0x05E5;
- t['finaltsadihebrew'] = 0x05E5;
- t['firsttonechinese'] = 0x02C9;
- t['fisheye'] = 0x25C9;
- t['fitacyrillic'] = 0x0473;
- t['five'] = 0x0035;
- t['fivearabic'] = 0x0665;
- t['fivebengali'] = 0x09EB;
- t['fivecircle'] = 0x2464;
- t['fivecircleinversesansserif'] = 0x278E;
- t['fivedeva'] = 0x096B;
- t['fiveeighths'] = 0x215D;
- t['fivegujarati'] = 0x0AEB;
- t['fivegurmukhi'] = 0x0A6B;
- t['fivehackarabic'] = 0x0665;
- t['fivehangzhou'] = 0x3025;
- t['fiveideographicparen'] = 0x3224;
- t['fiveinferior'] = 0x2085;
- t['fivemonospace'] = 0xFF15;
- t['fiveoldstyle'] = 0xF735;
- t['fiveparen'] = 0x2478;
- t['fiveperiod'] = 0x248C;
- t['fivepersian'] = 0x06F5;
- t['fiveroman'] = 0x2174;
- t['fivesuperior'] = 0x2075;
- t['fivethai'] = 0x0E55;
- t['fl'] = 0xFB02;
- t['florin'] = 0x0192;
- t['fmonospace'] = 0xFF46;
- t['fmsquare'] = 0x3399;
- t['fofanthai'] = 0x0E1F;
- t['fofathai'] = 0x0E1D;
- t['fongmanthai'] = 0x0E4F;
- t['forall'] = 0x2200;
- t['four'] = 0x0034;
- t['fourarabic'] = 0x0664;
- t['fourbengali'] = 0x09EA;
- t['fourcircle'] = 0x2463;
- t['fourcircleinversesansserif'] = 0x278D;
- t['fourdeva'] = 0x096A;
- t['fourgujarati'] = 0x0AEA;
- t['fourgurmukhi'] = 0x0A6A;
- t['fourhackarabic'] = 0x0664;
- t['fourhangzhou'] = 0x3024;
- t['fourideographicparen'] = 0x3223;
- t['fourinferior'] = 0x2084;
- t['fourmonospace'] = 0xFF14;
- t['fournumeratorbengali'] = 0x09F7;
- t['fouroldstyle'] = 0xF734;
- t['fourparen'] = 0x2477;
- t['fourperiod'] = 0x248B;
- t['fourpersian'] = 0x06F4;
- t['fourroman'] = 0x2173;
- t['foursuperior'] = 0x2074;
- t['fourteencircle'] = 0x246D;
- t['fourteenparen'] = 0x2481;
- t['fourteenperiod'] = 0x2495;
- t['fourthai'] = 0x0E54;
- t['fourthtonechinese'] = 0x02CB;
- t['fparen'] = 0x24A1;
- t['fraction'] = 0x2044;
- t['franc'] = 0x20A3;
- t['g'] = 0x0067;
- t['gabengali'] = 0x0997;
- t['gacute'] = 0x01F5;
- t['gadeva'] = 0x0917;
- t['gafarabic'] = 0x06AF;
- t['gaffinalarabic'] = 0xFB93;
- t['gafinitialarabic'] = 0xFB94;
- t['gafmedialarabic'] = 0xFB95;
- t['gagujarati'] = 0x0A97;
- t['gagurmukhi'] = 0x0A17;
- t['gahiragana'] = 0x304C;
- t['gakatakana'] = 0x30AC;
- t['gamma'] = 0x03B3;
- t['gammalatinsmall'] = 0x0263;
- t['gammasuperior'] = 0x02E0;
- t['gangiacoptic'] = 0x03EB;
- t['gbopomofo'] = 0x310D;
- t['gbreve'] = 0x011F;
- t['gcaron'] = 0x01E7;
- t['gcedilla'] = 0x0123;
- t['gcircle'] = 0x24D6;
- t['gcircumflex'] = 0x011D;
- t['gcommaaccent'] = 0x0123;
- t['gdot'] = 0x0121;
- t['gdotaccent'] = 0x0121;
- t['gecyrillic'] = 0x0433;
- t['gehiragana'] = 0x3052;
- t['gekatakana'] = 0x30B2;
- t['geometricallyequal'] = 0x2251;
- t['gereshaccenthebrew'] = 0x059C;
- t['gereshhebrew'] = 0x05F3;
- t['gereshmuqdamhebrew'] = 0x059D;
- t['germandbls'] = 0x00DF;
- t['gershayimaccenthebrew'] = 0x059E;
- t['gershayimhebrew'] = 0x05F4;
- t['getamark'] = 0x3013;
- t['ghabengali'] = 0x0998;
- t['ghadarmenian'] = 0x0572;
- t['ghadeva'] = 0x0918;
- t['ghagujarati'] = 0x0A98;
- t['ghagurmukhi'] = 0x0A18;
- t['ghainarabic'] = 0x063A;
- t['ghainfinalarabic'] = 0xFECE;
- t['ghaininitialarabic'] = 0xFECF;
- t['ghainmedialarabic'] = 0xFED0;
- t['ghemiddlehookcyrillic'] = 0x0495;
- t['ghestrokecyrillic'] = 0x0493;
- t['gheupturncyrillic'] = 0x0491;
- t['ghhadeva'] = 0x095A;
- t['ghhagurmukhi'] = 0x0A5A;
- t['ghook'] = 0x0260;
- t['ghzsquare'] = 0x3393;
- t['gihiragana'] = 0x304E;
- t['gikatakana'] = 0x30AE;
- t['gimarmenian'] = 0x0563;
- t['gimel'] = 0x05D2;
- t['gimeldagesh'] = 0xFB32;
- t['gimeldageshhebrew'] = 0xFB32;
- t['gimelhebrew'] = 0x05D2;
- t['gjecyrillic'] = 0x0453;
- t['glottalinvertedstroke'] = 0x01BE;
- t['glottalstop'] = 0x0294;
- t['glottalstopinverted'] = 0x0296;
- t['glottalstopmod'] = 0x02C0;
- t['glottalstopreversed'] = 0x0295;
- t['glottalstopreversedmod'] = 0x02C1;
- t['glottalstopreversedsuperior'] = 0x02E4;
- t['glottalstopstroke'] = 0x02A1;
- t['glottalstopstrokereversed'] = 0x02A2;
- t['gmacron'] = 0x1E21;
- t['gmonospace'] = 0xFF47;
- t['gohiragana'] = 0x3054;
- t['gokatakana'] = 0x30B4;
- t['gparen'] = 0x24A2;
- t['gpasquare'] = 0x33AC;
- t['gradient'] = 0x2207;
- t['grave'] = 0x0060;
- t['gravebelowcmb'] = 0x0316;
- t['gravecmb'] = 0x0300;
- t['gravecomb'] = 0x0300;
- t['gravedeva'] = 0x0953;
- t['gravelowmod'] = 0x02CE;
- t['gravemonospace'] = 0xFF40;
- t['gravetonecmb'] = 0x0340;
- t['greater'] = 0x003E;
- t['greaterequal'] = 0x2265;
- t['greaterequalorless'] = 0x22DB;
- t['greatermonospace'] = 0xFF1E;
- t['greaterorequivalent'] = 0x2273;
- t['greaterorless'] = 0x2277;
- t['greateroverequal'] = 0x2267;
- t['greatersmall'] = 0xFE65;
- t['gscript'] = 0x0261;
- t['gstroke'] = 0x01E5;
- t['guhiragana'] = 0x3050;
- t['guillemotleft'] = 0x00AB;
- t['guillemotright'] = 0x00BB;
- t['guilsinglleft'] = 0x2039;
- t['guilsinglright'] = 0x203A;
- t['gukatakana'] = 0x30B0;
- t['guramusquare'] = 0x3318;
- t['gysquare'] = 0x33C9;
- t['h'] = 0x0068;
- t['haabkhasiancyrillic'] = 0x04A9;
- t['haaltonearabic'] = 0x06C1;
- t['habengali'] = 0x09B9;
- t['hadescendercyrillic'] = 0x04B3;
- t['hadeva'] = 0x0939;
- t['hagujarati'] = 0x0AB9;
- t['hagurmukhi'] = 0x0A39;
- t['haharabic'] = 0x062D;
- t['hahfinalarabic'] = 0xFEA2;
- t['hahinitialarabic'] = 0xFEA3;
- t['hahiragana'] = 0x306F;
- t['hahmedialarabic'] = 0xFEA4;
- t['haitusquare'] = 0x332A;
- t['hakatakana'] = 0x30CF;
- t['hakatakanahalfwidth'] = 0xFF8A;
- t['halantgurmukhi'] = 0x0A4D;
- t['hamzaarabic'] = 0x0621;
- t['hamzalowarabic'] = 0x0621;
- t['hangulfiller'] = 0x3164;
- t['hardsigncyrillic'] = 0x044A;
- t['harpoonleftbarbup'] = 0x21BC;
- t['harpoonrightbarbup'] = 0x21C0;
- t['hasquare'] = 0x33CA;
- t['hatafpatah'] = 0x05B2;
- t['hatafpatah16'] = 0x05B2;
- t['hatafpatah23'] = 0x05B2;
- t['hatafpatah2f'] = 0x05B2;
- t['hatafpatahhebrew'] = 0x05B2;
- t['hatafpatahnarrowhebrew'] = 0x05B2;
- t['hatafpatahquarterhebrew'] = 0x05B2;
- t['hatafpatahwidehebrew'] = 0x05B2;
- t['hatafqamats'] = 0x05B3;
- t['hatafqamats1b'] = 0x05B3;
- t['hatafqamats28'] = 0x05B3;
- t['hatafqamats34'] = 0x05B3;
- t['hatafqamatshebrew'] = 0x05B3;
- t['hatafqamatsnarrowhebrew'] = 0x05B3;
- t['hatafqamatsquarterhebrew'] = 0x05B3;
- t['hatafqamatswidehebrew'] = 0x05B3;
- t['hatafsegol'] = 0x05B1;
- t['hatafsegol17'] = 0x05B1;
- t['hatafsegol24'] = 0x05B1;
- t['hatafsegol30'] = 0x05B1;
- t['hatafsegolhebrew'] = 0x05B1;
- t['hatafsegolnarrowhebrew'] = 0x05B1;
- t['hatafsegolquarterhebrew'] = 0x05B1;
- t['hatafsegolwidehebrew'] = 0x05B1;
- t['hbar'] = 0x0127;
- t['hbopomofo'] = 0x310F;
- t['hbrevebelow'] = 0x1E2B;
- t['hcedilla'] = 0x1E29;
- t['hcircle'] = 0x24D7;
- t['hcircumflex'] = 0x0125;
- t['hdieresis'] = 0x1E27;
- t['hdotaccent'] = 0x1E23;
- t['hdotbelow'] = 0x1E25;
- t['he'] = 0x05D4;
- t['heart'] = 0x2665;
- t['heartsuitblack'] = 0x2665;
- t['heartsuitwhite'] = 0x2661;
- t['hedagesh'] = 0xFB34;
- t['hedageshhebrew'] = 0xFB34;
- t['hehaltonearabic'] = 0x06C1;
- t['heharabic'] = 0x0647;
- t['hehebrew'] = 0x05D4;
- t['hehfinalaltonearabic'] = 0xFBA7;
- t['hehfinalalttwoarabic'] = 0xFEEA;
- t['hehfinalarabic'] = 0xFEEA;
- t['hehhamzaabovefinalarabic'] = 0xFBA5;
- t['hehhamzaaboveisolatedarabic'] = 0xFBA4;
- t['hehinitialaltonearabic'] = 0xFBA8;
- t['hehinitialarabic'] = 0xFEEB;
- t['hehiragana'] = 0x3078;
- t['hehmedialaltonearabic'] = 0xFBA9;
- t['hehmedialarabic'] = 0xFEEC;
- t['heiseierasquare'] = 0x337B;
- t['hekatakana'] = 0x30D8;
- t['hekatakanahalfwidth'] = 0xFF8D;
- t['hekutaarusquare'] = 0x3336;
- t['henghook'] = 0x0267;
- t['herutusquare'] = 0x3339;
- t['het'] = 0x05D7;
- t['hethebrew'] = 0x05D7;
- t['hhook'] = 0x0266;
- t['hhooksuperior'] = 0x02B1;
- t['hieuhacirclekorean'] = 0x327B;
- t['hieuhaparenkorean'] = 0x321B;
- t['hieuhcirclekorean'] = 0x326D;
- t['hieuhkorean'] = 0x314E;
- t['hieuhparenkorean'] = 0x320D;
- t['hihiragana'] = 0x3072;
- t['hikatakana'] = 0x30D2;
- t['hikatakanahalfwidth'] = 0xFF8B;
- t['hiriq'] = 0x05B4;
- t['hiriq14'] = 0x05B4;
- t['hiriq21'] = 0x05B4;
- t['hiriq2d'] = 0x05B4;
- t['hiriqhebrew'] = 0x05B4;
- t['hiriqnarrowhebrew'] = 0x05B4;
- t['hiriqquarterhebrew'] = 0x05B4;
- t['hiriqwidehebrew'] = 0x05B4;
- t['hlinebelow'] = 0x1E96;
- t['hmonospace'] = 0xFF48;
- t['hoarmenian'] = 0x0570;
- t['hohipthai'] = 0x0E2B;
- t['hohiragana'] = 0x307B;
- t['hokatakana'] = 0x30DB;
- t['hokatakanahalfwidth'] = 0xFF8E;
- t['holam'] = 0x05B9;
- t['holam19'] = 0x05B9;
- t['holam26'] = 0x05B9;
- t['holam32'] = 0x05B9;
- t['holamhebrew'] = 0x05B9;
- t['holamnarrowhebrew'] = 0x05B9;
- t['holamquarterhebrew'] = 0x05B9;
- t['holamwidehebrew'] = 0x05B9;
- t['honokhukthai'] = 0x0E2E;
- t['hookabovecomb'] = 0x0309;
- t['hookcmb'] = 0x0309;
- t['hookpalatalizedbelowcmb'] = 0x0321;
- t['hookretroflexbelowcmb'] = 0x0322;
- t['hoonsquare'] = 0x3342;
- t['horicoptic'] = 0x03E9;
- t['horizontalbar'] = 0x2015;
- t['horncmb'] = 0x031B;
- t['hotsprings'] = 0x2668;
- t['house'] = 0x2302;
- t['hparen'] = 0x24A3;
- t['hsuperior'] = 0x02B0;
- t['hturned'] = 0x0265;
- t['huhiragana'] = 0x3075;
- t['huiitosquare'] = 0x3333;
- t['hukatakana'] = 0x30D5;
- t['hukatakanahalfwidth'] = 0xFF8C;
- t['hungarumlaut'] = 0x02DD;
- t['hungarumlautcmb'] = 0x030B;
- t['hv'] = 0x0195;
- t['hyphen'] = 0x002D;
- t['hypheninferior'] = 0xF6E5;
- t['hyphenmonospace'] = 0xFF0D;
- t['hyphensmall'] = 0xFE63;
- t['hyphensuperior'] = 0xF6E6;
- t['hyphentwo'] = 0x2010;
- t['i'] = 0x0069;
- t['iacute'] = 0x00ED;
- t['iacyrillic'] = 0x044F;
- t['ibengali'] = 0x0987;
- t['ibopomofo'] = 0x3127;
- t['ibreve'] = 0x012D;
- t['icaron'] = 0x01D0;
- t['icircle'] = 0x24D8;
- t['icircumflex'] = 0x00EE;
- t['icyrillic'] = 0x0456;
- t['idblgrave'] = 0x0209;
- t['ideographearthcircle'] = 0x328F;
- t['ideographfirecircle'] = 0x328B;
- t['ideographicallianceparen'] = 0x323F;
- t['ideographiccallparen'] = 0x323A;
- t['ideographiccentrecircle'] = 0x32A5;
- t['ideographicclose'] = 0x3006;
- t['ideographiccomma'] = 0x3001;
- t['ideographiccommaleft'] = 0xFF64;
- t['ideographiccongratulationparen'] = 0x3237;
- t['ideographiccorrectcircle'] = 0x32A3;
- t['ideographicearthparen'] = 0x322F;
- t['ideographicenterpriseparen'] = 0x323D;
- t['ideographicexcellentcircle'] = 0x329D;
- t['ideographicfestivalparen'] = 0x3240;
- t['ideographicfinancialcircle'] = 0x3296;
- t['ideographicfinancialparen'] = 0x3236;
- t['ideographicfireparen'] = 0x322B;
- t['ideographichaveparen'] = 0x3232;
- t['ideographichighcircle'] = 0x32A4;
- t['ideographiciterationmark'] = 0x3005;
- t['ideographiclaborcircle'] = 0x3298;
- t['ideographiclaborparen'] = 0x3238;
- t['ideographicleftcircle'] = 0x32A7;
- t['ideographiclowcircle'] = 0x32A6;
- t['ideographicmedicinecircle'] = 0x32A9;
- t['ideographicmetalparen'] = 0x322E;
- t['ideographicmoonparen'] = 0x322A;
- t['ideographicnameparen'] = 0x3234;
- t['ideographicperiod'] = 0x3002;
- t['ideographicprintcircle'] = 0x329E;
- t['ideographicreachparen'] = 0x3243;
- t['ideographicrepresentparen'] = 0x3239;
- t['ideographicresourceparen'] = 0x323E;
- t['ideographicrightcircle'] = 0x32A8;
- t['ideographicsecretcircle'] = 0x3299;
- t['ideographicselfparen'] = 0x3242;
- t['ideographicsocietyparen'] = 0x3233;
- t['ideographicspace'] = 0x3000;
- t['ideographicspecialparen'] = 0x3235;
- t['ideographicstockparen'] = 0x3231;
- t['ideographicstudyparen'] = 0x323B;
- t['ideographicsunparen'] = 0x3230;
- t['ideographicsuperviseparen'] = 0x323C;
- t['ideographicwaterparen'] = 0x322C;
- t['ideographicwoodparen'] = 0x322D;
- t['ideographiczero'] = 0x3007;
- t['ideographmetalcircle'] = 0x328E;
- t['ideographmooncircle'] = 0x328A;
- t['ideographnamecircle'] = 0x3294;
- t['ideographsuncircle'] = 0x3290;
- t['ideographwatercircle'] = 0x328C;
- t['ideographwoodcircle'] = 0x328D;
- t['ideva'] = 0x0907;
- t['idieresis'] = 0x00EF;
- t['idieresisacute'] = 0x1E2F;
- t['idieresiscyrillic'] = 0x04E5;
- t['idotbelow'] = 0x1ECB;
- t['iebrevecyrillic'] = 0x04D7;
- t['iecyrillic'] = 0x0435;
- t['ieungacirclekorean'] = 0x3275;
- t['ieungaparenkorean'] = 0x3215;
- t['ieungcirclekorean'] = 0x3267;
- t['ieungkorean'] = 0x3147;
- t['ieungparenkorean'] = 0x3207;
- t['igrave'] = 0x00EC;
- t['igujarati'] = 0x0A87;
- t['igurmukhi'] = 0x0A07;
- t['ihiragana'] = 0x3044;
- t['ihookabove'] = 0x1EC9;
- t['iibengali'] = 0x0988;
- t['iicyrillic'] = 0x0438;
- t['iideva'] = 0x0908;
- t['iigujarati'] = 0x0A88;
- t['iigurmukhi'] = 0x0A08;
- t['iimatragurmukhi'] = 0x0A40;
- t['iinvertedbreve'] = 0x020B;
- t['iishortcyrillic'] = 0x0439;
- t['iivowelsignbengali'] = 0x09C0;
- t['iivowelsigndeva'] = 0x0940;
- t['iivowelsigngujarati'] = 0x0AC0;
- t['ij'] = 0x0133;
- t['ikatakana'] = 0x30A4;
- t['ikatakanahalfwidth'] = 0xFF72;
- t['ikorean'] = 0x3163;
- t['ilde'] = 0x02DC;
- t['iluyhebrew'] = 0x05AC;
- t['imacron'] = 0x012B;
- t['imacroncyrillic'] = 0x04E3;
- t['imageorapproximatelyequal'] = 0x2253;
- t['imatragurmukhi'] = 0x0A3F;
- t['imonospace'] = 0xFF49;
- t['increment'] = 0x2206;
- t['infinity'] = 0x221E;
- t['iniarmenian'] = 0x056B;
- t['integral'] = 0x222B;
- t['integralbottom'] = 0x2321;
- t['integralbt'] = 0x2321;
- t['integralex'] = 0xF8F5;
- t['integraltop'] = 0x2320;
- t['integraltp'] = 0x2320;
- t['intersection'] = 0x2229;
- t['intisquare'] = 0x3305;
- t['invbullet'] = 0x25D8;
- t['invcircle'] = 0x25D9;
- t['invsmileface'] = 0x263B;
- t['iocyrillic'] = 0x0451;
- t['iogonek'] = 0x012F;
- t['iota'] = 0x03B9;
- t['iotadieresis'] = 0x03CA;
- t['iotadieresistonos'] = 0x0390;
- t['iotalatin'] = 0x0269;
- t['iotatonos'] = 0x03AF;
- t['iparen'] = 0x24A4;
- t['irigurmukhi'] = 0x0A72;
- t['ismallhiragana'] = 0x3043;
- t['ismallkatakana'] = 0x30A3;
- t['ismallkatakanahalfwidth'] = 0xFF68;
- t['issharbengali'] = 0x09FA;
- t['istroke'] = 0x0268;
- t['isuperior'] = 0xF6ED;
- t['iterationhiragana'] = 0x309D;
- t['iterationkatakana'] = 0x30FD;
- t['itilde'] = 0x0129;
- t['itildebelow'] = 0x1E2D;
- t['iubopomofo'] = 0x3129;
- t['iucyrillic'] = 0x044E;
- t['ivowelsignbengali'] = 0x09BF;
- t['ivowelsigndeva'] = 0x093F;
- t['ivowelsigngujarati'] = 0x0ABF;
- t['izhitsacyrillic'] = 0x0475;
- t['izhitsadblgravecyrillic'] = 0x0477;
- t['j'] = 0x006A;
- t['jaarmenian'] = 0x0571;
- t['jabengali'] = 0x099C;
- t['jadeva'] = 0x091C;
- t['jagujarati'] = 0x0A9C;
- t['jagurmukhi'] = 0x0A1C;
- t['jbopomofo'] = 0x3110;
- t['jcaron'] = 0x01F0;
- t['jcircle'] = 0x24D9;
- t['jcircumflex'] = 0x0135;
- t['jcrossedtail'] = 0x029D;
- t['jdotlessstroke'] = 0x025F;
- t['jecyrillic'] = 0x0458;
- t['jeemarabic'] = 0x062C;
- t['jeemfinalarabic'] = 0xFE9E;
- t['jeeminitialarabic'] = 0xFE9F;
- t['jeemmedialarabic'] = 0xFEA0;
- t['jeharabic'] = 0x0698;
- t['jehfinalarabic'] = 0xFB8B;
- t['jhabengali'] = 0x099D;
- t['jhadeva'] = 0x091D;
- t['jhagujarati'] = 0x0A9D;
- t['jhagurmukhi'] = 0x0A1D;
- t['jheharmenian'] = 0x057B;
- t['jis'] = 0x3004;
- t['jmonospace'] = 0xFF4A;
- t['jparen'] = 0x24A5;
- t['jsuperior'] = 0x02B2;
- t['k'] = 0x006B;
- t['kabashkircyrillic'] = 0x04A1;
- t['kabengali'] = 0x0995;
- t['kacute'] = 0x1E31;
- t['kacyrillic'] = 0x043A;
- t['kadescendercyrillic'] = 0x049B;
- t['kadeva'] = 0x0915;
- t['kaf'] = 0x05DB;
- t['kafarabic'] = 0x0643;
- t['kafdagesh'] = 0xFB3B;
- t['kafdageshhebrew'] = 0xFB3B;
- t['kaffinalarabic'] = 0xFEDA;
- t['kafhebrew'] = 0x05DB;
- t['kafinitialarabic'] = 0xFEDB;
- t['kafmedialarabic'] = 0xFEDC;
- t['kafrafehebrew'] = 0xFB4D;
- t['kagujarati'] = 0x0A95;
- t['kagurmukhi'] = 0x0A15;
- t['kahiragana'] = 0x304B;
- t['kahookcyrillic'] = 0x04C4;
- t['kakatakana'] = 0x30AB;
- t['kakatakanahalfwidth'] = 0xFF76;
- t['kappa'] = 0x03BA;
- t['kappasymbolgreek'] = 0x03F0;
- t['kapyeounmieumkorean'] = 0x3171;
- t['kapyeounphieuphkorean'] = 0x3184;
- t['kapyeounpieupkorean'] = 0x3178;
- t['kapyeounssangpieupkorean'] = 0x3179;
- t['karoriisquare'] = 0x330D;
- t['kashidaautoarabic'] = 0x0640;
- t['kashidaautonosidebearingarabic'] = 0x0640;
- t['kasmallkatakana'] = 0x30F5;
- t['kasquare'] = 0x3384;
- t['kasraarabic'] = 0x0650;
- t['kasratanarabic'] = 0x064D;
- t['kastrokecyrillic'] = 0x049F;
- t['katahiraprolongmarkhalfwidth'] = 0xFF70;
- t['kaverticalstrokecyrillic'] = 0x049D;
- t['kbopomofo'] = 0x310E;
- t['kcalsquare'] = 0x3389;
- t['kcaron'] = 0x01E9;
- t['kcedilla'] = 0x0137;
- t['kcircle'] = 0x24DA;
- t['kcommaaccent'] = 0x0137;
- t['kdotbelow'] = 0x1E33;
- t['keharmenian'] = 0x0584;
- t['kehiragana'] = 0x3051;
- t['kekatakana'] = 0x30B1;
- t['kekatakanahalfwidth'] = 0xFF79;
- t['kenarmenian'] = 0x056F;
- t['kesmallkatakana'] = 0x30F6;
- t['kgreenlandic'] = 0x0138;
- t['khabengali'] = 0x0996;
- t['khacyrillic'] = 0x0445;
- t['khadeva'] = 0x0916;
- t['khagujarati'] = 0x0A96;
- t['khagurmukhi'] = 0x0A16;
- t['khaharabic'] = 0x062E;
- t['khahfinalarabic'] = 0xFEA6;
- t['khahinitialarabic'] = 0xFEA7;
- t['khahmedialarabic'] = 0xFEA8;
- t['kheicoptic'] = 0x03E7;
- t['khhadeva'] = 0x0959;
- t['khhagurmukhi'] = 0x0A59;
- t['khieukhacirclekorean'] = 0x3278;
- t['khieukhaparenkorean'] = 0x3218;
- t['khieukhcirclekorean'] = 0x326A;
- t['khieukhkorean'] = 0x314B;
- t['khieukhparenkorean'] = 0x320A;
- t['khokhaithai'] = 0x0E02;
- t['khokhonthai'] = 0x0E05;
- t['khokhuatthai'] = 0x0E03;
- t['khokhwaithai'] = 0x0E04;
- t['khomutthai'] = 0x0E5B;
- t['khook'] = 0x0199;
- t['khorakhangthai'] = 0x0E06;
- t['khzsquare'] = 0x3391;
- t['kihiragana'] = 0x304D;
- t['kikatakana'] = 0x30AD;
- t['kikatakanahalfwidth'] = 0xFF77;
- t['kiroguramusquare'] = 0x3315;
- t['kiromeetorusquare'] = 0x3316;
- t['kirosquare'] = 0x3314;
- t['kiyeokacirclekorean'] = 0x326E;
- t['kiyeokaparenkorean'] = 0x320E;
- t['kiyeokcirclekorean'] = 0x3260;
- t['kiyeokkorean'] = 0x3131;
- t['kiyeokparenkorean'] = 0x3200;
- t['kiyeoksioskorean'] = 0x3133;
- t['kjecyrillic'] = 0x045C;
- t['klinebelow'] = 0x1E35;
- t['klsquare'] = 0x3398;
- t['kmcubedsquare'] = 0x33A6;
- t['kmonospace'] = 0xFF4B;
- t['kmsquaredsquare'] = 0x33A2;
- t['kohiragana'] = 0x3053;
- t['kohmsquare'] = 0x33C0;
- t['kokaithai'] = 0x0E01;
- t['kokatakana'] = 0x30B3;
- t['kokatakanahalfwidth'] = 0xFF7A;
- t['kooposquare'] = 0x331E;
- t['koppacyrillic'] = 0x0481;
- t['koreanstandardsymbol'] = 0x327F;
- t['koroniscmb'] = 0x0343;
- t['kparen'] = 0x24A6;
- t['kpasquare'] = 0x33AA;
- t['ksicyrillic'] = 0x046F;
- t['ktsquare'] = 0x33CF;
- t['kturned'] = 0x029E;
- t['kuhiragana'] = 0x304F;
- t['kukatakana'] = 0x30AF;
- t['kukatakanahalfwidth'] = 0xFF78;
- t['kvsquare'] = 0x33B8;
- t['kwsquare'] = 0x33BE;
- t['l'] = 0x006C;
- t['labengali'] = 0x09B2;
- t['lacute'] = 0x013A;
- t['ladeva'] = 0x0932;
- t['lagujarati'] = 0x0AB2;
- t['lagurmukhi'] = 0x0A32;
- t['lakkhangyaothai'] = 0x0E45;
- t['lamaleffinalarabic'] = 0xFEFC;
- t['lamalefhamzaabovefinalarabic'] = 0xFEF8;
- t['lamalefhamzaaboveisolatedarabic'] = 0xFEF7;
- t['lamalefhamzabelowfinalarabic'] = 0xFEFA;
- t['lamalefhamzabelowisolatedarabic'] = 0xFEF9;
- t['lamalefisolatedarabic'] = 0xFEFB;
- t['lamalefmaddaabovefinalarabic'] = 0xFEF6;
- t['lamalefmaddaaboveisolatedarabic'] = 0xFEF5;
- t['lamarabic'] = 0x0644;
- t['lambda'] = 0x03BB;
- t['lambdastroke'] = 0x019B;
- t['lamed'] = 0x05DC;
- t['lameddagesh'] = 0xFB3C;
- t['lameddageshhebrew'] = 0xFB3C;
- t['lamedhebrew'] = 0x05DC;
- t['lamfinalarabic'] = 0xFEDE;
- t['lamhahinitialarabic'] = 0xFCCA;
- t['laminitialarabic'] = 0xFEDF;
- t['lamjeeminitialarabic'] = 0xFCC9;
- t['lamkhahinitialarabic'] = 0xFCCB;
- t['lamlamhehisolatedarabic'] = 0xFDF2;
- t['lammedialarabic'] = 0xFEE0;
- t['lammeemhahinitialarabic'] = 0xFD88;
- t['lammeeminitialarabic'] = 0xFCCC;
- t['largecircle'] = 0x25EF;
- t['lbar'] = 0x019A;
- t['lbelt'] = 0x026C;
- t['lbopomofo'] = 0x310C;
- t['lcaron'] = 0x013E;
- t['lcedilla'] = 0x013C;
- t['lcircle'] = 0x24DB;
- t['lcircumflexbelow'] = 0x1E3D;
- t['lcommaaccent'] = 0x013C;
- t['ldot'] = 0x0140;
- t['ldotaccent'] = 0x0140;
- t['ldotbelow'] = 0x1E37;
- t['ldotbelowmacron'] = 0x1E39;
- t['leftangleabovecmb'] = 0x031A;
- t['lefttackbelowcmb'] = 0x0318;
- t['less'] = 0x003C;
- t['lessequal'] = 0x2264;
- t['lessequalorgreater'] = 0x22DA;
- t['lessmonospace'] = 0xFF1C;
- t['lessorequivalent'] = 0x2272;
- t['lessorgreater'] = 0x2276;
- t['lessoverequal'] = 0x2266;
- t['lesssmall'] = 0xFE64;
- t['lezh'] = 0x026E;
- t['lfblock'] = 0x258C;
- t['lhookretroflex'] = 0x026D;
- t['lira'] = 0x20A4;
- t['liwnarmenian'] = 0x056C;
- t['lj'] = 0x01C9;
- t['ljecyrillic'] = 0x0459;
- t['ll'] = 0xF6C0;
- t['lladeva'] = 0x0933;
- t['llagujarati'] = 0x0AB3;
- t['llinebelow'] = 0x1E3B;
- t['llladeva'] = 0x0934;
- t['llvocalicbengali'] = 0x09E1;
- t['llvocalicdeva'] = 0x0961;
- t['llvocalicvowelsignbengali'] = 0x09E3;
- t['llvocalicvowelsigndeva'] = 0x0963;
- t['lmiddletilde'] = 0x026B;
- t['lmonospace'] = 0xFF4C;
- t['lmsquare'] = 0x33D0;
- t['lochulathai'] = 0x0E2C;
- t['logicaland'] = 0x2227;
- t['logicalnot'] = 0x00AC;
- t['logicalnotreversed'] = 0x2310;
- t['logicalor'] = 0x2228;
- t['lolingthai'] = 0x0E25;
- t['longs'] = 0x017F;
- t['lowlinecenterline'] = 0xFE4E;
- t['lowlinecmb'] = 0x0332;
- t['lowlinedashed'] = 0xFE4D;
- t['lozenge'] = 0x25CA;
- t['lparen'] = 0x24A7;
- t['lslash'] = 0x0142;
- t['lsquare'] = 0x2113;
- t['lsuperior'] = 0xF6EE;
- t['ltshade'] = 0x2591;
- t['luthai'] = 0x0E26;
- t['lvocalicbengali'] = 0x098C;
- t['lvocalicdeva'] = 0x090C;
- t['lvocalicvowelsignbengali'] = 0x09E2;
- t['lvocalicvowelsigndeva'] = 0x0962;
- t['lxsquare'] = 0x33D3;
- t['m'] = 0x006D;
- t['mabengali'] = 0x09AE;
- t['macron'] = 0x00AF;
- t['macronbelowcmb'] = 0x0331;
- t['macroncmb'] = 0x0304;
- t['macronlowmod'] = 0x02CD;
- t['macronmonospace'] = 0xFFE3;
- t['macute'] = 0x1E3F;
- t['madeva'] = 0x092E;
- t['magujarati'] = 0x0AAE;
- t['magurmukhi'] = 0x0A2E;
- t['mahapakhhebrew'] = 0x05A4;
- t['mahapakhlefthebrew'] = 0x05A4;
- t['mahiragana'] = 0x307E;
- t['maichattawalowleftthai'] = 0xF895;
- t['maichattawalowrightthai'] = 0xF894;
- t['maichattawathai'] = 0x0E4B;
- t['maichattawaupperleftthai'] = 0xF893;
- t['maieklowleftthai'] = 0xF88C;
- t['maieklowrightthai'] = 0xF88B;
- t['maiekthai'] = 0x0E48;
- t['maiekupperleftthai'] = 0xF88A;
- t['maihanakatleftthai'] = 0xF884;
- t['maihanakatthai'] = 0x0E31;
- t['maitaikhuleftthai'] = 0xF889;
- t['maitaikhuthai'] = 0x0E47;
- t['maitholowleftthai'] = 0xF88F;
- t['maitholowrightthai'] = 0xF88E;
- t['maithothai'] = 0x0E49;
- t['maithoupperleftthai'] = 0xF88D;
- t['maitrilowleftthai'] = 0xF892;
- t['maitrilowrightthai'] = 0xF891;
- t['maitrithai'] = 0x0E4A;
- t['maitriupperleftthai'] = 0xF890;
- t['maiyamokthai'] = 0x0E46;
- t['makatakana'] = 0x30DE;
- t['makatakanahalfwidth'] = 0xFF8F;
- t['male'] = 0x2642;
- t['mansyonsquare'] = 0x3347;
- t['maqafhebrew'] = 0x05BE;
- t['mars'] = 0x2642;
- t['masoracirclehebrew'] = 0x05AF;
- t['masquare'] = 0x3383;
- t['mbopomofo'] = 0x3107;
- t['mbsquare'] = 0x33D4;
- t['mcircle'] = 0x24DC;
- t['mcubedsquare'] = 0x33A5;
- t['mdotaccent'] = 0x1E41;
- t['mdotbelow'] = 0x1E43;
- t['meemarabic'] = 0x0645;
- t['meemfinalarabic'] = 0xFEE2;
- t['meeminitialarabic'] = 0xFEE3;
- t['meemmedialarabic'] = 0xFEE4;
- t['meemmeeminitialarabic'] = 0xFCD1;
- t['meemmeemisolatedarabic'] = 0xFC48;
- t['meetorusquare'] = 0x334D;
- t['mehiragana'] = 0x3081;
- t['meizierasquare'] = 0x337E;
- t['mekatakana'] = 0x30E1;
- t['mekatakanahalfwidth'] = 0xFF92;
- t['mem'] = 0x05DE;
- t['memdagesh'] = 0xFB3E;
- t['memdageshhebrew'] = 0xFB3E;
- t['memhebrew'] = 0x05DE;
- t['menarmenian'] = 0x0574;
- t['merkhahebrew'] = 0x05A5;
- t['merkhakefulahebrew'] = 0x05A6;
- t['merkhakefulalefthebrew'] = 0x05A6;
- t['merkhalefthebrew'] = 0x05A5;
- t['mhook'] = 0x0271;
- t['mhzsquare'] = 0x3392;
- t['middledotkatakanahalfwidth'] = 0xFF65;
- t['middot'] = 0x00B7;
- t['mieumacirclekorean'] = 0x3272;
- t['mieumaparenkorean'] = 0x3212;
- t['mieumcirclekorean'] = 0x3264;
- t['mieumkorean'] = 0x3141;
- t['mieumpansioskorean'] = 0x3170;
- t['mieumparenkorean'] = 0x3204;
- t['mieumpieupkorean'] = 0x316E;
- t['mieumsioskorean'] = 0x316F;
- t['mihiragana'] = 0x307F;
- t['mikatakana'] = 0x30DF;
- t['mikatakanahalfwidth'] = 0xFF90;
- t['minus'] = 0x2212;
- t['minusbelowcmb'] = 0x0320;
- t['minuscircle'] = 0x2296;
- t['minusmod'] = 0x02D7;
- t['minusplus'] = 0x2213;
- t['minute'] = 0x2032;
- t['miribaarusquare'] = 0x334A;
- t['mirisquare'] = 0x3349;
- t['mlonglegturned'] = 0x0270;
- t['mlsquare'] = 0x3396;
- t['mmcubedsquare'] = 0x33A3;
- t['mmonospace'] = 0xFF4D;
- t['mmsquaredsquare'] = 0x339F;
- t['mohiragana'] = 0x3082;
- t['mohmsquare'] = 0x33C1;
- t['mokatakana'] = 0x30E2;
- t['mokatakanahalfwidth'] = 0xFF93;
- t['molsquare'] = 0x33D6;
- t['momathai'] = 0x0E21;
- t['moverssquare'] = 0x33A7;
- t['moverssquaredsquare'] = 0x33A8;
- t['mparen'] = 0x24A8;
- t['mpasquare'] = 0x33AB;
- t['mssquare'] = 0x33B3;
- t['msuperior'] = 0xF6EF;
- t['mturned'] = 0x026F;
- t['mu'] = 0x00B5;
- t['mu1'] = 0x00B5;
- t['muasquare'] = 0x3382;
- t['muchgreater'] = 0x226B;
- t['muchless'] = 0x226A;
- t['mufsquare'] = 0x338C;
- t['mugreek'] = 0x03BC;
- t['mugsquare'] = 0x338D;
- t['muhiragana'] = 0x3080;
- t['mukatakana'] = 0x30E0;
- t['mukatakanahalfwidth'] = 0xFF91;
- t['mulsquare'] = 0x3395;
- t['multiply'] = 0x00D7;
- t['mumsquare'] = 0x339B;
- t['munahhebrew'] = 0x05A3;
- t['munahlefthebrew'] = 0x05A3;
- t['musicalnote'] = 0x266A;
- t['musicalnotedbl'] = 0x266B;
- t['musicflatsign'] = 0x266D;
- t['musicsharpsign'] = 0x266F;
- t['mussquare'] = 0x33B2;
- t['muvsquare'] = 0x33B6;
- t['muwsquare'] = 0x33BC;
- t['mvmegasquare'] = 0x33B9;
- t['mvsquare'] = 0x33B7;
- t['mwmegasquare'] = 0x33BF;
- t['mwsquare'] = 0x33BD;
- t['n'] = 0x006E;
- t['nabengali'] = 0x09A8;
- t['nabla'] = 0x2207;
- t['nacute'] = 0x0144;
- t['nadeva'] = 0x0928;
- t['nagujarati'] = 0x0AA8;
- t['nagurmukhi'] = 0x0A28;
- t['nahiragana'] = 0x306A;
- t['nakatakana'] = 0x30CA;
- t['nakatakanahalfwidth'] = 0xFF85;
- t['napostrophe'] = 0x0149;
- t['nasquare'] = 0x3381;
- t['nbopomofo'] = 0x310B;
- t['nbspace'] = 0x00A0;
- t['ncaron'] = 0x0148;
- t['ncedilla'] = 0x0146;
- t['ncircle'] = 0x24DD;
- t['ncircumflexbelow'] = 0x1E4B;
- t['ncommaaccent'] = 0x0146;
- t['ndotaccent'] = 0x1E45;
- t['ndotbelow'] = 0x1E47;
- t['nehiragana'] = 0x306D;
- t['nekatakana'] = 0x30CD;
- t['nekatakanahalfwidth'] = 0xFF88;
- t['newsheqelsign'] = 0x20AA;
- t['nfsquare'] = 0x338B;
- t['ngabengali'] = 0x0999;
- t['ngadeva'] = 0x0919;
- t['ngagujarati'] = 0x0A99;
- t['ngagurmukhi'] = 0x0A19;
- t['ngonguthai'] = 0x0E07;
- t['nhiragana'] = 0x3093;
- t['nhookleft'] = 0x0272;
- t['nhookretroflex'] = 0x0273;
- t['nieunacirclekorean'] = 0x326F;
- t['nieunaparenkorean'] = 0x320F;
- t['nieuncieuckorean'] = 0x3135;
- t['nieuncirclekorean'] = 0x3261;
- t['nieunhieuhkorean'] = 0x3136;
- t['nieunkorean'] = 0x3134;
- t['nieunpansioskorean'] = 0x3168;
- t['nieunparenkorean'] = 0x3201;
- t['nieunsioskorean'] = 0x3167;
- t['nieuntikeutkorean'] = 0x3166;
- t['nihiragana'] = 0x306B;
- t['nikatakana'] = 0x30CB;
- t['nikatakanahalfwidth'] = 0xFF86;
- t['nikhahitleftthai'] = 0xF899;
- t['nikhahitthai'] = 0x0E4D;
- t['nine'] = 0x0039;
- t['ninearabic'] = 0x0669;
- t['ninebengali'] = 0x09EF;
- t['ninecircle'] = 0x2468;
- t['ninecircleinversesansserif'] = 0x2792;
- t['ninedeva'] = 0x096F;
- t['ninegujarati'] = 0x0AEF;
- t['ninegurmukhi'] = 0x0A6F;
- t['ninehackarabic'] = 0x0669;
- t['ninehangzhou'] = 0x3029;
- t['nineideographicparen'] = 0x3228;
- t['nineinferior'] = 0x2089;
- t['ninemonospace'] = 0xFF19;
- t['nineoldstyle'] = 0xF739;
- t['nineparen'] = 0x247C;
- t['nineperiod'] = 0x2490;
- t['ninepersian'] = 0x06F9;
- t['nineroman'] = 0x2178;
- t['ninesuperior'] = 0x2079;
- t['nineteencircle'] = 0x2472;
- t['nineteenparen'] = 0x2486;
- t['nineteenperiod'] = 0x249A;
- t['ninethai'] = 0x0E59;
- t['nj'] = 0x01CC;
- t['njecyrillic'] = 0x045A;
- t['nkatakana'] = 0x30F3;
- t['nkatakanahalfwidth'] = 0xFF9D;
- t['nlegrightlong'] = 0x019E;
- t['nlinebelow'] = 0x1E49;
- t['nmonospace'] = 0xFF4E;
- t['nmsquare'] = 0x339A;
- t['nnabengali'] = 0x09A3;
- t['nnadeva'] = 0x0923;
- t['nnagujarati'] = 0x0AA3;
- t['nnagurmukhi'] = 0x0A23;
- t['nnnadeva'] = 0x0929;
- t['nohiragana'] = 0x306E;
- t['nokatakana'] = 0x30CE;
- t['nokatakanahalfwidth'] = 0xFF89;
- t['nonbreakingspace'] = 0x00A0;
- t['nonenthai'] = 0x0E13;
- t['nonuthai'] = 0x0E19;
- t['noonarabic'] = 0x0646;
- t['noonfinalarabic'] = 0xFEE6;
- t['noonghunnaarabic'] = 0x06BA;
- t['noonghunnafinalarabic'] = 0xFB9F;
- t['nooninitialarabic'] = 0xFEE7;
- t['noonjeeminitialarabic'] = 0xFCD2;
- t['noonjeemisolatedarabic'] = 0xFC4B;
- t['noonmedialarabic'] = 0xFEE8;
- t['noonmeeminitialarabic'] = 0xFCD5;
- t['noonmeemisolatedarabic'] = 0xFC4E;
- t['noonnoonfinalarabic'] = 0xFC8D;
- t['notcontains'] = 0x220C;
- t['notelement'] = 0x2209;
- t['notelementof'] = 0x2209;
- t['notequal'] = 0x2260;
- t['notgreater'] = 0x226F;
- t['notgreaternorequal'] = 0x2271;
- t['notgreaternorless'] = 0x2279;
- t['notidentical'] = 0x2262;
- t['notless'] = 0x226E;
- t['notlessnorequal'] = 0x2270;
- t['notparallel'] = 0x2226;
- t['notprecedes'] = 0x2280;
- t['notsubset'] = 0x2284;
- t['notsucceeds'] = 0x2281;
- t['notsuperset'] = 0x2285;
- t['nowarmenian'] = 0x0576;
- t['nparen'] = 0x24A9;
- t['nssquare'] = 0x33B1;
- t['nsuperior'] = 0x207F;
- t['ntilde'] = 0x00F1;
- t['nu'] = 0x03BD;
- t['nuhiragana'] = 0x306C;
- t['nukatakana'] = 0x30CC;
- t['nukatakanahalfwidth'] = 0xFF87;
- t['nuktabengali'] = 0x09BC;
- t['nuktadeva'] = 0x093C;
- t['nuktagujarati'] = 0x0ABC;
- t['nuktagurmukhi'] = 0x0A3C;
- t['numbersign'] = 0x0023;
- t['numbersignmonospace'] = 0xFF03;
- t['numbersignsmall'] = 0xFE5F;
- t['numeralsigngreek'] = 0x0374;
- t['numeralsignlowergreek'] = 0x0375;
- t['numero'] = 0x2116;
- t['nun'] = 0x05E0;
- t['nundagesh'] = 0xFB40;
- t['nundageshhebrew'] = 0xFB40;
- t['nunhebrew'] = 0x05E0;
- t['nvsquare'] = 0x33B5;
- t['nwsquare'] = 0x33BB;
- t['nyabengali'] = 0x099E;
- t['nyadeva'] = 0x091E;
- t['nyagujarati'] = 0x0A9E;
- t['nyagurmukhi'] = 0x0A1E;
- t['o'] = 0x006F;
- t['oacute'] = 0x00F3;
- t['oangthai'] = 0x0E2D;
- t['obarred'] = 0x0275;
- t['obarredcyrillic'] = 0x04E9;
- t['obarreddieresiscyrillic'] = 0x04EB;
- t['obengali'] = 0x0993;
- t['obopomofo'] = 0x311B;
- t['obreve'] = 0x014F;
- t['ocandradeva'] = 0x0911;
- t['ocandragujarati'] = 0x0A91;
- t['ocandravowelsigndeva'] = 0x0949;
- t['ocandravowelsigngujarati'] = 0x0AC9;
- t['ocaron'] = 0x01D2;
- t['ocircle'] = 0x24DE;
- t['ocircumflex'] = 0x00F4;
- t['ocircumflexacute'] = 0x1ED1;
- t['ocircumflexdotbelow'] = 0x1ED9;
- t['ocircumflexgrave'] = 0x1ED3;
- t['ocircumflexhookabove'] = 0x1ED5;
- t['ocircumflextilde'] = 0x1ED7;
- t['ocyrillic'] = 0x043E;
- t['odblacute'] = 0x0151;
- t['odblgrave'] = 0x020D;
- t['odeva'] = 0x0913;
- t['odieresis'] = 0x00F6;
- t['odieresiscyrillic'] = 0x04E7;
- t['odotbelow'] = 0x1ECD;
- t['oe'] = 0x0153;
- t['oekorean'] = 0x315A;
- t['ogonek'] = 0x02DB;
- t['ogonekcmb'] = 0x0328;
- t['ograve'] = 0x00F2;
- t['ogujarati'] = 0x0A93;
- t['oharmenian'] = 0x0585;
- t['ohiragana'] = 0x304A;
- t['ohookabove'] = 0x1ECF;
- t['ohorn'] = 0x01A1;
- t['ohornacute'] = 0x1EDB;
- t['ohorndotbelow'] = 0x1EE3;
- t['ohorngrave'] = 0x1EDD;
- t['ohornhookabove'] = 0x1EDF;
- t['ohorntilde'] = 0x1EE1;
- t['ohungarumlaut'] = 0x0151;
- t['oi'] = 0x01A3;
- t['oinvertedbreve'] = 0x020F;
- t['okatakana'] = 0x30AA;
- t['okatakanahalfwidth'] = 0xFF75;
- t['okorean'] = 0x3157;
- t['olehebrew'] = 0x05AB;
- t['omacron'] = 0x014D;
- t['omacronacute'] = 0x1E53;
- t['omacrongrave'] = 0x1E51;
- t['omdeva'] = 0x0950;
- t['omega'] = 0x03C9;
- t['omega1'] = 0x03D6;
- t['omegacyrillic'] = 0x0461;
- t['omegalatinclosed'] = 0x0277;
- t['omegaroundcyrillic'] = 0x047B;
- t['omegatitlocyrillic'] = 0x047D;
- t['omegatonos'] = 0x03CE;
- t['omgujarati'] = 0x0AD0;
- t['omicron'] = 0x03BF;
- t['omicrontonos'] = 0x03CC;
- t['omonospace'] = 0xFF4F;
- t['one'] = 0x0031;
- t['onearabic'] = 0x0661;
- t['onebengali'] = 0x09E7;
- t['onecircle'] = 0x2460;
- t['onecircleinversesansserif'] = 0x278A;
- t['onedeva'] = 0x0967;
- t['onedotenleader'] = 0x2024;
- t['oneeighth'] = 0x215B;
- t['onefitted'] = 0xF6DC;
- t['onegujarati'] = 0x0AE7;
- t['onegurmukhi'] = 0x0A67;
- t['onehackarabic'] = 0x0661;
- t['onehalf'] = 0x00BD;
- t['onehangzhou'] = 0x3021;
- t['oneideographicparen'] = 0x3220;
- t['oneinferior'] = 0x2081;
- t['onemonospace'] = 0xFF11;
- t['onenumeratorbengali'] = 0x09F4;
- t['oneoldstyle'] = 0xF731;
- t['oneparen'] = 0x2474;
- t['oneperiod'] = 0x2488;
- t['onepersian'] = 0x06F1;
- t['onequarter'] = 0x00BC;
- t['oneroman'] = 0x2170;
- t['onesuperior'] = 0x00B9;
- t['onethai'] = 0x0E51;
- t['onethird'] = 0x2153;
- t['oogonek'] = 0x01EB;
- t['oogonekmacron'] = 0x01ED;
- t['oogurmukhi'] = 0x0A13;
- t['oomatragurmukhi'] = 0x0A4B;
- t['oopen'] = 0x0254;
- t['oparen'] = 0x24AA;
- t['openbullet'] = 0x25E6;
- t['option'] = 0x2325;
- t['ordfeminine'] = 0x00AA;
- t['ordmasculine'] = 0x00BA;
- t['orthogonal'] = 0x221F;
- t['oshortdeva'] = 0x0912;
- t['oshortvowelsigndeva'] = 0x094A;
- t['oslash'] = 0x00F8;
- t['oslashacute'] = 0x01FF;
- t['osmallhiragana'] = 0x3049;
- t['osmallkatakana'] = 0x30A9;
- t['osmallkatakanahalfwidth'] = 0xFF6B;
- t['ostrokeacute'] = 0x01FF;
- t['osuperior'] = 0xF6F0;
- t['otcyrillic'] = 0x047F;
- t['otilde'] = 0x00F5;
- t['otildeacute'] = 0x1E4D;
- t['otildedieresis'] = 0x1E4F;
- t['oubopomofo'] = 0x3121;
- t['overline'] = 0x203E;
- t['overlinecenterline'] = 0xFE4A;
- t['overlinecmb'] = 0x0305;
- t['overlinedashed'] = 0xFE49;
- t['overlinedblwavy'] = 0xFE4C;
- t['overlinewavy'] = 0xFE4B;
- t['overscore'] = 0x00AF;
- t['ovowelsignbengali'] = 0x09CB;
- t['ovowelsigndeva'] = 0x094B;
- t['ovowelsigngujarati'] = 0x0ACB;
- t['p'] = 0x0070;
- t['paampssquare'] = 0x3380;
- t['paasentosquare'] = 0x332B;
- t['pabengali'] = 0x09AA;
- t['pacute'] = 0x1E55;
- t['padeva'] = 0x092A;
- t['pagedown'] = 0x21DF;
- t['pageup'] = 0x21DE;
- t['pagujarati'] = 0x0AAA;
- t['pagurmukhi'] = 0x0A2A;
- t['pahiragana'] = 0x3071;
- t['paiyannoithai'] = 0x0E2F;
- t['pakatakana'] = 0x30D1;
- t['palatalizationcyrilliccmb'] = 0x0484;
- t['palochkacyrillic'] = 0x04C0;
- t['pansioskorean'] = 0x317F;
- t['paragraph'] = 0x00B6;
- t['parallel'] = 0x2225;
- t['parenleft'] = 0x0028;
- t['parenleftaltonearabic'] = 0xFD3E;
- t['parenleftbt'] = 0xF8ED;
- t['parenleftex'] = 0xF8EC;
- t['parenleftinferior'] = 0x208D;
- t['parenleftmonospace'] = 0xFF08;
- t['parenleftsmall'] = 0xFE59;
- t['parenleftsuperior'] = 0x207D;
- t['parenlefttp'] = 0xF8EB;
- t['parenleftvertical'] = 0xFE35;
- t['parenright'] = 0x0029;
- t['parenrightaltonearabic'] = 0xFD3F;
- t['parenrightbt'] = 0xF8F8;
- t['parenrightex'] = 0xF8F7;
- t['parenrightinferior'] = 0x208E;
- t['parenrightmonospace'] = 0xFF09;
- t['parenrightsmall'] = 0xFE5A;
- t['parenrightsuperior'] = 0x207E;
- t['parenrighttp'] = 0xF8F6;
- t['parenrightvertical'] = 0xFE36;
- t['partialdiff'] = 0x2202;
- t['paseqhebrew'] = 0x05C0;
- t['pashtahebrew'] = 0x0599;
- t['pasquare'] = 0x33A9;
- t['patah'] = 0x05B7;
- t['patah11'] = 0x05B7;
- t['patah1d'] = 0x05B7;
- t['patah2a'] = 0x05B7;
- t['patahhebrew'] = 0x05B7;
- t['patahnarrowhebrew'] = 0x05B7;
- t['patahquarterhebrew'] = 0x05B7;
- t['patahwidehebrew'] = 0x05B7;
- t['pazerhebrew'] = 0x05A1;
- t['pbopomofo'] = 0x3106;
- t['pcircle'] = 0x24DF;
- t['pdotaccent'] = 0x1E57;
- t['pe'] = 0x05E4;
- t['pecyrillic'] = 0x043F;
- t['pedagesh'] = 0xFB44;
- t['pedageshhebrew'] = 0xFB44;
- t['peezisquare'] = 0x333B;
- t['pefinaldageshhebrew'] = 0xFB43;
- t['peharabic'] = 0x067E;
- t['peharmenian'] = 0x057A;
- t['pehebrew'] = 0x05E4;
- t['pehfinalarabic'] = 0xFB57;
- t['pehinitialarabic'] = 0xFB58;
- t['pehiragana'] = 0x307A;
- t['pehmedialarabic'] = 0xFB59;
- t['pekatakana'] = 0x30DA;
- t['pemiddlehookcyrillic'] = 0x04A7;
- t['perafehebrew'] = 0xFB4E;
- t['percent'] = 0x0025;
- t['percentarabic'] = 0x066A;
- t['percentmonospace'] = 0xFF05;
- t['percentsmall'] = 0xFE6A;
- t['period'] = 0x002E;
- t['periodarmenian'] = 0x0589;
- t['periodcentered'] = 0x00B7;
- t['periodhalfwidth'] = 0xFF61;
- t['periodinferior'] = 0xF6E7;
- t['periodmonospace'] = 0xFF0E;
- t['periodsmall'] = 0xFE52;
- t['periodsuperior'] = 0xF6E8;
- t['perispomenigreekcmb'] = 0x0342;
- t['perpendicular'] = 0x22A5;
- t['perthousand'] = 0x2030;
- t['peseta'] = 0x20A7;
- t['pfsquare'] = 0x338A;
- t['phabengali'] = 0x09AB;
- t['phadeva'] = 0x092B;
- t['phagujarati'] = 0x0AAB;
- t['phagurmukhi'] = 0x0A2B;
- t['phi'] = 0x03C6;
- t['phi1'] = 0x03D5;
- t['phieuphacirclekorean'] = 0x327A;
- t['phieuphaparenkorean'] = 0x321A;
- t['phieuphcirclekorean'] = 0x326C;
- t['phieuphkorean'] = 0x314D;
- t['phieuphparenkorean'] = 0x320C;
- t['philatin'] = 0x0278;
- t['phinthuthai'] = 0x0E3A;
- t['phisymbolgreek'] = 0x03D5;
- t['phook'] = 0x01A5;
- t['phophanthai'] = 0x0E1E;
- t['phophungthai'] = 0x0E1C;
- t['phosamphaothai'] = 0x0E20;
- t['pi'] = 0x03C0;
- t['pieupacirclekorean'] = 0x3273;
- t['pieupaparenkorean'] = 0x3213;
- t['pieupcieuckorean'] = 0x3176;
- t['pieupcirclekorean'] = 0x3265;
- t['pieupkiyeokkorean'] = 0x3172;
- t['pieupkorean'] = 0x3142;
- t['pieupparenkorean'] = 0x3205;
- t['pieupsioskiyeokkorean'] = 0x3174;
- t['pieupsioskorean'] = 0x3144;
- t['pieupsiostikeutkorean'] = 0x3175;
- t['pieupthieuthkorean'] = 0x3177;
- t['pieuptikeutkorean'] = 0x3173;
- t['pihiragana'] = 0x3074;
- t['pikatakana'] = 0x30D4;
- t['pisymbolgreek'] = 0x03D6;
- t['piwrarmenian'] = 0x0583;
- t['plus'] = 0x002B;
- t['plusbelowcmb'] = 0x031F;
- t['pluscircle'] = 0x2295;
- t['plusminus'] = 0x00B1;
- t['plusmod'] = 0x02D6;
- t['plusmonospace'] = 0xFF0B;
- t['plussmall'] = 0xFE62;
- t['plussuperior'] = 0x207A;
- t['pmonospace'] = 0xFF50;
- t['pmsquare'] = 0x33D8;
- t['pohiragana'] = 0x307D;
- t['pointingindexdownwhite'] = 0x261F;
- t['pointingindexleftwhite'] = 0x261C;
- t['pointingindexrightwhite'] = 0x261E;
- t['pointingindexupwhite'] = 0x261D;
- t['pokatakana'] = 0x30DD;
- t['poplathai'] = 0x0E1B;
- t['postalmark'] = 0x3012;
- t['postalmarkface'] = 0x3020;
- t['pparen'] = 0x24AB;
- t['precedes'] = 0x227A;
- t['prescription'] = 0x211E;
- t['primemod'] = 0x02B9;
- t['primereversed'] = 0x2035;
- t['product'] = 0x220F;
- t['projective'] = 0x2305;
- t['prolongedkana'] = 0x30FC;
- t['propellor'] = 0x2318;
- t['propersubset'] = 0x2282;
- t['propersuperset'] = 0x2283;
- t['proportion'] = 0x2237;
- t['proportional'] = 0x221D;
- t['psi'] = 0x03C8;
- t['psicyrillic'] = 0x0471;
- t['psilipneumatacyrilliccmb'] = 0x0486;
- t['pssquare'] = 0x33B0;
- t['puhiragana'] = 0x3077;
- t['pukatakana'] = 0x30D7;
- t['pvsquare'] = 0x33B4;
- t['pwsquare'] = 0x33BA;
- t['q'] = 0x0071;
- t['qadeva'] = 0x0958;
- t['qadmahebrew'] = 0x05A8;
- t['qafarabic'] = 0x0642;
- t['qaffinalarabic'] = 0xFED6;
- t['qafinitialarabic'] = 0xFED7;
- t['qafmedialarabic'] = 0xFED8;
- t['qamats'] = 0x05B8;
- t['qamats10'] = 0x05B8;
- t['qamats1a'] = 0x05B8;
- t['qamats1c'] = 0x05B8;
- t['qamats27'] = 0x05B8;
- t['qamats29'] = 0x05B8;
- t['qamats33'] = 0x05B8;
- t['qamatsde'] = 0x05B8;
- t['qamatshebrew'] = 0x05B8;
- t['qamatsnarrowhebrew'] = 0x05B8;
- t['qamatsqatanhebrew'] = 0x05B8;
- t['qamatsqatannarrowhebrew'] = 0x05B8;
- t['qamatsqatanquarterhebrew'] = 0x05B8;
- t['qamatsqatanwidehebrew'] = 0x05B8;
- t['qamatsquarterhebrew'] = 0x05B8;
- t['qamatswidehebrew'] = 0x05B8;
- t['qarneyparahebrew'] = 0x059F;
- t['qbopomofo'] = 0x3111;
- t['qcircle'] = 0x24E0;
- t['qhook'] = 0x02A0;
- t['qmonospace'] = 0xFF51;
- t['qof'] = 0x05E7;
- t['qofdagesh'] = 0xFB47;
- t['qofdageshhebrew'] = 0xFB47;
- t['qofhebrew'] = 0x05E7;
- t['qparen'] = 0x24AC;
- t['quarternote'] = 0x2669;
- t['qubuts'] = 0x05BB;
- t['qubuts18'] = 0x05BB;
- t['qubuts25'] = 0x05BB;
- t['qubuts31'] = 0x05BB;
- t['qubutshebrew'] = 0x05BB;
- t['qubutsnarrowhebrew'] = 0x05BB;
- t['qubutsquarterhebrew'] = 0x05BB;
- t['qubutswidehebrew'] = 0x05BB;
- t['question'] = 0x003F;
- t['questionarabic'] = 0x061F;
- t['questionarmenian'] = 0x055E;
- t['questiondown'] = 0x00BF;
- t['questiondownsmall'] = 0xF7BF;
- t['questiongreek'] = 0x037E;
- t['questionmonospace'] = 0xFF1F;
- t['questionsmall'] = 0xF73F;
- t['quotedbl'] = 0x0022;
- t['quotedblbase'] = 0x201E;
- t['quotedblleft'] = 0x201C;
- t['quotedblmonospace'] = 0xFF02;
- t['quotedblprime'] = 0x301E;
- t['quotedblprimereversed'] = 0x301D;
- t['quotedblright'] = 0x201D;
- t['quoteleft'] = 0x2018;
- t['quoteleftreversed'] = 0x201B;
- t['quotereversed'] = 0x201B;
- t['quoteright'] = 0x2019;
- t['quoterightn'] = 0x0149;
- t['quotesinglbase'] = 0x201A;
- t['quotesingle'] = 0x0027;
- t['quotesinglemonospace'] = 0xFF07;
- t['r'] = 0x0072;
- t['raarmenian'] = 0x057C;
- t['rabengali'] = 0x09B0;
- t['racute'] = 0x0155;
- t['radeva'] = 0x0930;
- t['radical'] = 0x221A;
- t['radicalex'] = 0xF8E5;
- t['radoverssquare'] = 0x33AE;
- t['radoverssquaredsquare'] = 0x33AF;
- t['radsquare'] = 0x33AD;
- t['rafe'] = 0x05BF;
- t['rafehebrew'] = 0x05BF;
- t['ragujarati'] = 0x0AB0;
- t['ragurmukhi'] = 0x0A30;
- t['rahiragana'] = 0x3089;
- t['rakatakana'] = 0x30E9;
- t['rakatakanahalfwidth'] = 0xFF97;
- t['ralowerdiagonalbengali'] = 0x09F1;
- t['ramiddlediagonalbengali'] = 0x09F0;
- t['ramshorn'] = 0x0264;
- t['ratio'] = 0x2236;
- t['rbopomofo'] = 0x3116;
- t['rcaron'] = 0x0159;
- t['rcedilla'] = 0x0157;
- t['rcircle'] = 0x24E1;
- t['rcommaaccent'] = 0x0157;
- t['rdblgrave'] = 0x0211;
- t['rdotaccent'] = 0x1E59;
- t['rdotbelow'] = 0x1E5B;
- t['rdotbelowmacron'] = 0x1E5D;
- t['referencemark'] = 0x203B;
- t['reflexsubset'] = 0x2286;
- t['reflexsuperset'] = 0x2287;
- t['registered'] = 0x00AE;
- t['registersans'] = 0xF8E8;
- t['registerserif'] = 0xF6DA;
- t['reharabic'] = 0x0631;
- t['reharmenian'] = 0x0580;
- t['rehfinalarabic'] = 0xFEAE;
- t['rehiragana'] = 0x308C;
- t['rekatakana'] = 0x30EC;
- t['rekatakanahalfwidth'] = 0xFF9A;
- t['resh'] = 0x05E8;
- t['reshdageshhebrew'] = 0xFB48;
- t['reshhebrew'] = 0x05E8;
- t['reversedtilde'] = 0x223D;
- t['reviahebrew'] = 0x0597;
- t['reviamugrashhebrew'] = 0x0597;
- t['revlogicalnot'] = 0x2310;
- t['rfishhook'] = 0x027E;
- t['rfishhookreversed'] = 0x027F;
- t['rhabengali'] = 0x09DD;
- t['rhadeva'] = 0x095D;
- t['rho'] = 0x03C1;
- t['rhook'] = 0x027D;
- t['rhookturned'] = 0x027B;
- t['rhookturnedsuperior'] = 0x02B5;
- t['rhosymbolgreek'] = 0x03F1;
- t['rhotichookmod'] = 0x02DE;
- t['rieulacirclekorean'] = 0x3271;
- t['rieulaparenkorean'] = 0x3211;
- t['rieulcirclekorean'] = 0x3263;
- t['rieulhieuhkorean'] = 0x3140;
- t['rieulkiyeokkorean'] = 0x313A;
- t['rieulkiyeoksioskorean'] = 0x3169;
- t['rieulkorean'] = 0x3139;
- t['rieulmieumkorean'] = 0x313B;
- t['rieulpansioskorean'] = 0x316C;
- t['rieulparenkorean'] = 0x3203;
- t['rieulphieuphkorean'] = 0x313F;
- t['rieulpieupkorean'] = 0x313C;
- t['rieulpieupsioskorean'] = 0x316B;
- t['rieulsioskorean'] = 0x313D;
- t['rieulthieuthkorean'] = 0x313E;
- t['rieultikeutkorean'] = 0x316A;
- t['rieulyeorinhieuhkorean'] = 0x316D;
- t['rightangle'] = 0x221F;
- t['righttackbelowcmb'] = 0x0319;
- t['righttriangle'] = 0x22BF;
- t['rihiragana'] = 0x308A;
- t['rikatakana'] = 0x30EA;
- t['rikatakanahalfwidth'] = 0xFF98;
- t['ring'] = 0x02DA;
- t['ringbelowcmb'] = 0x0325;
- t['ringcmb'] = 0x030A;
- t['ringhalfleft'] = 0x02BF;
- t['ringhalfleftarmenian'] = 0x0559;
- t['ringhalfleftbelowcmb'] = 0x031C;
- t['ringhalfleftcentered'] = 0x02D3;
- t['ringhalfright'] = 0x02BE;
- t['ringhalfrightbelowcmb'] = 0x0339;
- t['ringhalfrightcentered'] = 0x02D2;
- t['rinvertedbreve'] = 0x0213;
- t['rittorusquare'] = 0x3351;
- t['rlinebelow'] = 0x1E5F;
- t['rlongleg'] = 0x027C;
- t['rlonglegturned'] = 0x027A;
- t['rmonospace'] = 0xFF52;
- t['rohiragana'] = 0x308D;
- t['rokatakana'] = 0x30ED;
- t['rokatakanahalfwidth'] = 0xFF9B;
- t['roruathai'] = 0x0E23;
- t['rparen'] = 0x24AD;
- t['rrabengali'] = 0x09DC;
- t['rradeva'] = 0x0931;
- t['rragurmukhi'] = 0x0A5C;
- t['rreharabic'] = 0x0691;
- t['rrehfinalarabic'] = 0xFB8D;
- t['rrvocalicbengali'] = 0x09E0;
- t['rrvocalicdeva'] = 0x0960;
- t['rrvocalicgujarati'] = 0x0AE0;
- t['rrvocalicvowelsignbengali'] = 0x09C4;
- t['rrvocalicvowelsigndeva'] = 0x0944;
- t['rrvocalicvowelsigngujarati'] = 0x0AC4;
- t['rsuperior'] = 0xF6F1;
- t['rtblock'] = 0x2590;
- t['rturned'] = 0x0279;
- t['rturnedsuperior'] = 0x02B4;
- t['ruhiragana'] = 0x308B;
- t['rukatakana'] = 0x30EB;
- t['rukatakanahalfwidth'] = 0xFF99;
- t['rupeemarkbengali'] = 0x09F2;
- t['rupeesignbengali'] = 0x09F3;
- t['rupiah'] = 0xF6DD;
- t['ruthai'] = 0x0E24;
- t['rvocalicbengali'] = 0x098B;
- t['rvocalicdeva'] = 0x090B;
- t['rvocalicgujarati'] = 0x0A8B;
- t['rvocalicvowelsignbengali'] = 0x09C3;
- t['rvocalicvowelsigndeva'] = 0x0943;
- t['rvocalicvowelsigngujarati'] = 0x0AC3;
- t['s'] = 0x0073;
- t['sabengali'] = 0x09B8;
- t['sacute'] = 0x015B;
- t['sacutedotaccent'] = 0x1E65;
- t['sadarabic'] = 0x0635;
- t['sadeva'] = 0x0938;
- t['sadfinalarabic'] = 0xFEBA;
- t['sadinitialarabic'] = 0xFEBB;
- t['sadmedialarabic'] = 0xFEBC;
- t['sagujarati'] = 0x0AB8;
- t['sagurmukhi'] = 0x0A38;
- t['sahiragana'] = 0x3055;
- t['sakatakana'] = 0x30B5;
- t['sakatakanahalfwidth'] = 0xFF7B;
- t['sallallahoualayhewasallamarabic'] = 0xFDFA;
- t['samekh'] = 0x05E1;
- t['samekhdagesh'] = 0xFB41;
- t['samekhdageshhebrew'] = 0xFB41;
- t['samekhhebrew'] = 0x05E1;
- t['saraaathai'] = 0x0E32;
- t['saraaethai'] = 0x0E41;
- t['saraaimaimalaithai'] = 0x0E44;
- t['saraaimaimuanthai'] = 0x0E43;
- t['saraamthai'] = 0x0E33;
- t['saraathai'] = 0x0E30;
- t['saraethai'] = 0x0E40;
- t['saraiileftthai'] = 0xF886;
- t['saraiithai'] = 0x0E35;
- t['saraileftthai'] = 0xF885;
- t['saraithai'] = 0x0E34;
- t['saraothai'] = 0x0E42;
- t['saraueeleftthai'] = 0xF888;
- t['saraueethai'] = 0x0E37;
- t['saraueleftthai'] = 0xF887;
- t['sarauethai'] = 0x0E36;
- t['sarauthai'] = 0x0E38;
- t['sarauuthai'] = 0x0E39;
- t['sbopomofo'] = 0x3119;
- t['scaron'] = 0x0161;
- t['scarondotaccent'] = 0x1E67;
- t['scedilla'] = 0x015F;
- t['schwa'] = 0x0259;
- t['schwacyrillic'] = 0x04D9;
- t['schwadieresiscyrillic'] = 0x04DB;
- t['schwahook'] = 0x025A;
- t['scircle'] = 0x24E2;
- t['scircumflex'] = 0x015D;
- t['scommaaccent'] = 0x0219;
- t['sdotaccent'] = 0x1E61;
- t['sdotbelow'] = 0x1E63;
- t['sdotbelowdotaccent'] = 0x1E69;
- t['seagullbelowcmb'] = 0x033C;
- t['second'] = 0x2033;
- t['secondtonechinese'] = 0x02CA;
- t['section'] = 0x00A7;
- t['seenarabic'] = 0x0633;
- t['seenfinalarabic'] = 0xFEB2;
- t['seeninitialarabic'] = 0xFEB3;
- t['seenmedialarabic'] = 0xFEB4;
- t['segol'] = 0x05B6;
- t['segol13'] = 0x05B6;
- t['segol1f'] = 0x05B6;
- t['segol2c'] = 0x05B6;
- t['segolhebrew'] = 0x05B6;
- t['segolnarrowhebrew'] = 0x05B6;
- t['segolquarterhebrew'] = 0x05B6;
- t['segoltahebrew'] = 0x0592;
- t['segolwidehebrew'] = 0x05B6;
- t['seharmenian'] = 0x057D;
- t['sehiragana'] = 0x305B;
- t['sekatakana'] = 0x30BB;
- t['sekatakanahalfwidth'] = 0xFF7E;
- t['semicolon'] = 0x003B;
- t['semicolonarabic'] = 0x061B;
- t['semicolonmonospace'] = 0xFF1B;
- t['semicolonsmall'] = 0xFE54;
- t['semivoicedmarkkana'] = 0x309C;
- t['semivoicedmarkkanahalfwidth'] = 0xFF9F;
- t['sentisquare'] = 0x3322;
- t['sentosquare'] = 0x3323;
- t['seven'] = 0x0037;
- t['sevenarabic'] = 0x0667;
- t['sevenbengali'] = 0x09ED;
- t['sevencircle'] = 0x2466;
- t['sevencircleinversesansserif'] = 0x2790;
- t['sevendeva'] = 0x096D;
- t['seveneighths'] = 0x215E;
- t['sevengujarati'] = 0x0AED;
- t['sevengurmukhi'] = 0x0A6D;
- t['sevenhackarabic'] = 0x0667;
- t['sevenhangzhou'] = 0x3027;
- t['sevenideographicparen'] = 0x3226;
- t['seveninferior'] = 0x2087;
- t['sevenmonospace'] = 0xFF17;
- t['sevenoldstyle'] = 0xF737;
- t['sevenparen'] = 0x247A;
- t['sevenperiod'] = 0x248E;
- t['sevenpersian'] = 0x06F7;
- t['sevenroman'] = 0x2176;
- t['sevensuperior'] = 0x2077;
- t['seventeencircle'] = 0x2470;
- t['seventeenparen'] = 0x2484;
- t['seventeenperiod'] = 0x2498;
- t['seventhai'] = 0x0E57;
- t['sfthyphen'] = 0x00AD;
- t['shaarmenian'] = 0x0577;
- t['shabengali'] = 0x09B6;
- t['shacyrillic'] = 0x0448;
- t['shaddaarabic'] = 0x0651;
- t['shaddadammaarabic'] = 0xFC61;
- t['shaddadammatanarabic'] = 0xFC5E;
- t['shaddafathaarabic'] = 0xFC60;
- t['shaddakasraarabic'] = 0xFC62;
- t['shaddakasratanarabic'] = 0xFC5F;
- t['shade'] = 0x2592;
- t['shadedark'] = 0x2593;
- t['shadelight'] = 0x2591;
- t['shademedium'] = 0x2592;
- t['shadeva'] = 0x0936;
- t['shagujarati'] = 0x0AB6;
- t['shagurmukhi'] = 0x0A36;
- t['shalshelethebrew'] = 0x0593;
- t['shbopomofo'] = 0x3115;
- t['shchacyrillic'] = 0x0449;
- t['sheenarabic'] = 0x0634;
- t['sheenfinalarabic'] = 0xFEB6;
- t['sheeninitialarabic'] = 0xFEB7;
- t['sheenmedialarabic'] = 0xFEB8;
- t['sheicoptic'] = 0x03E3;
- t['sheqel'] = 0x20AA;
- t['sheqelhebrew'] = 0x20AA;
- t['sheva'] = 0x05B0;
- t['sheva115'] = 0x05B0;
- t['sheva15'] = 0x05B0;
- t['sheva22'] = 0x05B0;
- t['sheva2e'] = 0x05B0;
- t['shevahebrew'] = 0x05B0;
- t['shevanarrowhebrew'] = 0x05B0;
- t['shevaquarterhebrew'] = 0x05B0;
- t['shevawidehebrew'] = 0x05B0;
- t['shhacyrillic'] = 0x04BB;
- t['shimacoptic'] = 0x03ED;
- t['shin'] = 0x05E9;
- t['shindagesh'] = 0xFB49;
- t['shindageshhebrew'] = 0xFB49;
- t['shindageshshindot'] = 0xFB2C;
- t['shindageshshindothebrew'] = 0xFB2C;
- t['shindageshsindot'] = 0xFB2D;
- t['shindageshsindothebrew'] = 0xFB2D;
- t['shindothebrew'] = 0x05C1;
- t['shinhebrew'] = 0x05E9;
- t['shinshindot'] = 0xFB2A;
- t['shinshindothebrew'] = 0xFB2A;
- t['shinsindot'] = 0xFB2B;
- t['shinsindothebrew'] = 0xFB2B;
- t['shook'] = 0x0282;
- t['sigma'] = 0x03C3;
- t['sigma1'] = 0x03C2;
- t['sigmafinal'] = 0x03C2;
- t['sigmalunatesymbolgreek'] = 0x03F2;
- t['sihiragana'] = 0x3057;
- t['sikatakana'] = 0x30B7;
- t['sikatakanahalfwidth'] = 0xFF7C;
- t['siluqhebrew'] = 0x05BD;
- t['siluqlefthebrew'] = 0x05BD;
- t['similar'] = 0x223C;
- t['sindothebrew'] = 0x05C2;
- t['siosacirclekorean'] = 0x3274;
- t['siosaparenkorean'] = 0x3214;
- t['sioscieuckorean'] = 0x317E;
- t['sioscirclekorean'] = 0x3266;
- t['sioskiyeokkorean'] = 0x317A;
- t['sioskorean'] = 0x3145;
- t['siosnieunkorean'] = 0x317B;
- t['siosparenkorean'] = 0x3206;
- t['siospieupkorean'] = 0x317D;
- t['siostikeutkorean'] = 0x317C;
- t['six'] = 0x0036;
- t['sixarabic'] = 0x0666;
- t['sixbengali'] = 0x09EC;
- t['sixcircle'] = 0x2465;
- t['sixcircleinversesansserif'] = 0x278F;
- t['sixdeva'] = 0x096C;
- t['sixgujarati'] = 0x0AEC;
- t['sixgurmukhi'] = 0x0A6C;
- t['sixhackarabic'] = 0x0666;
- t['sixhangzhou'] = 0x3026;
- t['sixideographicparen'] = 0x3225;
- t['sixinferior'] = 0x2086;
- t['sixmonospace'] = 0xFF16;
- t['sixoldstyle'] = 0xF736;
- t['sixparen'] = 0x2479;
- t['sixperiod'] = 0x248D;
- t['sixpersian'] = 0x06F6;
- t['sixroman'] = 0x2175;
- t['sixsuperior'] = 0x2076;
- t['sixteencircle'] = 0x246F;
- t['sixteencurrencydenominatorbengali'] = 0x09F9;
- t['sixteenparen'] = 0x2483;
- t['sixteenperiod'] = 0x2497;
- t['sixthai'] = 0x0E56;
- t['slash'] = 0x002F;
- t['slashmonospace'] = 0xFF0F;
- t['slong'] = 0x017F;
- t['slongdotaccent'] = 0x1E9B;
- t['smileface'] = 0x263A;
- t['smonospace'] = 0xFF53;
- t['sofpasuqhebrew'] = 0x05C3;
- t['softhyphen'] = 0x00AD;
- t['softsigncyrillic'] = 0x044C;
- t['sohiragana'] = 0x305D;
- t['sokatakana'] = 0x30BD;
- t['sokatakanahalfwidth'] = 0xFF7F;
- t['soliduslongoverlaycmb'] = 0x0338;
- t['solidusshortoverlaycmb'] = 0x0337;
- t['sorusithai'] = 0x0E29;
- t['sosalathai'] = 0x0E28;
- t['sosothai'] = 0x0E0B;
- t['sosuathai'] = 0x0E2A;
- t['space'] = 0x0020;
- t['spacehackarabic'] = 0x0020;
- t['spade'] = 0x2660;
- t['spadesuitblack'] = 0x2660;
- t['spadesuitwhite'] = 0x2664;
- t['sparen'] = 0x24AE;
- t['squarebelowcmb'] = 0x033B;
- t['squarecc'] = 0x33C4;
- t['squarecm'] = 0x339D;
- t['squarediagonalcrosshatchfill'] = 0x25A9;
- t['squarehorizontalfill'] = 0x25A4;
- t['squarekg'] = 0x338F;
- t['squarekm'] = 0x339E;
- t['squarekmcapital'] = 0x33CE;
- t['squareln'] = 0x33D1;
- t['squarelog'] = 0x33D2;
- t['squaremg'] = 0x338E;
- t['squaremil'] = 0x33D5;
- t['squaremm'] = 0x339C;
- t['squaremsquared'] = 0x33A1;
- t['squareorthogonalcrosshatchfill'] = 0x25A6;
- t['squareupperlefttolowerrightfill'] = 0x25A7;
- t['squareupperrighttolowerleftfill'] = 0x25A8;
- t['squareverticalfill'] = 0x25A5;
- t['squarewhitewithsmallblack'] = 0x25A3;
- t['srsquare'] = 0x33DB;
- t['ssabengali'] = 0x09B7;
- t['ssadeva'] = 0x0937;
- t['ssagujarati'] = 0x0AB7;
- t['ssangcieuckorean'] = 0x3149;
- t['ssanghieuhkorean'] = 0x3185;
- t['ssangieungkorean'] = 0x3180;
- t['ssangkiyeokkorean'] = 0x3132;
- t['ssangnieunkorean'] = 0x3165;
- t['ssangpieupkorean'] = 0x3143;
- t['ssangsioskorean'] = 0x3146;
- t['ssangtikeutkorean'] = 0x3138;
- t['ssuperior'] = 0xF6F2;
- t['sterling'] = 0x00A3;
- t['sterlingmonospace'] = 0xFFE1;
- t['strokelongoverlaycmb'] = 0x0336;
- t['strokeshortoverlaycmb'] = 0x0335;
- t['subset'] = 0x2282;
- t['subsetnotequal'] = 0x228A;
- t['subsetorequal'] = 0x2286;
- t['succeeds'] = 0x227B;
- t['suchthat'] = 0x220B;
- t['suhiragana'] = 0x3059;
- t['sukatakana'] = 0x30B9;
- t['sukatakanahalfwidth'] = 0xFF7D;
- t['sukunarabic'] = 0x0652;
- t['summation'] = 0x2211;
- t['sun'] = 0x263C;
- t['superset'] = 0x2283;
- t['supersetnotequal'] = 0x228B;
- t['supersetorequal'] = 0x2287;
- t['svsquare'] = 0x33DC;
- t['syouwaerasquare'] = 0x337C;
- t['t'] = 0x0074;
- t['tabengali'] = 0x09A4;
- t['tackdown'] = 0x22A4;
- t['tackleft'] = 0x22A3;
- t['tadeva'] = 0x0924;
- t['tagujarati'] = 0x0AA4;
- t['tagurmukhi'] = 0x0A24;
- t['taharabic'] = 0x0637;
- t['tahfinalarabic'] = 0xFEC2;
- t['tahinitialarabic'] = 0xFEC3;
- t['tahiragana'] = 0x305F;
- t['tahmedialarabic'] = 0xFEC4;
- t['taisyouerasquare'] = 0x337D;
- t['takatakana'] = 0x30BF;
- t['takatakanahalfwidth'] = 0xFF80;
- t['tatweelarabic'] = 0x0640;
- t['tau'] = 0x03C4;
- t['tav'] = 0x05EA;
- t['tavdages'] = 0xFB4A;
- t['tavdagesh'] = 0xFB4A;
- t['tavdageshhebrew'] = 0xFB4A;
- t['tavhebrew'] = 0x05EA;
- t['tbar'] = 0x0167;
- t['tbopomofo'] = 0x310A;
- t['tcaron'] = 0x0165;
- t['tccurl'] = 0x02A8;
- t['tcedilla'] = 0x0163;
- t['tcheharabic'] = 0x0686;
- t['tchehfinalarabic'] = 0xFB7B;
- t['tchehinitialarabic'] = 0xFB7C;
- t['tchehmedialarabic'] = 0xFB7D;
- t['tcircle'] = 0x24E3;
- t['tcircumflexbelow'] = 0x1E71;
- t['tcommaaccent'] = 0x0163;
- t['tdieresis'] = 0x1E97;
- t['tdotaccent'] = 0x1E6B;
- t['tdotbelow'] = 0x1E6D;
- t['tecyrillic'] = 0x0442;
- t['tedescendercyrillic'] = 0x04AD;
- t['teharabic'] = 0x062A;
- t['tehfinalarabic'] = 0xFE96;
- t['tehhahinitialarabic'] = 0xFCA2;
- t['tehhahisolatedarabic'] = 0xFC0C;
- t['tehinitialarabic'] = 0xFE97;
- t['tehiragana'] = 0x3066;
- t['tehjeeminitialarabic'] = 0xFCA1;
- t['tehjeemisolatedarabic'] = 0xFC0B;
- t['tehmarbutaarabic'] = 0x0629;
- t['tehmarbutafinalarabic'] = 0xFE94;
- t['tehmedialarabic'] = 0xFE98;
- t['tehmeeminitialarabic'] = 0xFCA4;
- t['tehmeemisolatedarabic'] = 0xFC0E;
- t['tehnoonfinalarabic'] = 0xFC73;
- t['tekatakana'] = 0x30C6;
- t['tekatakanahalfwidth'] = 0xFF83;
- t['telephone'] = 0x2121;
- t['telephoneblack'] = 0x260E;
- t['telishagedolahebrew'] = 0x05A0;
- t['telishaqetanahebrew'] = 0x05A9;
- t['tencircle'] = 0x2469;
- t['tenideographicparen'] = 0x3229;
- t['tenparen'] = 0x247D;
- t['tenperiod'] = 0x2491;
- t['tenroman'] = 0x2179;
- t['tesh'] = 0x02A7;
- t['tet'] = 0x05D8;
- t['tetdagesh'] = 0xFB38;
- t['tetdageshhebrew'] = 0xFB38;
- t['tethebrew'] = 0x05D8;
- t['tetsecyrillic'] = 0x04B5;
- t['tevirhebrew'] = 0x059B;
- t['tevirlefthebrew'] = 0x059B;
- t['thabengali'] = 0x09A5;
- t['thadeva'] = 0x0925;
- t['thagujarati'] = 0x0AA5;
- t['thagurmukhi'] = 0x0A25;
- t['thalarabic'] = 0x0630;
- t['thalfinalarabic'] = 0xFEAC;
- t['thanthakhatlowleftthai'] = 0xF898;
- t['thanthakhatlowrightthai'] = 0xF897;
- t['thanthakhatthai'] = 0x0E4C;
- t['thanthakhatupperleftthai'] = 0xF896;
- t['theharabic'] = 0x062B;
- t['thehfinalarabic'] = 0xFE9A;
- t['thehinitialarabic'] = 0xFE9B;
- t['thehmedialarabic'] = 0xFE9C;
- t['thereexists'] = 0x2203;
- t['therefore'] = 0x2234;
- t['theta'] = 0x03B8;
- t['theta1'] = 0x03D1;
- t['thetasymbolgreek'] = 0x03D1;
- t['thieuthacirclekorean'] = 0x3279;
- t['thieuthaparenkorean'] = 0x3219;
- t['thieuthcirclekorean'] = 0x326B;
- t['thieuthkorean'] = 0x314C;
- t['thieuthparenkorean'] = 0x320B;
- t['thirteencircle'] = 0x246C;
- t['thirteenparen'] = 0x2480;
- t['thirteenperiod'] = 0x2494;
- t['thonangmonthothai'] = 0x0E11;
- t['thook'] = 0x01AD;
- t['thophuthaothai'] = 0x0E12;
- t['thorn'] = 0x00FE;
- t['thothahanthai'] = 0x0E17;
- t['thothanthai'] = 0x0E10;
- t['thothongthai'] = 0x0E18;
- t['thothungthai'] = 0x0E16;
- t['thousandcyrillic'] = 0x0482;
- t['thousandsseparatorarabic'] = 0x066C;
- t['thousandsseparatorpersian'] = 0x066C;
- t['three'] = 0x0033;
- t['threearabic'] = 0x0663;
- t['threebengali'] = 0x09E9;
- t['threecircle'] = 0x2462;
- t['threecircleinversesansserif'] = 0x278C;
- t['threedeva'] = 0x0969;
- t['threeeighths'] = 0x215C;
- t['threegujarati'] = 0x0AE9;
- t['threegurmukhi'] = 0x0A69;
- t['threehackarabic'] = 0x0663;
- t['threehangzhou'] = 0x3023;
- t['threeideographicparen'] = 0x3222;
- t['threeinferior'] = 0x2083;
- t['threemonospace'] = 0xFF13;
- t['threenumeratorbengali'] = 0x09F6;
- t['threeoldstyle'] = 0xF733;
- t['threeparen'] = 0x2476;
- t['threeperiod'] = 0x248A;
- t['threepersian'] = 0x06F3;
- t['threequarters'] = 0x00BE;
- t['threequartersemdash'] = 0xF6DE;
- t['threeroman'] = 0x2172;
- t['threesuperior'] = 0x00B3;
- t['threethai'] = 0x0E53;
- t['thzsquare'] = 0x3394;
- t['tihiragana'] = 0x3061;
- t['tikatakana'] = 0x30C1;
- t['tikatakanahalfwidth'] = 0xFF81;
- t['tikeutacirclekorean'] = 0x3270;
- t['tikeutaparenkorean'] = 0x3210;
- t['tikeutcirclekorean'] = 0x3262;
- t['tikeutkorean'] = 0x3137;
- t['tikeutparenkorean'] = 0x3202;
- t['tilde'] = 0x02DC;
- t['tildebelowcmb'] = 0x0330;
- t['tildecmb'] = 0x0303;
- t['tildecomb'] = 0x0303;
- t['tildedoublecmb'] = 0x0360;
- t['tildeoperator'] = 0x223C;
- t['tildeoverlaycmb'] = 0x0334;
- t['tildeverticalcmb'] = 0x033E;
- t['timescircle'] = 0x2297;
- t['tipehahebrew'] = 0x0596;
- t['tipehalefthebrew'] = 0x0596;
- t['tippigurmukhi'] = 0x0A70;
- t['titlocyrilliccmb'] = 0x0483;
- t['tiwnarmenian'] = 0x057F;
- t['tlinebelow'] = 0x1E6F;
- t['tmonospace'] = 0xFF54;
- t['toarmenian'] = 0x0569;
- t['tohiragana'] = 0x3068;
- t['tokatakana'] = 0x30C8;
- t['tokatakanahalfwidth'] = 0xFF84;
- t['tonebarextrahighmod'] = 0x02E5;
- t['tonebarextralowmod'] = 0x02E9;
- t['tonebarhighmod'] = 0x02E6;
- t['tonebarlowmod'] = 0x02E8;
- t['tonebarmidmod'] = 0x02E7;
- t['tonefive'] = 0x01BD;
- t['tonesix'] = 0x0185;
- t['tonetwo'] = 0x01A8;
- t['tonos'] = 0x0384;
- t['tonsquare'] = 0x3327;
- t['topatakthai'] = 0x0E0F;
- t['tortoiseshellbracketleft'] = 0x3014;
- t['tortoiseshellbracketleftsmall'] = 0xFE5D;
- t['tortoiseshellbracketleftvertical'] = 0xFE39;
- t['tortoiseshellbracketright'] = 0x3015;
- t['tortoiseshellbracketrightsmall'] = 0xFE5E;
- t['tortoiseshellbracketrightvertical'] = 0xFE3A;
- t['totaothai'] = 0x0E15;
- t['tpalatalhook'] = 0x01AB;
- t['tparen'] = 0x24AF;
- t['trademark'] = 0x2122;
- t['trademarksans'] = 0xF8EA;
- t['trademarkserif'] = 0xF6DB;
- t['tretroflexhook'] = 0x0288;
- t['triagdn'] = 0x25BC;
- t['triaglf'] = 0x25C4;
- t['triagrt'] = 0x25BA;
- t['triagup'] = 0x25B2;
- t['ts'] = 0x02A6;
- t['tsadi'] = 0x05E6;
- t['tsadidagesh'] = 0xFB46;
- t['tsadidageshhebrew'] = 0xFB46;
- t['tsadihebrew'] = 0x05E6;
- t['tsecyrillic'] = 0x0446;
- t['tsere'] = 0x05B5;
- t['tsere12'] = 0x05B5;
- t['tsere1e'] = 0x05B5;
- t['tsere2b'] = 0x05B5;
- t['tserehebrew'] = 0x05B5;
- t['tserenarrowhebrew'] = 0x05B5;
- t['tserequarterhebrew'] = 0x05B5;
- t['tserewidehebrew'] = 0x05B5;
- t['tshecyrillic'] = 0x045B;
- t['tsuperior'] = 0xF6F3;
- t['ttabengali'] = 0x099F;
- t['ttadeva'] = 0x091F;
- t['ttagujarati'] = 0x0A9F;
- t['ttagurmukhi'] = 0x0A1F;
- t['tteharabic'] = 0x0679;
- t['ttehfinalarabic'] = 0xFB67;
- t['ttehinitialarabic'] = 0xFB68;
- t['ttehmedialarabic'] = 0xFB69;
- t['tthabengali'] = 0x09A0;
- t['tthadeva'] = 0x0920;
- t['tthagujarati'] = 0x0AA0;
- t['tthagurmukhi'] = 0x0A20;
- t['tturned'] = 0x0287;
- t['tuhiragana'] = 0x3064;
- t['tukatakana'] = 0x30C4;
- t['tukatakanahalfwidth'] = 0xFF82;
- t['tusmallhiragana'] = 0x3063;
- t['tusmallkatakana'] = 0x30C3;
- t['tusmallkatakanahalfwidth'] = 0xFF6F;
- t['twelvecircle'] = 0x246B;
- t['twelveparen'] = 0x247F;
- t['twelveperiod'] = 0x2493;
- t['twelveroman'] = 0x217B;
- t['twentycircle'] = 0x2473;
- t['twentyhangzhou'] = 0x5344;
- t['twentyparen'] = 0x2487;
- t['twentyperiod'] = 0x249B;
- t['two'] = 0x0032;
- t['twoarabic'] = 0x0662;
- t['twobengali'] = 0x09E8;
- t['twocircle'] = 0x2461;
- t['twocircleinversesansserif'] = 0x278B;
- t['twodeva'] = 0x0968;
- t['twodotenleader'] = 0x2025;
- t['twodotleader'] = 0x2025;
- t['twodotleadervertical'] = 0xFE30;
- t['twogujarati'] = 0x0AE8;
- t['twogurmukhi'] = 0x0A68;
- t['twohackarabic'] = 0x0662;
- t['twohangzhou'] = 0x3022;
- t['twoideographicparen'] = 0x3221;
- t['twoinferior'] = 0x2082;
- t['twomonospace'] = 0xFF12;
- t['twonumeratorbengali'] = 0x09F5;
- t['twooldstyle'] = 0xF732;
- t['twoparen'] = 0x2475;
- t['twoperiod'] = 0x2489;
- t['twopersian'] = 0x06F2;
- t['tworoman'] = 0x2171;
- t['twostroke'] = 0x01BB;
- t['twosuperior'] = 0x00B2;
- t['twothai'] = 0x0E52;
- t['twothirds'] = 0x2154;
- t['u'] = 0x0075;
- t['uacute'] = 0x00FA;
- t['ubar'] = 0x0289;
- t['ubengali'] = 0x0989;
- t['ubopomofo'] = 0x3128;
- t['ubreve'] = 0x016D;
- t['ucaron'] = 0x01D4;
- t['ucircle'] = 0x24E4;
- t['ucircumflex'] = 0x00FB;
- t['ucircumflexbelow'] = 0x1E77;
- t['ucyrillic'] = 0x0443;
- t['udattadeva'] = 0x0951;
- t['udblacute'] = 0x0171;
- t['udblgrave'] = 0x0215;
- t['udeva'] = 0x0909;
- t['udieresis'] = 0x00FC;
- t['udieresisacute'] = 0x01D8;
- t['udieresisbelow'] = 0x1E73;
- t['udieresiscaron'] = 0x01DA;
- t['udieresiscyrillic'] = 0x04F1;
- t['udieresisgrave'] = 0x01DC;
- t['udieresismacron'] = 0x01D6;
- t['udotbelow'] = 0x1EE5;
- t['ugrave'] = 0x00F9;
- t['ugujarati'] = 0x0A89;
- t['ugurmukhi'] = 0x0A09;
- t['uhiragana'] = 0x3046;
- t['uhookabove'] = 0x1EE7;
- t['uhorn'] = 0x01B0;
- t['uhornacute'] = 0x1EE9;
- t['uhorndotbelow'] = 0x1EF1;
- t['uhorngrave'] = 0x1EEB;
- t['uhornhookabove'] = 0x1EED;
- t['uhorntilde'] = 0x1EEF;
- t['uhungarumlaut'] = 0x0171;
- t['uhungarumlautcyrillic'] = 0x04F3;
- t['uinvertedbreve'] = 0x0217;
- t['ukatakana'] = 0x30A6;
- t['ukatakanahalfwidth'] = 0xFF73;
- t['ukcyrillic'] = 0x0479;
- t['ukorean'] = 0x315C;
- t['umacron'] = 0x016B;
- t['umacroncyrillic'] = 0x04EF;
- t['umacrondieresis'] = 0x1E7B;
- t['umatragurmukhi'] = 0x0A41;
- t['umonospace'] = 0xFF55;
- t['underscore'] = 0x005F;
- t['underscoredbl'] = 0x2017;
- t['underscoremonospace'] = 0xFF3F;
- t['underscorevertical'] = 0xFE33;
- t['underscorewavy'] = 0xFE4F;
- t['union'] = 0x222A;
- t['universal'] = 0x2200;
- t['uogonek'] = 0x0173;
- t['uparen'] = 0x24B0;
- t['upblock'] = 0x2580;
- t['upperdothebrew'] = 0x05C4;
- t['upsilon'] = 0x03C5;
- t['upsilondieresis'] = 0x03CB;
- t['upsilondieresistonos'] = 0x03B0;
- t['upsilonlatin'] = 0x028A;
- t['upsilontonos'] = 0x03CD;
- t['uptackbelowcmb'] = 0x031D;
- t['uptackmod'] = 0x02D4;
- t['uragurmukhi'] = 0x0A73;
- t['uring'] = 0x016F;
- t['ushortcyrillic'] = 0x045E;
- t['usmallhiragana'] = 0x3045;
- t['usmallkatakana'] = 0x30A5;
- t['usmallkatakanahalfwidth'] = 0xFF69;
- t['ustraightcyrillic'] = 0x04AF;
- t['ustraightstrokecyrillic'] = 0x04B1;
- t['utilde'] = 0x0169;
- t['utildeacute'] = 0x1E79;
- t['utildebelow'] = 0x1E75;
- t['uubengali'] = 0x098A;
- t['uudeva'] = 0x090A;
- t['uugujarati'] = 0x0A8A;
- t['uugurmukhi'] = 0x0A0A;
- t['uumatragurmukhi'] = 0x0A42;
- t['uuvowelsignbengali'] = 0x09C2;
- t['uuvowelsigndeva'] = 0x0942;
- t['uuvowelsigngujarati'] = 0x0AC2;
- t['uvowelsignbengali'] = 0x09C1;
- t['uvowelsigndeva'] = 0x0941;
- t['uvowelsigngujarati'] = 0x0AC1;
- t['v'] = 0x0076;
- t['vadeva'] = 0x0935;
- t['vagujarati'] = 0x0AB5;
- t['vagurmukhi'] = 0x0A35;
- t['vakatakana'] = 0x30F7;
- t['vav'] = 0x05D5;
- t['vavdagesh'] = 0xFB35;
- t['vavdagesh65'] = 0xFB35;
- t['vavdageshhebrew'] = 0xFB35;
- t['vavhebrew'] = 0x05D5;
- t['vavholam'] = 0xFB4B;
- t['vavholamhebrew'] = 0xFB4B;
- t['vavvavhebrew'] = 0x05F0;
- t['vavyodhebrew'] = 0x05F1;
- t['vcircle'] = 0x24E5;
- t['vdotbelow'] = 0x1E7F;
- t['vecyrillic'] = 0x0432;
- t['veharabic'] = 0x06A4;
- t['vehfinalarabic'] = 0xFB6B;
- t['vehinitialarabic'] = 0xFB6C;
- t['vehmedialarabic'] = 0xFB6D;
- t['vekatakana'] = 0x30F9;
- t['venus'] = 0x2640;
- t['verticalbar'] = 0x007C;
- t['verticallineabovecmb'] = 0x030D;
- t['verticallinebelowcmb'] = 0x0329;
- t['verticallinelowmod'] = 0x02CC;
- t['verticallinemod'] = 0x02C8;
- t['vewarmenian'] = 0x057E;
- t['vhook'] = 0x028B;
- t['vikatakana'] = 0x30F8;
- t['viramabengali'] = 0x09CD;
- t['viramadeva'] = 0x094D;
- t['viramagujarati'] = 0x0ACD;
- t['visargabengali'] = 0x0983;
- t['visargadeva'] = 0x0903;
- t['visargagujarati'] = 0x0A83;
- t['vmonospace'] = 0xFF56;
- t['voarmenian'] = 0x0578;
- t['voicediterationhiragana'] = 0x309E;
- t['voicediterationkatakana'] = 0x30FE;
- t['voicedmarkkana'] = 0x309B;
- t['voicedmarkkanahalfwidth'] = 0xFF9E;
- t['vokatakana'] = 0x30FA;
- t['vparen'] = 0x24B1;
- t['vtilde'] = 0x1E7D;
- t['vturned'] = 0x028C;
- t['vuhiragana'] = 0x3094;
- t['vukatakana'] = 0x30F4;
- t['w'] = 0x0077;
- t['wacute'] = 0x1E83;
- t['waekorean'] = 0x3159;
- t['wahiragana'] = 0x308F;
- t['wakatakana'] = 0x30EF;
- t['wakatakanahalfwidth'] = 0xFF9C;
- t['wakorean'] = 0x3158;
- t['wasmallhiragana'] = 0x308E;
- t['wasmallkatakana'] = 0x30EE;
- t['wattosquare'] = 0x3357;
- t['wavedash'] = 0x301C;
- t['wavyunderscorevertical'] = 0xFE34;
- t['wawarabic'] = 0x0648;
- t['wawfinalarabic'] = 0xFEEE;
- t['wawhamzaabovearabic'] = 0x0624;
- t['wawhamzaabovefinalarabic'] = 0xFE86;
- t['wbsquare'] = 0x33DD;
- t['wcircle'] = 0x24E6;
- t['wcircumflex'] = 0x0175;
- t['wdieresis'] = 0x1E85;
- t['wdotaccent'] = 0x1E87;
- t['wdotbelow'] = 0x1E89;
- t['wehiragana'] = 0x3091;
- t['weierstrass'] = 0x2118;
- t['wekatakana'] = 0x30F1;
- t['wekorean'] = 0x315E;
- t['weokorean'] = 0x315D;
- t['wgrave'] = 0x1E81;
- t['whitebullet'] = 0x25E6;
- t['whitecircle'] = 0x25CB;
- t['whitecircleinverse'] = 0x25D9;
- t['whitecornerbracketleft'] = 0x300E;
- t['whitecornerbracketleftvertical'] = 0xFE43;
- t['whitecornerbracketright'] = 0x300F;
- t['whitecornerbracketrightvertical'] = 0xFE44;
- t['whitediamond'] = 0x25C7;
- t['whitediamondcontainingblacksmalldiamond'] = 0x25C8;
- t['whitedownpointingsmalltriangle'] = 0x25BF;
- t['whitedownpointingtriangle'] = 0x25BD;
- t['whiteleftpointingsmalltriangle'] = 0x25C3;
- t['whiteleftpointingtriangle'] = 0x25C1;
- t['whitelenticularbracketleft'] = 0x3016;
- t['whitelenticularbracketright'] = 0x3017;
- t['whiterightpointingsmalltriangle'] = 0x25B9;
- t['whiterightpointingtriangle'] = 0x25B7;
- t['whitesmallsquare'] = 0x25AB;
- t['whitesmilingface'] = 0x263A;
- t['whitesquare'] = 0x25A1;
- t['whitestar'] = 0x2606;
- t['whitetelephone'] = 0x260F;
- t['whitetortoiseshellbracketleft'] = 0x3018;
- t['whitetortoiseshellbracketright'] = 0x3019;
- t['whiteuppointingsmalltriangle'] = 0x25B5;
- t['whiteuppointingtriangle'] = 0x25B3;
- t['wihiragana'] = 0x3090;
- t['wikatakana'] = 0x30F0;
- t['wikorean'] = 0x315F;
- t['wmonospace'] = 0xFF57;
- t['wohiragana'] = 0x3092;
- t['wokatakana'] = 0x30F2;
- t['wokatakanahalfwidth'] = 0xFF66;
- t['won'] = 0x20A9;
- t['wonmonospace'] = 0xFFE6;
- t['wowaenthai'] = 0x0E27;
- t['wparen'] = 0x24B2;
- t['wring'] = 0x1E98;
- t['wsuperior'] = 0x02B7;
- t['wturned'] = 0x028D;
- t['wynn'] = 0x01BF;
- t['x'] = 0x0078;
- t['xabovecmb'] = 0x033D;
- t['xbopomofo'] = 0x3112;
- t['xcircle'] = 0x24E7;
- t['xdieresis'] = 0x1E8D;
- t['xdotaccent'] = 0x1E8B;
- t['xeharmenian'] = 0x056D;
- t['xi'] = 0x03BE;
- t['xmonospace'] = 0xFF58;
- t['xparen'] = 0x24B3;
- t['xsuperior'] = 0x02E3;
- t['y'] = 0x0079;
- t['yaadosquare'] = 0x334E;
- t['yabengali'] = 0x09AF;
- t['yacute'] = 0x00FD;
- t['yadeva'] = 0x092F;
- t['yaekorean'] = 0x3152;
- t['yagujarati'] = 0x0AAF;
- t['yagurmukhi'] = 0x0A2F;
- t['yahiragana'] = 0x3084;
- t['yakatakana'] = 0x30E4;
- t['yakatakanahalfwidth'] = 0xFF94;
- t['yakorean'] = 0x3151;
- t['yamakkanthai'] = 0x0E4E;
- t['yasmallhiragana'] = 0x3083;
- t['yasmallkatakana'] = 0x30E3;
- t['yasmallkatakanahalfwidth'] = 0xFF6C;
- t['yatcyrillic'] = 0x0463;
- t['ycircle'] = 0x24E8;
- t['ycircumflex'] = 0x0177;
- t['ydieresis'] = 0x00FF;
- t['ydotaccent'] = 0x1E8F;
- t['ydotbelow'] = 0x1EF5;
- t['yeharabic'] = 0x064A;
- t['yehbarreearabic'] = 0x06D2;
- t['yehbarreefinalarabic'] = 0xFBAF;
- t['yehfinalarabic'] = 0xFEF2;
- t['yehhamzaabovearabic'] = 0x0626;
- t['yehhamzaabovefinalarabic'] = 0xFE8A;
- t['yehhamzaaboveinitialarabic'] = 0xFE8B;
- t['yehhamzaabovemedialarabic'] = 0xFE8C;
- t['yehinitialarabic'] = 0xFEF3;
- t['yehmedialarabic'] = 0xFEF4;
- t['yehmeeminitialarabic'] = 0xFCDD;
- t['yehmeemisolatedarabic'] = 0xFC58;
- t['yehnoonfinalarabic'] = 0xFC94;
- t['yehthreedotsbelowarabic'] = 0x06D1;
- t['yekorean'] = 0x3156;
- t['yen'] = 0x00A5;
- t['yenmonospace'] = 0xFFE5;
- t['yeokorean'] = 0x3155;
- t['yeorinhieuhkorean'] = 0x3186;
- t['yerahbenyomohebrew'] = 0x05AA;
- t['yerahbenyomolefthebrew'] = 0x05AA;
- t['yericyrillic'] = 0x044B;
- t['yerudieresiscyrillic'] = 0x04F9;
- t['yesieungkorean'] = 0x3181;
- t['yesieungpansioskorean'] = 0x3183;
- t['yesieungsioskorean'] = 0x3182;
- t['yetivhebrew'] = 0x059A;
- t['ygrave'] = 0x1EF3;
- t['yhook'] = 0x01B4;
- t['yhookabove'] = 0x1EF7;
- t['yiarmenian'] = 0x0575;
- t['yicyrillic'] = 0x0457;
- t['yikorean'] = 0x3162;
- t['yinyang'] = 0x262F;
- t['yiwnarmenian'] = 0x0582;
- t['ymonospace'] = 0xFF59;
- t['yod'] = 0x05D9;
- t['yoddagesh'] = 0xFB39;
- t['yoddageshhebrew'] = 0xFB39;
- t['yodhebrew'] = 0x05D9;
- t['yodyodhebrew'] = 0x05F2;
- t['yodyodpatahhebrew'] = 0xFB1F;
- t['yohiragana'] = 0x3088;
- t['yoikorean'] = 0x3189;
- t['yokatakana'] = 0x30E8;
- t['yokatakanahalfwidth'] = 0xFF96;
- t['yokorean'] = 0x315B;
- t['yosmallhiragana'] = 0x3087;
- t['yosmallkatakana'] = 0x30E7;
- t['yosmallkatakanahalfwidth'] = 0xFF6E;
- t['yotgreek'] = 0x03F3;
- t['yoyaekorean'] = 0x3188;
- t['yoyakorean'] = 0x3187;
- t['yoyakthai'] = 0x0E22;
- t['yoyingthai'] = 0x0E0D;
- t['yparen'] = 0x24B4;
- t['ypogegrammeni'] = 0x037A;
- t['ypogegrammenigreekcmb'] = 0x0345;
- t['yr'] = 0x01A6;
- t['yring'] = 0x1E99;
- t['ysuperior'] = 0x02B8;
- t['ytilde'] = 0x1EF9;
- t['yturned'] = 0x028E;
- t['yuhiragana'] = 0x3086;
- t['yuikorean'] = 0x318C;
- t['yukatakana'] = 0x30E6;
- t['yukatakanahalfwidth'] = 0xFF95;
- t['yukorean'] = 0x3160;
- t['yusbigcyrillic'] = 0x046B;
- t['yusbigiotifiedcyrillic'] = 0x046D;
- t['yuslittlecyrillic'] = 0x0467;
- t['yuslittleiotifiedcyrillic'] = 0x0469;
- t['yusmallhiragana'] = 0x3085;
- t['yusmallkatakana'] = 0x30E5;
- t['yusmallkatakanahalfwidth'] = 0xFF6D;
- t['yuyekorean'] = 0x318B;
- t['yuyeokorean'] = 0x318A;
- t['yyabengali'] = 0x09DF;
- t['yyadeva'] = 0x095F;
- t['z'] = 0x007A;
- t['zaarmenian'] = 0x0566;
- t['zacute'] = 0x017A;
- t['zadeva'] = 0x095B;
- t['zagurmukhi'] = 0x0A5B;
- t['zaharabic'] = 0x0638;
- t['zahfinalarabic'] = 0xFEC6;
- t['zahinitialarabic'] = 0xFEC7;
- t['zahiragana'] = 0x3056;
- t['zahmedialarabic'] = 0xFEC8;
- t['zainarabic'] = 0x0632;
- t['zainfinalarabic'] = 0xFEB0;
- t['zakatakana'] = 0x30B6;
- t['zaqefgadolhebrew'] = 0x0595;
- t['zaqefqatanhebrew'] = 0x0594;
- t['zarqahebrew'] = 0x0598;
- t['zayin'] = 0x05D6;
- t['zayindagesh'] = 0xFB36;
- t['zayindageshhebrew'] = 0xFB36;
- t['zayinhebrew'] = 0x05D6;
- t['zbopomofo'] = 0x3117;
- t['zcaron'] = 0x017E;
- t['zcircle'] = 0x24E9;
- t['zcircumflex'] = 0x1E91;
- t['zcurl'] = 0x0291;
- t['zdot'] = 0x017C;
- t['zdotaccent'] = 0x017C;
- t['zdotbelow'] = 0x1E93;
- t['zecyrillic'] = 0x0437;
- t['zedescendercyrillic'] = 0x0499;
- t['zedieresiscyrillic'] = 0x04DF;
- t['zehiragana'] = 0x305C;
- t['zekatakana'] = 0x30BC;
- t['zero'] = 0x0030;
- t['zeroarabic'] = 0x0660;
- t['zerobengali'] = 0x09E6;
- t['zerodeva'] = 0x0966;
- t['zerogujarati'] = 0x0AE6;
- t['zerogurmukhi'] = 0x0A66;
- t['zerohackarabic'] = 0x0660;
- t['zeroinferior'] = 0x2080;
- t['zeromonospace'] = 0xFF10;
- t['zerooldstyle'] = 0xF730;
- t['zeropersian'] = 0x06F0;
- t['zerosuperior'] = 0x2070;
- t['zerothai'] = 0x0E50;
- t['zerowidthjoiner'] = 0xFEFF;
- t['zerowidthnonjoiner'] = 0x200C;
- t['zerowidthspace'] = 0x200B;
- t['zeta'] = 0x03B6;
- t['zhbopomofo'] = 0x3113;
- t['zhearmenian'] = 0x056A;
- t['zhebrevecyrillic'] = 0x04C2;
- t['zhecyrillic'] = 0x0436;
- t['zhedescendercyrillic'] = 0x0497;
- t['zhedieresiscyrillic'] = 0x04DD;
- t['zihiragana'] = 0x3058;
- t['zikatakana'] = 0x30B8;
- t['zinorhebrew'] = 0x05AE;
- t['zlinebelow'] = 0x1E95;
- t['zmonospace'] = 0xFF5A;
- t['zohiragana'] = 0x305E;
- t['zokatakana'] = 0x30BE;
- t['zparen'] = 0x24B5;
- t['zretroflexhook'] = 0x0290;
- t['zstroke'] = 0x01B6;
- t['zuhiragana'] = 0x305A;
- t['zukatakana'] = 0x30BA;
- t['.notdef'] = 0x0000;
- });
- var getDingbatsGlyphsUnicode = getLookupTableFactory(function (t) {
- t['space'] = 0x0020;
- t['a1'] = 0x2701;
- t['a2'] = 0x2702;
- t['a202'] = 0x2703;
- t['a3'] = 0x2704;
- t['a4'] = 0x260E;
- t['a5'] = 0x2706;
- t['a119'] = 0x2707;
- t['a118'] = 0x2708;
- t['a117'] = 0x2709;
- t['a11'] = 0x261B;
- t['a12'] = 0x261E;
- t['a13'] = 0x270C;
- t['a14'] = 0x270D;
- t['a15'] = 0x270E;
- t['a16'] = 0x270F;
- t['a105'] = 0x2710;
- t['a17'] = 0x2711;
- t['a18'] = 0x2712;
- t['a19'] = 0x2713;
- t['a20'] = 0x2714;
- t['a21'] = 0x2715;
- t['a22'] = 0x2716;
- t['a23'] = 0x2717;
- t['a24'] = 0x2718;
- t['a25'] = 0x2719;
- t['a26'] = 0x271A;
- t['a27'] = 0x271B;
- t['a28'] = 0x271C;
- t['a6'] = 0x271D;
- t['a7'] = 0x271E;
- t['a8'] = 0x271F;
- t['a9'] = 0x2720;
- t['a10'] = 0x2721;
- t['a29'] = 0x2722;
- t['a30'] = 0x2723;
- t['a31'] = 0x2724;
- t['a32'] = 0x2725;
- t['a33'] = 0x2726;
- t['a34'] = 0x2727;
- t['a35'] = 0x2605;
- t['a36'] = 0x2729;
- t['a37'] = 0x272A;
- t['a38'] = 0x272B;
- t['a39'] = 0x272C;
- t['a40'] = 0x272D;
- t['a41'] = 0x272E;
- t['a42'] = 0x272F;
- t['a43'] = 0x2730;
- t['a44'] = 0x2731;
- t['a45'] = 0x2732;
- t['a46'] = 0x2733;
- t['a47'] = 0x2734;
- t['a48'] = 0x2735;
- t['a49'] = 0x2736;
- t['a50'] = 0x2737;
- t['a51'] = 0x2738;
- t['a52'] = 0x2739;
- t['a53'] = 0x273A;
- t['a54'] = 0x273B;
- t['a55'] = 0x273C;
- t['a56'] = 0x273D;
- t['a57'] = 0x273E;
- t['a58'] = 0x273F;
- t['a59'] = 0x2740;
- t['a60'] = 0x2741;
- t['a61'] = 0x2742;
- t['a62'] = 0x2743;
- t['a63'] = 0x2744;
- t['a64'] = 0x2745;
- t['a65'] = 0x2746;
- t['a66'] = 0x2747;
- t['a67'] = 0x2748;
- t['a68'] = 0x2749;
- t['a69'] = 0x274A;
- t['a70'] = 0x274B;
- t['a71'] = 0x25CF;
- t['a72'] = 0x274D;
- t['a73'] = 0x25A0;
- t['a74'] = 0x274F;
- t['a203'] = 0x2750;
- t['a75'] = 0x2751;
- t['a204'] = 0x2752;
- t['a76'] = 0x25B2;
- t['a77'] = 0x25BC;
- t['a78'] = 0x25C6;
- t['a79'] = 0x2756;
- t['a81'] = 0x25D7;
- t['a82'] = 0x2758;
- t['a83'] = 0x2759;
- t['a84'] = 0x275A;
- t['a97'] = 0x275B;
- t['a98'] = 0x275C;
- t['a99'] = 0x275D;
- t['a100'] = 0x275E;
- t['a101'] = 0x2761;
- t['a102'] = 0x2762;
- t['a103'] = 0x2763;
- t['a104'] = 0x2764;
- t['a106'] = 0x2765;
- t['a107'] = 0x2766;
- t['a108'] = 0x2767;
- t['a112'] = 0x2663;
- t['a111'] = 0x2666;
- t['a110'] = 0x2665;
- t['a109'] = 0x2660;
- t['a120'] = 0x2460;
- t['a121'] = 0x2461;
- t['a122'] = 0x2462;
- t['a123'] = 0x2463;
- t['a124'] = 0x2464;
- t['a125'] = 0x2465;
- t['a126'] = 0x2466;
- t['a127'] = 0x2467;
- t['a128'] = 0x2468;
- t['a129'] = 0x2469;
- t['a130'] = 0x2776;
- t['a131'] = 0x2777;
- t['a132'] = 0x2778;
- t['a133'] = 0x2779;
- t['a134'] = 0x277A;
- t['a135'] = 0x277B;
- t['a136'] = 0x277C;
- t['a137'] = 0x277D;
- t['a138'] = 0x277E;
- t['a139'] = 0x277F;
- t['a140'] = 0x2780;
- t['a141'] = 0x2781;
- t['a142'] = 0x2782;
- t['a143'] = 0x2783;
- t['a144'] = 0x2784;
- t['a145'] = 0x2785;
- t['a146'] = 0x2786;
- t['a147'] = 0x2787;
- t['a148'] = 0x2788;
- t['a149'] = 0x2789;
- t['a150'] = 0x278A;
- t['a151'] = 0x278B;
- t['a152'] = 0x278C;
- t['a153'] = 0x278D;
- t['a154'] = 0x278E;
- t['a155'] = 0x278F;
- t['a156'] = 0x2790;
- t['a157'] = 0x2791;
- t['a158'] = 0x2792;
- t['a159'] = 0x2793;
- t['a160'] = 0x2794;
- t['a161'] = 0x2192;
- t['a163'] = 0x2194;
- t['a164'] = 0x2195;
- t['a196'] = 0x2798;
- t['a165'] = 0x2799;
- t['a192'] = 0x279A;
- t['a166'] = 0x279B;
- t['a167'] = 0x279C;
- t['a168'] = 0x279D;
- t['a169'] = 0x279E;
- t['a170'] = 0x279F;
- t['a171'] = 0x27A0;
- t['a172'] = 0x27A1;
- t['a173'] = 0x27A2;
- t['a162'] = 0x27A3;
- t['a174'] = 0x27A4;
- t['a175'] = 0x27A5;
- t['a176'] = 0x27A6;
- t['a177'] = 0x27A7;
- t['a178'] = 0x27A8;
- t['a179'] = 0x27A9;
- t['a193'] = 0x27AA;
- t['a180'] = 0x27AB;
- t['a199'] = 0x27AC;
- t['a181'] = 0x27AD;
- t['a200'] = 0x27AE;
- t['a182'] = 0x27AF;
- t['a201'] = 0x27B1;
- t['a183'] = 0x27B2;
- t['a184'] = 0x27B3;
- t['a197'] = 0x27B4;
- t['a185'] = 0x27B5;
- t['a194'] = 0x27B6;
- t['a198'] = 0x27B7;
- t['a186'] = 0x27B8;
- t['a195'] = 0x27B9;
- t['a187'] = 0x27BA;
- t['a188'] = 0x27BB;
- t['a189'] = 0x27BC;
- t['a190'] = 0x27BD;
- t['a191'] = 0x27BE;
- t['a89'] = 0x2768;
- // 0xF8D7
- t['a90'] = 0x2769;
- // 0xF8D8
- t['a93'] = 0x276A;
- // 0xF8D9
- t['a94'] = 0x276B;
- // 0xF8DA
- t['a91'] = 0x276C;
- // 0xF8DB
- t['a92'] = 0x276D;
- // 0xF8DC
- t['a205'] = 0x276E;
- // 0xF8DD
- t['a85'] = 0x276F;
- // 0xF8DE
- t['a206'] = 0x2770;
- // 0xF8DF
- t['a86'] = 0x2771;
- // 0xF8E0
- t['a87'] = 0x2772;
- // 0xF8E1
- t['a88'] = 0x2773;
- // 0xF8E2
- t['a95'] = 0x2774;
- // 0xF8E3
- t['a96'] = 0x2775;
- // 0xF8E4
- t['.notdef'] = 0x0000;
- });
- exports.getGlyphsUnicode = getGlyphsUnicode;
- exports.getDingbatsGlyphsUnicode = getDingbatsGlyphsUnicode;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreJbig2 = {}, root.pdfjsSharedUtil, root.pdfjsCoreArithmeticDecoder);
- }(this, function (exports, sharedUtil, coreArithmeticDecoder) {
- var error = sharedUtil.error;
- var log2 = sharedUtil.log2;
- var readInt8 = sharedUtil.readInt8;
- var readUint16 = sharedUtil.readUint16;
- var readUint32 = sharedUtil.readUint32;
- var shadow = sharedUtil.shadow;
- var ArithmeticDecoder = coreArithmeticDecoder.ArithmeticDecoder;
- var Jbig2Image = function Jbig2ImageClosure() {
- // Utility data structures
- function ContextCache() {
- }
- ContextCache.prototype = {
- getContexts: function (id) {
- if (id in this) {
- return this[id];
- }
- return this[id] = new Int8Array(1 << 16);
- }
- };
- function DecodingContext(data, start, end) {
- this.data = data;
- this.start = start;
- this.end = end;
- }
- DecodingContext.prototype = {
- get decoder() {
- var decoder = new ArithmeticDecoder(this.data, this.start, this.end);
- return shadow(this, 'decoder', decoder);
- },
- get contextCache() {
- var cache = new ContextCache();
- return shadow(this, 'contextCache', cache);
- }
- };
- // Annex A. Arithmetic Integer Decoding Procedure
- // A.2 Procedure for decoding values
- function decodeInteger(contextCache, procedure, decoder) {
- var contexts = contextCache.getContexts(procedure);
- var prev = 1;
- function readBits(length) {
- var v = 0;
- for (var i = 0; i < length; i++) {
- var bit = decoder.readBit(contexts, prev);
- prev = prev < 256 ? prev << 1 | bit : (prev << 1 | bit) & 511 | 256;
- v = v << 1 | bit;
- }
- return v >>> 0;
- }
- var sign = readBits(1);
- var value = readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(32) + 4436 : readBits(12) + 340 : readBits(8) + 84 : readBits(6) + 20 : readBits(4) + 4 : readBits(2);
- return sign === 0 ? value : value > 0 ? -value : null;
- }
- // A.3 The IAID decoding procedure
- function decodeIAID(contextCache, decoder, codeLength) {
- var contexts = contextCache.getContexts('IAID');
- var prev = 1;
- for (var i = 0; i < codeLength; i++) {
- var bit = decoder.readBit(contexts, prev);
- prev = prev << 1 | bit;
- }
- if (codeLength < 31) {
- return prev & (1 << codeLength) - 1;
- }
- return prev & 0x7FFFFFFF;
- }
- // 7.3 Segment types
- var SegmentTypes = [
- 'SymbolDictionary',
- null,
- null,
- null,
- 'IntermediateTextRegion',
- null,
- 'ImmediateTextRegion',
- 'ImmediateLosslessTextRegion',
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- 'patternDictionary',
- null,
- null,
- null,
- 'IntermediateHalftoneRegion',
- null,
- 'ImmediateHalftoneRegion',
- 'ImmediateLosslessHalftoneRegion',
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- 'IntermediateGenericRegion',
- null,
- 'ImmediateGenericRegion',
- 'ImmediateLosslessGenericRegion',
- 'IntermediateGenericRefinementRegion',
- null,
- 'ImmediateGenericRefinementRegion',
- 'ImmediateLosslessGenericRefinementRegion',
- null,
- null,
- null,
- null,
- 'PageInformation',
- 'EndOfPage',
- 'EndOfStripe',
- 'EndOfFile',
- 'Profiles',
- 'Tables',
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- 'Extension'
- ];
- var CodingTemplates = [
- [
- {
- x: -1,
- y: -2
- },
- {
- x: 0,
- y: -2
- },
- {
- x: 1,
- y: -2
- },
- {
- x: -2,
- y: -1
- },
- {
- x: -1,
- y: -1
- },
- {
- x: 0,
- y: -1
- },
- {
- x: 1,
- y: -1
- },
- {
- x: 2,
- y: -1
- },
- {
- x: -4,
- y: 0
- },
- {
- x: -3,
- y: 0
- },
- {
- x: -2,
- y: 0
- },
- {
- x: -1,
- y: 0
- }
- ],
- [
- {
- x: -1,
- y: -2
- },
- {
- x: 0,
- y: -2
- },
- {
- x: 1,
- y: -2
- },
- {
- x: 2,
- y: -2
- },
- {
- x: -2,
- y: -1
- },
- {
- x: -1,
- y: -1
- },
- {
- x: 0,
- y: -1
- },
- {
- x: 1,
- y: -1
- },
- {
- x: 2,
- y: -1
- },
- {
- x: -3,
- y: 0
- },
- {
- x: -2,
- y: 0
- },
- {
- x: -1,
- y: 0
- }
- ],
- [
- {
- x: -1,
- y: -2
- },
- {
- x: 0,
- y: -2
- },
- {
- x: 1,
- y: -2
- },
- {
- x: -2,
- y: -1
- },
- {
- x: -1,
- y: -1
- },
- {
- x: 0,
- y: -1
- },
- {
- x: 1,
- y: -1
- },
- {
- x: -2,
- y: 0
- },
- {
- x: -1,
- y: 0
- }
- ],
- [
- {
- x: -3,
- y: -1
- },
- {
- x: -2,
- y: -1
- },
- {
- x: -1,
- y: -1
- },
- {
- x: 0,
- y: -1
- },
- {
- x: 1,
- y: -1
- },
- {
- x: -4,
- y: 0
- },
- {
- x: -3,
- y: 0
- },
- {
- x: -2,
- y: 0
- },
- {
- x: -1,
- y: 0
- }
- ]
- ];
- var RefinementTemplates = [
- {
- coding: [
- {
- x: 0,
- y: -1
- },
- {
- x: 1,
- y: -1
- },
- {
- x: -1,
- y: 0
- }
- ],
- reference: [
- {
- x: 0,
- y: -1
- },
- {
- x: 1,
- y: -1
- },
- {
- x: -1,
- y: 0
- },
- {
- x: 0,
- y: 0
- },
- {
- x: 1,
- y: 0
- },
- {
- x: -1,
- y: 1
- },
- {
- x: 0,
- y: 1
- },
- {
- x: 1,
- y: 1
- }
- ]
- },
- {
- coding: [
- {
- x: -1,
- y: -1
- },
- {
- x: 0,
- y: -1
- },
- {
- x: 1,
- y: -1
- },
- {
- x: -1,
- y: 0
- }
- ],
- reference: [
- {
- x: 0,
- y: -1
- },
- {
- x: -1,
- y: 0
- },
- {
- x: 0,
- y: 0
- },
- {
- x: 1,
- y: 0
- },
- {
- x: 0,
- y: 1
- },
- {
- x: 1,
- y: 1
- }
- ]
- }
- ];
- // See 6.2.5.7 Decoding the bitmap.
- var ReusedContexts = [
- 0x9B25,
- // 10011 0110010 0101
- 0x0795,
- // 0011 110010 101
- 0x00E5,
- // 001 11001 01
- 0x0195
- ];
- // 011001 0101
- var RefinementReusedContexts = [
- 0x0020,
- // '000' + '0' (coding) + '00010000' + '0' (reference)
- 0x0008
- ];
- // '0000' + '001000'
- function decodeBitmapTemplate0(width, height, decodingContext) {
- var decoder = decodingContext.decoder;
- var contexts = decodingContext.contextCache.getContexts('GB');
- var contextLabel, i, j, pixel, row, row1, row2, bitmap = [];
- // ...ooooo....
- // ..ooooooo... Context template for current pixel (X)
- // .ooooX...... (concatenate values of 'o'-pixels to get contextLabel)
- var OLD_PIXEL_MASK = 0x7BF7;
- // 01111 0111111 0111
- for (i = 0; i < height; i++) {
- row = bitmap[i] = new Uint8Array(width);
- row1 = i < 1 ? row : bitmap[i - 1];
- row2 = i < 2 ? row : bitmap[i - 2];
- // At the beginning of each row:
- // Fill contextLabel with pixels that are above/right of (X)
- contextLabel = row2[0] << 13 | row2[1] << 12 | row2[2] << 11 | row1[0] << 7 | row1[1] << 6 | row1[2] << 5 | row1[3] << 4;
- for (j = 0; j < width; j++) {
- row[j] = pixel = decoder.readBit(contexts, contextLabel);
- // At each pixel: Clear contextLabel pixels that are shifted
- // out of the context, then add new ones.
- contextLabel = (contextLabel & OLD_PIXEL_MASK) << 1 | (j + 3 < width ? row2[j + 3] << 11 : 0) | (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel;
- }
- }
- return bitmap;
- }
- // 6.2 Generic Region Decoding Procedure
- function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, decodingContext) {
- if (mmr) {
- error('JBIG2 error: MMR encoding is not supported');
- }
- // Use optimized version for the most common case
- if (templateIndex === 0 && !skip && !prediction && at.length === 4 && at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) {
- return decodeBitmapTemplate0(width, height, decodingContext);
- }
- var useskip = !!skip;
- var template = CodingTemplates[templateIndex].concat(at);
- // Sorting is non-standard, and it is not required. But sorting increases
- // the number of template bits that can be reused from the previous
- // contextLabel in the main loop.
- template.sort(function (a, b) {
- return a.y - b.y || a.x - b.x;
- });
- var templateLength = template.length;
- var templateX = new Int8Array(templateLength);
- var templateY = new Int8Array(templateLength);
- var changingTemplateEntries = [];
- var reuseMask = 0, minX = 0, maxX = 0, minY = 0;
- var c, k;
- for (k = 0; k < templateLength; k++) {
- templateX[k] = template[k].x;
- templateY[k] = template[k].y;
- minX = Math.min(minX, template[k].x);
- maxX = Math.max(maxX, template[k].x);
- minY = Math.min(minY, template[k].y);
- // Check if the template pixel appears in two consecutive context labels,
- // so it can be reused. Otherwise, we add it to the list of changing
- // template entries.
- if (k < templateLength - 1 && template[k].y === template[k + 1].y && template[k].x === template[k + 1].x - 1) {
- reuseMask |= 1 << templateLength - 1 - k;
- } else {
- changingTemplateEntries.push(k);
- }
- }
- var changingEntriesLength = changingTemplateEntries.length;
- var changingTemplateX = new Int8Array(changingEntriesLength);
- var changingTemplateY = new Int8Array(changingEntriesLength);
- var changingTemplateBit = new Uint16Array(changingEntriesLength);
- for (c = 0; c < changingEntriesLength; c++) {
- k = changingTemplateEntries[c];
- changingTemplateX[c] = template[k].x;
- changingTemplateY[c] = template[k].y;
- changingTemplateBit[c] = 1 << templateLength - 1 - k;
- }
- // Get the safe bounding box edges from the width, height, minX, maxX, minY
- var sbb_left = -minX;
- var sbb_top = -minY;
- var sbb_right = width - maxX;
- var pseudoPixelContext = ReusedContexts[templateIndex];
- var row = new Uint8Array(width);
- var bitmap = [];
- var decoder = decodingContext.decoder;
- var contexts = decodingContext.contextCache.getContexts('GB');
- var ltp = 0, j, i0, j0, contextLabel = 0, bit, shift;
- for (var i = 0; i < height; i++) {
- if (prediction) {
- var sltp = decoder.readBit(contexts, pseudoPixelContext);
- ltp ^= sltp;
- if (ltp) {
- bitmap.push(row);
- // duplicate previous row
- continue;
- }
- }
- row = new Uint8Array(row);
- bitmap.push(row);
- for (j = 0; j < width; j++) {
- if (useskip && skip[i][j]) {
- row[j] = 0;
- continue;
- }
- // Are we in the middle of a scanline, so we can reuse contextLabel
- // bits?
- if (j >= sbb_left && j < sbb_right && i >= sbb_top) {
- // If yes, we can just shift the bits that are reusable and only
- // fetch the remaining ones.
- contextLabel = contextLabel << 1 & reuseMask;
- for (k = 0; k < changingEntriesLength; k++) {
- i0 = i + changingTemplateY[k];
- j0 = j + changingTemplateX[k];
- bit = bitmap[i0][j0];
- if (bit) {
- bit = changingTemplateBit[k];
- contextLabel |= bit;
- }
- }
- } else {
- // compute the contextLabel from scratch
- contextLabel = 0;
- shift = templateLength - 1;
- for (k = 0; k < templateLength; k++, shift--) {
- j0 = j + templateX[k];
- if (j0 >= 0 && j0 < width) {
- i0 = i + templateY[k];
- if (i0 >= 0) {
- bit = bitmap[i0][j0];
- if (bit) {
- contextLabel |= bit << shift;
- }
- }
- }
- }
- }
- var pixel = decoder.readBit(contexts, contextLabel);
- row[j] = pixel;
- }
- }
- return bitmap;
- }
- // 6.3.2 Generic Refinement Region Decoding Procedure
- function decodeRefinement(width, height, templateIndex, referenceBitmap, offsetX, offsetY, prediction, at, decodingContext) {
- var codingTemplate = RefinementTemplates[templateIndex].coding;
- if (templateIndex === 0) {
- codingTemplate = codingTemplate.concat([at[0]]);
- }
- var codingTemplateLength = codingTemplate.length;
- var codingTemplateX = new Int32Array(codingTemplateLength);
- var codingTemplateY = new Int32Array(codingTemplateLength);
- var k;
- for (k = 0; k < codingTemplateLength; k++) {
- codingTemplateX[k] = codingTemplate[k].x;
- codingTemplateY[k] = codingTemplate[k].y;
- }
- var referenceTemplate = RefinementTemplates[templateIndex].reference;
- if (templateIndex === 0) {
- referenceTemplate = referenceTemplate.concat([at[1]]);
- }
- var referenceTemplateLength = referenceTemplate.length;
- var referenceTemplateX = new Int32Array(referenceTemplateLength);
- var referenceTemplateY = new Int32Array(referenceTemplateLength);
- for (k = 0; k < referenceTemplateLength; k++) {
- referenceTemplateX[k] = referenceTemplate[k].x;
- referenceTemplateY[k] = referenceTemplate[k].y;
- }
- var referenceWidth = referenceBitmap[0].length;
- var referenceHeight = referenceBitmap.length;
- var pseudoPixelContext = RefinementReusedContexts[templateIndex];
- var bitmap = [];
- var decoder = decodingContext.decoder;
- var contexts = decodingContext.contextCache.getContexts('GR');
- var ltp = 0;
- for (var i = 0; i < height; i++) {
- if (prediction) {
- var sltp = decoder.readBit(contexts, pseudoPixelContext);
- ltp ^= sltp;
- if (ltp) {
- error('JBIG2 error: prediction is not supported');
- }
- }
- var row = new Uint8Array(width);
- bitmap.push(row);
- for (var j = 0; j < width; j++) {
- var i0, j0;
- var contextLabel = 0;
- for (k = 0; k < codingTemplateLength; k++) {
- i0 = i + codingTemplateY[k];
- j0 = j + codingTemplateX[k];
- if (i0 < 0 || j0 < 0 || j0 >= width) {
- contextLabel <<= 1;
- } else
- // out of bound pixel
- {
- contextLabel = contextLabel << 1 | bitmap[i0][j0];
- }
- }
- for (k = 0; k < referenceTemplateLength; k++) {
- i0 = i + referenceTemplateY[k] + offsetY;
- j0 = j + referenceTemplateX[k] + offsetX;
- if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth) {
- contextLabel <<= 1;
- } else
- // out of bound pixel
- {
- contextLabel = contextLabel << 1 | referenceBitmap[i0][j0];
- }
- }
- var pixel = decoder.readBit(contexts, contextLabel);
- row[j] = pixel;
- }
- }
- return bitmap;
- }
- // 6.5.5 Decoding the symbol dictionary
- function decodeSymbolDictionary(huffman, refinement, symbols, numberOfNewSymbols, numberOfExportedSymbols, huffmanTables, templateIndex, at, refinementTemplateIndex, refinementAt, decodingContext) {
- if (huffman) {
- error('JBIG2 error: huffman is not supported');
- }
- var newSymbols = [];
- var currentHeight = 0;
- var symbolCodeLength = log2(symbols.length + numberOfNewSymbols);
- var decoder = decodingContext.decoder;
- var contextCache = decodingContext.contextCache;
- while (newSymbols.length < numberOfNewSymbols) {
- var deltaHeight = decodeInteger(contextCache, 'IADH', decoder);
- // 6.5.6
- currentHeight += deltaHeight;
- var currentWidth = 0;
- var totalWidth = 0;
- while (true) {
- var deltaWidth = decodeInteger(contextCache, 'IADW', decoder);
- // 6.5.7
- if (deltaWidth === null) {
- break;
- }
- // OOB
- currentWidth += deltaWidth;
- totalWidth += currentWidth;
- var bitmap;
- if (refinement) {
- // 6.5.8.2 Refinement/aggregate-coded symbol bitmap
- var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder);
- if (numberOfInstances > 1) {
- bitmap = decodeTextRegion(huffman, refinement, currentWidth, currentHeight, 0, numberOfInstances, 1, //strip size
- symbols.concat(newSymbols), symbolCodeLength, 0, //transposed
- 0, //ds offset
- 1, //top left 7.4.3.1.1
- 0, //OR operator
- huffmanTables, refinementTemplateIndex, refinementAt, decodingContext);
- } else {
- var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
- var rdx = decodeInteger(contextCache, 'IARDX', decoder);
- // 6.4.11.3
- var rdy = decodeInteger(contextCache, 'IARDY', decoder);
- // 6.4.11.4
- var symbol = symbolId < symbols.length ? symbols[symbolId] : newSymbols[symbolId - symbols.length];
- bitmap = decodeRefinement(currentWidth, currentHeight, refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, decodingContext);
- }
- } else {
- // 6.5.8.1 Direct-coded symbol bitmap
- bitmap = decodeBitmap(false, currentWidth, currentHeight, templateIndex, false, null, at, decodingContext);
- }
- newSymbols.push(bitmap);
- }
- }
- // 6.5.10 Exported symbols
- var exportedSymbols = [];
- var flags = [], currentFlag = false;
- var totalSymbolsLength = symbols.length + numberOfNewSymbols;
- while (flags.length < totalSymbolsLength) {
- var runLength = decodeInteger(contextCache, 'IAEX', decoder);
- while (runLength--) {
- flags.push(currentFlag);
- }
- currentFlag = !currentFlag;
- }
- for (var i = 0, ii = symbols.length; i < ii; i++) {
- if (flags[i]) {
- exportedSymbols.push(symbols[i]);
- }
- }
- for (var j = 0; j < numberOfNewSymbols; i++, j++) {
- if (flags[i]) {
- exportedSymbols.push(newSymbols[j]);
- }
- }
- return exportedSymbols;
- }
- function decodeTextRegion(huffman, refinement, width, height, defaultPixelValue, numberOfSymbolInstances, stripSize, inputSymbols, symbolCodeLength, transposed, dsOffset, referenceCorner, combinationOperator, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext) {
- if (huffman) {
- error('JBIG2 error: huffman is not supported');
- }
- // Prepare bitmap
- var bitmap = [];
- var i, row;
- for (i = 0; i < height; i++) {
- row = new Uint8Array(width);
- if (defaultPixelValue) {
- for (var j = 0; j < width; j++) {
- row[j] = defaultPixelValue;
- }
- }
- bitmap.push(row);
- }
- var decoder = decodingContext.decoder;
- var contextCache = decodingContext.contextCache;
- var stripT = -decodeInteger(contextCache, 'IADT', decoder);
- // 6.4.6
- var firstS = 0;
- i = 0;
- while (i < numberOfSymbolInstances) {
- var deltaT = decodeInteger(contextCache, 'IADT', decoder);
- // 6.4.6
- stripT += deltaT;
- var deltaFirstS = decodeInteger(contextCache, 'IAFS', decoder);
- // 6.4.7
- firstS += deltaFirstS;
- var currentS = firstS;
- do {
- var currentT = stripSize === 1 ? 0 : decodeInteger(contextCache, 'IAIT', decoder);
- // 6.4.9
- var t = stripSize * stripT + currentT;
- var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
- var applyRefinement = refinement && decodeInteger(contextCache, 'IARI', decoder);
- var symbolBitmap = inputSymbols[symbolId];
- var symbolWidth = symbolBitmap[0].length;
- var symbolHeight = symbolBitmap.length;
- if (applyRefinement) {
- var rdw = decodeInteger(contextCache, 'IARDW', decoder);
- // 6.4.11.1
- var rdh = decodeInteger(contextCache, 'IARDH', decoder);
- // 6.4.11.2
- var rdx = decodeInteger(contextCache, 'IARDX', decoder);
- // 6.4.11.3
- var rdy = decodeInteger(contextCache, 'IARDY', decoder);
- // 6.4.11.4
- symbolWidth += rdw;
- symbolHeight += rdh;
- symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, (rdh >> 1) + rdy, false, refinementAt, decodingContext);
- }
- var offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight);
- var offsetS = currentS - (referenceCorner & 2 ? symbolWidth : 0);
- var s2, t2, symbolRow;
- if (transposed) {
- // Place Symbol Bitmap from T1,S1
- for (s2 = 0; s2 < symbolHeight; s2++) {
- row = bitmap[offsetS + s2];
- if (!row) {
- continue;
- }
- symbolRow = symbolBitmap[s2];
- // To ignore Parts of Symbol bitmap which goes
- // outside bitmap region
- var maxWidth = Math.min(width - offsetT, symbolWidth);
- switch (combinationOperator) {
- case 0:
- // OR
- for (t2 = 0; t2 < maxWidth; t2++) {
- row[offsetT + t2] |= symbolRow[t2];
- }
- break;
- case 2:
- // XOR
- for (t2 = 0; t2 < maxWidth; t2++) {
- row[offsetT + t2] ^= symbolRow[t2];
- }
- break;
- default:
- error('JBIG2 error: operator ' + combinationOperator + ' is not supported');
- }
- }
- currentS += symbolHeight - 1;
- } else {
- for (t2 = 0; t2 < symbolHeight; t2++) {
- row = bitmap[offsetT + t2];
- if (!row) {
- continue;
- }
- symbolRow = symbolBitmap[t2];
- switch (combinationOperator) {
- case 0:
- // OR
- for (s2 = 0; s2 < symbolWidth; s2++) {
- row[offsetS + s2] |= symbolRow[s2];
- }
- break;
- case 2:
- // XOR
- for (s2 = 0; s2 < symbolWidth; s2++) {
- row[offsetS + s2] ^= symbolRow[s2];
- }
- break;
- default:
- error('JBIG2 error: operator ' + combinationOperator + ' is not supported');
- }
- }
- currentS += symbolWidth - 1;
- }
- i++;
- var deltaS = decodeInteger(contextCache, 'IADS', decoder);
- // 6.4.8
- if (deltaS === null) {
- break;
- }
- // OOB
- currentS += deltaS + dsOffset;
- } while (true);
- }
- return bitmap;
- }
- function readSegmentHeader(data, start) {
- var segmentHeader = {};
- segmentHeader.number = readUint32(data, start);
- var flags = data[start + 4];
- var segmentType = flags & 0x3F;
- if (!SegmentTypes[segmentType]) {
- error('JBIG2 error: invalid segment type: ' + segmentType);
- }
- segmentHeader.type = segmentType;
- segmentHeader.typeName = SegmentTypes[segmentType];
- segmentHeader.deferredNonRetain = !!(flags & 0x80);
- var pageAssociationFieldSize = !!(flags & 0x40);
- var referredFlags = data[start + 5];
- var referredToCount = referredFlags >> 5 & 7;
- var retainBits = [referredFlags & 31];
- var position = start + 6;
- if (referredFlags === 7) {
- referredToCount = readUint32(data, position - 1) & 0x1FFFFFFF;
- position += 3;
- var bytes = referredToCount + 7 >> 3;
- retainBits[0] = data[position++];
- while (--bytes > 0) {
- retainBits.push(data[position++]);
- }
- } else if (referredFlags === 5 || referredFlags === 6) {
- error('JBIG2 error: invalid referred-to flags');
- }
- segmentHeader.retainBits = retainBits;
- var referredToSegmentNumberSize = segmentHeader.number <= 256 ? 1 : segmentHeader.number <= 65536 ? 2 : 4;
- var referredTo = [];
- var i, ii;
- for (i = 0; i < referredToCount; i++) {
- var number = referredToSegmentNumberSize === 1 ? data[position] : referredToSegmentNumberSize === 2 ? readUint16(data, position) : readUint32(data, position);
- referredTo.push(number);
- position += referredToSegmentNumberSize;
- }
- segmentHeader.referredTo = referredTo;
- if (!pageAssociationFieldSize) {
- segmentHeader.pageAssociation = data[position++];
- } else {
- segmentHeader.pageAssociation = readUint32(data, position);
- position += 4;
- }
- segmentHeader.length = readUint32(data, position);
- position += 4;
- if (segmentHeader.length === 0xFFFFFFFF) {
- // 7.2.7 Segment data length, unknown segment length
- if (segmentType === 38) {
- // ImmediateGenericRegion
- var genericRegionInfo = readRegionSegmentInformation(data, position);
- var genericRegionSegmentFlags = data[position + RegionSegmentInformationFieldLength];
- var genericRegionMmr = !!(genericRegionSegmentFlags & 1);
- // searching for the segment end
- var searchPatternLength = 6;
- var searchPattern = new Uint8Array(searchPatternLength);
- if (!genericRegionMmr) {
- searchPattern[0] = 0xFF;
- searchPattern[1] = 0xAC;
- }
- searchPattern[2] = genericRegionInfo.height >>> 24 & 0xFF;
- searchPattern[3] = genericRegionInfo.height >> 16 & 0xFF;
- searchPattern[4] = genericRegionInfo.height >> 8 & 0xFF;
- searchPattern[5] = genericRegionInfo.height & 0xFF;
- for (i = position, ii = data.length; i < ii; i++) {
- var j = 0;
- while (j < searchPatternLength && searchPattern[j] === data[i + j]) {
- j++;
- }
- if (j === searchPatternLength) {
- segmentHeader.length = i + searchPatternLength;
- break;
- }
- }
- if (segmentHeader.length === 0xFFFFFFFF) {
- error('JBIG2 error: segment end was not found');
- }
- } else {
- error('JBIG2 error: invalid unknown segment length');
- }
- }
- segmentHeader.headerEnd = position;
- return segmentHeader;
- }
- function readSegments(header, data, start, end) {
- var segments = [];
- var position = start;
- while (position < end) {
- var segmentHeader = readSegmentHeader(data, position);
- position = segmentHeader.headerEnd;
- var segment = {
- header: segmentHeader,
- data: data
- };
- if (!header.randomAccess) {
- segment.start = position;
- position += segmentHeader.length;
- segment.end = position;
- }
- segments.push(segment);
- if (segmentHeader.type === 51) {
- break;
- }
- }
- // end of file is found
- if (header.randomAccess) {
- for (var i = 0, ii = segments.length; i < ii; i++) {
- segments[i].start = position;
- position += segments[i].header.length;
- segments[i].end = position;
- }
- }
- return segments;
- }
- // 7.4.1 Region segment information field
- function readRegionSegmentInformation(data, start) {
- return {
- width: readUint32(data, start),
- height: readUint32(data, start + 4),
- x: readUint32(data, start + 8),
- y: readUint32(data, start + 12),
- combinationOperator: data[start + 16] & 7
- };
- }
- var RegionSegmentInformationFieldLength = 17;
- function processSegment(segment, visitor) {
- var header = segment.header;
- var data = segment.data, position = segment.start, end = segment.end;
- var args, at, i, atLength;
- switch (header.type) {
- case 0:
- // SymbolDictionary
- // 7.4.2 Symbol dictionary segment syntax
- var dictionary = {};
- var dictionaryFlags = readUint16(data, position);
- // 7.4.2.1.1
- dictionary.huffman = !!(dictionaryFlags & 1);
- dictionary.refinement = !!(dictionaryFlags & 2);
- dictionary.huffmanDHSelector = dictionaryFlags >> 2 & 3;
- dictionary.huffmanDWSelector = dictionaryFlags >> 4 & 3;
- dictionary.bitmapSizeSelector = dictionaryFlags >> 6 & 1;
- dictionary.aggregationInstancesSelector = dictionaryFlags >> 7 & 1;
- dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256);
- dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512);
- dictionary.template = dictionaryFlags >> 10 & 3;
- dictionary.refinementTemplate = dictionaryFlags >> 12 & 1;
- position += 2;
- if (!dictionary.huffman) {
- atLength = dictionary.template === 0 ? 4 : 1;
- at = [];
- for (i = 0; i < atLength; i++) {
- at.push({
- x: readInt8(data, position),
- y: readInt8(data, position + 1)
- });
- position += 2;
- }
- dictionary.at = at;
- }
- if (dictionary.refinement && !dictionary.refinementTemplate) {
- at = [];
- for (i = 0; i < 2; i++) {
- at.push({
- x: readInt8(data, position),
- y: readInt8(data, position + 1)
- });
- position += 2;
- }
- dictionary.refinementAt = at;
- }
- dictionary.numberOfExportedSymbols = readUint32(data, position);
- position += 4;
- dictionary.numberOfNewSymbols = readUint32(data, position);
- position += 4;
- args = [
- dictionary,
- header.number,
- header.referredTo,
- data,
- position,
- end
- ];
- break;
- case 6:
- // ImmediateTextRegion
- case 7:
- // ImmediateLosslessTextRegion
- var textRegion = {};
- textRegion.info = readRegionSegmentInformation(data, position);
- position += RegionSegmentInformationFieldLength;
- var textRegionSegmentFlags = readUint16(data, position);
- position += 2;
- textRegion.huffman = !!(textRegionSegmentFlags & 1);
- textRegion.refinement = !!(textRegionSegmentFlags & 2);
- textRegion.stripSize = 1 << (textRegionSegmentFlags >> 2 & 3);
- textRegion.referenceCorner = textRegionSegmentFlags >> 4 & 3;
- textRegion.transposed = !!(textRegionSegmentFlags & 64);
- textRegion.combinationOperator = textRegionSegmentFlags >> 7 & 3;
- textRegion.defaultPixelValue = textRegionSegmentFlags >> 9 & 1;
- textRegion.dsOffset = textRegionSegmentFlags << 17 >> 27;
- textRegion.refinementTemplate = textRegionSegmentFlags >> 15 & 1;
- if (textRegion.huffman) {
- var textRegionHuffmanFlags = readUint16(data, position);
- position += 2;
- textRegion.huffmanFS = textRegionHuffmanFlags & 3;
- textRegion.huffmanDS = textRegionHuffmanFlags >> 2 & 3;
- textRegion.huffmanDT = textRegionHuffmanFlags >> 4 & 3;
- textRegion.huffmanRefinementDW = textRegionHuffmanFlags >> 6 & 3;
- textRegion.huffmanRefinementDH = textRegionHuffmanFlags >> 8 & 3;
- textRegion.huffmanRefinementDX = textRegionHuffmanFlags >> 10 & 3;
- textRegion.huffmanRefinementDY = textRegionHuffmanFlags >> 12 & 3;
- textRegion.huffmanRefinementSizeSelector = !!(textRegionHuffmanFlags & 14);
- }
- if (textRegion.refinement && !textRegion.refinementTemplate) {
- at = [];
- for (i = 0; i < 2; i++) {
- at.push({
- x: readInt8(data, position),
- y: readInt8(data, position + 1)
- });
- position += 2;
- }
- textRegion.refinementAt = at;
- }
- textRegion.numberOfSymbolInstances = readUint32(data, position);
- position += 4;
- // TODO 7.4.3.1.7 Symbol ID Huffman table decoding
- if (textRegion.huffman) {
- error('JBIG2 error: huffman is not supported');
- }
- args = [
- textRegion,
- header.referredTo,
- data,
- position,
- end
- ];
- break;
- case 38:
- // ImmediateGenericRegion
- case 39:
- // ImmediateLosslessGenericRegion
- var genericRegion = {};
- genericRegion.info = readRegionSegmentInformation(data, position);
- position += RegionSegmentInformationFieldLength;
- var genericRegionSegmentFlags = data[position++];
- genericRegion.mmr = !!(genericRegionSegmentFlags & 1);
- genericRegion.template = genericRegionSegmentFlags >> 1 & 3;
- genericRegion.prediction = !!(genericRegionSegmentFlags & 8);
- if (!genericRegion.mmr) {
- atLength = genericRegion.template === 0 ? 4 : 1;
- at = [];
- for (i = 0; i < atLength; i++) {
- at.push({
- x: readInt8(data, position),
- y: readInt8(data, position + 1)
- });
- position += 2;
- }
- genericRegion.at = at;
- }
- args = [
- genericRegion,
- data,
- position,
- end
- ];
- break;
- case 48:
- // PageInformation
- var pageInfo = {
- width: readUint32(data, position),
- height: readUint32(data, position + 4),
- resolutionX: readUint32(data, position + 8),
- resolutionY: readUint32(data, position + 12)
- };
- if (pageInfo.height === 0xFFFFFFFF) {
- delete pageInfo.height;
- }
- var pageSegmentFlags = data[position + 16];
- var pageStripingInformation = readUint16(data, position + 17);
- pageInfo.lossless = !!(pageSegmentFlags & 1);
- pageInfo.refinement = !!(pageSegmentFlags & 2);
- pageInfo.defaultPixelValue = pageSegmentFlags >> 2 & 1;
- pageInfo.combinationOperator = pageSegmentFlags >> 3 & 3;
- pageInfo.requiresBuffer = !!(pageSegmentFlags & 32);
- pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64);
- args = [pageInfo];
- break;
- case 49:
- // EndOfPage
- break;
- case 50:
- // EndOfStripe
- break;
- case 51:
- // EndOfFile
- break;
- case 62:
- // 7.4.15 defines 2 extension types which
- // are comments and can be ignored.
- break;
- default:
- error('JBIG2 error: segment type ' + header.typeName + '(' + header.type + ') is not implemented');
- }
- var callbackName = 'on' + header.typeName;
- if (callbackName in visitor) {
- visitor[callbackName].apply(visitor, args);
- }
- }
- function processSegments(segments, visitor) {
- for (var i = 0, ii = segments.length; i < ii; i++) {
- processSegment(segments[i], visitor);
- }
- }
- function parseJbig2(data, start, end) {
- var position = start;
- if (data[position] !== 0x97 || data[position + 1] !== 0x4A || data[position + 2] !== 0x42 || data[position + 3] !== 0x32 || data[position + 4] !== 0x0D || data[position + 5] !== 0x0A || data[position + 6] !== 0x1A || data[position + 7] !== 0x0A) {
- error('JBIG2 error: invalid header');
- }
- var header = {};
- position += 8;
- var flags = data[position++];
- header.randomAccess = !(flags & 1);
- if (!(flags & 2)) {
- header.numberOfPages = readUint32(data, position);
- position += 4;
- }
- var segments = readSegments(header, data, position, end);
- error('Not implemented');
- }
- // processSegments(segments, new SimpleSegmentVisitor());
- function parseJbig2Chunks(chunks) {
- var visitor = new SimpleSegmentVisitor();
- for (var i = 0, ii = chunks.length; i < ii; i++) {
- var chunk = chunks[i];
- var segments = readSegments({}, chunk.data, chunk.start, chunk.end);
- processSegments(segments, visitor);
- }
- return visitor.buffer;
- }
- function SimpleSegmentVisitor() {
- }
- SimpleSegmentVisitor.prototype = {
- onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) {
- this.currentPageInfo = info;
- var rowSize = info.width + 7 >> 3;
- var buffer = new Uint8Array(rowSize * info.height);
- // The contents of ArrayBuffers are initialized to 0.
- // Fill the buffer with 0xFF only if info.defaultPixelValue is set
- if (info.defaultPixelValue) {
- for (var i = 0, ii = buffer.length; i < ii; i++) {
- buffer[i] = 0xFF;
- }
- }
- this.buffer = buffer;
- },
- drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) {
- var pageInfo = this.currentPageInfo;
- var width = regionInfo.width, height = regionInfo.height;
- var rowSize = pageInfo.width + 7 >> 3;
- var combinationOperator = pageInfo.combinationOperatorOverride ? regionInfo.combinationOperator : pageInfo.combinationOperator;
- var buffer = this.buffer;
- var mask0 = 128 >> (regionInfo.x & 7);
- var offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3);
- var i, j, mask, offset;
- switch (combinationOperator) {
- case 0:
- // OR
- for (i = 0; i < height; i++) {
- mask = mask0;
- offset = offset0;
- for (j = 0; j < width; j++) {
- if (bitmap[i][j]) {
- buffer[offset] |= mask;
- }
- mask >>= 1;
- if (!mask) {
- mask = 128;
- offset++;
- }
- }
- offset0 += rowSize;
- }
- break;
- case 2:
- // XOR
- for (i = 0; i < height; i++) {
- mask = mask0;
- offset = offset0;
- for (j = 0; j < width; j++) {
- if (bitmap[i][j]) {
- buffer[offset] ^= mask;
- }
- mask >>= 1;
- if (!mask) {
- mask = 128;
- offset++;
- }
- }
- offset0 += rowSize;
- }
- break;
- default:
- error('JBIG2 error: operator ' + combinationOperator + ' is not supported');
- }
- },
- onImmediateGenericRegion: function SimpleSegmentVisitor_onImmediateGenericRegion(region, data, start, end) {
- var regionInfo = region.info;
- var decodingContext = new DecodingContext(data, start, end);
- var bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, region.template, region.prediction, null, region.at, decodingContext);
- this.drawBitmap(regionInfo, bitmap);
- },
- onImmediateLosslessGenericRegion: function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() {
- this.onImmediateGenericRegion.apply(this, arguments);
- },
- onSymbolDictionary: function SimpleSegmentVisitor_onSymbolDictionary(dictionary, currentSegment, referredSegments, data, start, end) {
- var huffmanTables;
- if (dictionary.huffman) {
- error('JBIG2 error: huffman is not supported');
- }
- // Combines exported symbols from all referred segments
- var symbols = this.symbols;
- if (!symbols) {
- this.symbols = symbols = {};
- }
- var inputSymbols = [];
- for (var i = 0, ii = referredSegments.length; i < ii; i++) {
- inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]);
- }
- var decodingContext = new DecodingContext(data, start, end);
- symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, dictionary.numberOfExportedSymbols, huffmanTables, dictionary.template, dictionary.at, dictionary.refinementTemplate, dictionary.refinementAt, decodingContext);
- },
- onImmediateTextRegion: function SimpleSegmentVisitor_onImmediateTextRegion(region, referredSegments, data, start, end) {
- var regionInfo = region.info;
- var huffmanTables;
- // Combines exported symbols from all referred segments
- var symbols = this.symbols;
- var inputSymbols = [];
- for (var i = 0, ii = referredSegments.length; i < ii; i++) {
- inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]);
- }
- var symbolCodeLength = log2(inputSymbols.length);
- var decodingContext = new DecodingContext(data, start, end);
- var bitmap = decodeTextRegion(region.huffman, region.refinement, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.numberOfSymbolInstances, region.stripSize, inputSymbols, symbolCodeLength, region.transposed, region.dsOffset, region.referenceCorner, region.combinationOperator, huffmanTables, region.refinementTemplate, region.refinementAt, decodingContext);
- this.drawBitmap(regionInfo, bitmap);
- },
- onImmediateLosslessTextRegion: function SimpleSegmentVisitor_onImmediateLosslessTextRegion() {
- this.onImmediateTextRegion.apply(this, arguments);
- }
- };
- function Jbig2Image() {
- }
- Jbig2Image.prototype = {
- parseChunks: function Jbig2Image_parseChunks(chunks) {
- return parseJbig2Chunks(chunks);
- }
- };
- return Jbig2Image;
- }();
- exports.Jbig2Image = Jbig2Image;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreJpg = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- var error = sharedUtil.error;
- /**
- * This code was forked from https://github.com/notmasteryet/jpgjs.
- * The original version was created by GitHub user notmasteryet.
- *
- * - The JPEG specification can be found in the ITU CCITT Recommendation T.81
- * (www.w3.org/Graphics/JPEG/itu-t81.pdf)
- * - The JFIF specification can be found in the JPEG File Interchange Format
- * (www.w3.org/Graphics/JPEG/jfif3.pdf)
- * - The Adobe Application-Specific JPEG markers in the
- * Supporting the DCT Filters in PostScript Level 2, Technical Note #5116
- * (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
- */
- var JpegImage = function JpegImageClosure() {
- var dctZigZag = new Uint8Array([
- 0,
- 1,
- 8,
- 16,
- 9,
- 2,
- 3,
- 10,
- 17,
- 24,
- 32,
- 25,
- 18,
- 11,
- 4,
- 5,
- 12,
- 19,
- 26,
- 33,
- 40,
- 48,
- 41,
- 34,
- 27,
- 20,
- 13,
- 6,
- 7,
- 14,
- 21,
- 28,
- 35,
- 42,
- 49,
- 56,
- 57,
- 50,
- 43,
- 36,
- 29,
- 22,
- 15,
- 23,
- 30,
- 37,
- 44,
- 51,
- 58,
- 59,
- 52,
- 45,
- 38,
- 31,
- 39,
- 46,
- 53,
- 60,
- 61,
- 54,
- 47,
- 55,
- 62,
- 63
- ]);
- var dctCos1 = 4017;
- // cos(pi/16)
- var dctSin1 = 799;
- // sin(pi/16)
- var dctCos3 = 3406;
- // cos(3*pi/16)
- var dctSin3 = 2276;
- // sin(3*pi/16)
- var dctCos6 = 1567;
- // cos(6*pi/16)
- var dctSin6 = 3784;
- // sin(6*pi/16)
- var dctSqrt2 = 5793;
- // sqrt(2)
- var dctSqrt1d2 = 2896;
- // sqrt(2) / 2
- function JpegImage() {
- this.decodeTransform = null;
- this.colorTransform = -1;
- }
- function buildHuffmanTable(codeLengths, values) {
- var k = 0, code = [], i, j, length = 16;
- while (length > 0 && !codeLengths[length - 1]) {
- length--;
- }
- code.push({
- children: [],
- index: 0
- });
- var p = code[0], q;
- for (i = 0; i < length; i++) {
- for (j = 0; j < codeLengths[i]; j++) {
- p = code.pop();
- p.children[p.index] = values[k];
- while (p.index > 0) {
- p = code.pop();
- }
- p.index++;
- code.push(p);
- while (code.length <= i) {
- code.push(q = {
- children: [],
- index: 0
- });
- p.children[p.index] = q.children;
- p = q;
- }
- k++;
- }
- if (i + 1 < length) {
- // p here points to last code
- code.push(q = {
- children: [],
- index: 0
- });
- p.children[p.index] = q.children;
- p = q;
- }
- }
- return code[0].children;
- }
- function getBlockBufferOffset(component, row, col) {
- return 64 * ((component.blocksPerLine + 1) * row + col);
- }
- function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive) {
- var mcusPerLine = frame.mcusPerLine;
- var progressive = frame.progressive;
- var startOffset = offset, bitsData = 0, bitsCount = 0;
- function readBit() {
- if (bitsCount > 0) {
- bitsCount--;
- return bitsData >> bitsCount & 1;
- }
- bitsData = data[offset++];
- if (bitsData === 0xFF) {
- var nextByte = data[offset++];
- if (nextByte) {
- error('JPEG error: unexpected marker ' + (bitsData << 8 | nextByte).toString(16));
- }
- }
- // unstuff 0
- bitsCount = 7;
- return bitsData >>> 7;
- }
- function decodeHuffman(tree) {
- var node = tree;
- while (true) {
- node = node[readBit()];
- if (typeof node === 'number') {
- return node;
- }
- if (typeof node !== 'object') {
- error('JPEG error: invalid huffman sequence');
- }
- }
- }
- function receive(length) {
- var n = 0;
- while (length > 0) {
- n = n << 1 | readBit();
- length--;
- }
- return n;
- }
- function receiveAndExtend(length) {
- if (length === 1) {
- return readBit() === 1 ? 1 : -1;
- }
- var n = receive(length);
- if (n >= 1 << length - 1) {
- return n;
- }
- return n + (-1 << length) + 1;
- }
- function decodeBaseline(component, offset) {
- var t = decodeHuffman(component.huffmanTableDC);
- var diff = t === 0 ? 0 : receiveAndExtend(t);
- component.blockData[offset] = component.pred += diff;
- var k = 1;
- while (k < 64) {
- var rs = decodeHuffman(component.huffmanTableAC);
- var s = rs & 15, r = rs >> 4;
- if (s === 0) {
- if (r < 15) {
- break;
- }
- k += 16;
- continue;
- }
- k += r;
- var z = dctZigZag[k];
- component.blockData[offset + z] = receiveAndExtend(s);
- k++;
- }
- }
- function decodeDCFirst(component, offset) {
- var t = decodeHuffman(component.huffmanTableDC);
- var diff = t === 0 ? 0 : receiveAndExtend(t) << successive;
- component.blockData[offset] = component.pred += diff;
- }
- function decodeDCSuccessive(component, offset) {
- component.blockData[offset] |= readBit() << successive;
- }
- var eobrun = 0;
- function decodeACFirst(component, offset) {
- if (eobrun > 0) {
- eobrun--;
- return;
- }
- var k = spectralStart, e = spectralEnd;
- while (k <= e) {
- var rs = decodeHuffman(component.huffmanTableAC);
- var s = rs & 15, r = rs >> 4;
- if (s === 0) {
- if (r < 15) {
- eobrun = receive(r) + (1 << r) - 1;
- break;
- }
- k += 16;
- continue;
- }
- k += r;
- var z = dctZigZag[k];
- component.blockData[offset + z] = receiveAndExtend(s) * (1 << successive);
- k++;
- }
- }
- var successiveACState = 0, successiveACNextValue;
- function decodeACSuccessive(component, offset) {
- var k = spectralStart;
- var e = spectralEnd;
- var r = 0;
- var s;
- var rs;
- while (k <= e) {
- var z = dctZigZag[k];
- switch (successiveACState) {
- case 0:
- // initial state
- rs = decodeHuffman(component.huffmanTableAC);
- s = rs & 15;
- r = rs >> 4;
- if (s === 0) {
- if (r < 15) {
- eobrun = receive(r) + (1 << r);
- successiveACState = 4;
- } else {
- r = 16;
- successiveACState = 1;
- }
- } else {
- if (s !== 1) {
- error('JPEG error: invalid ACn encoding');
- }
- successiveACNextValue = receiveAndExtend(s);
- successiveACState = r ? 2 : 3;
- }
- continue;
- case 1:
- // skipping r zero items
- case 2:
- if (component.blockData[offset + z]) {
- component.blockData[offset + z] += readBit() << successive;
- } else {
- r--;
- if (r === 0) {
- successiveACState = successiveACState === 2 ? 3 : 0;
- }
- }
- break;
- case 3:
- // set value for a zero item
- if (component.blockData[offset + z]) {
- component.blockData[offset + z] += readBit() << successive;
- } else {
- component.blockData[offset + z] = successiveACNextValue << successive;
- successiveACState = 0;
- }
- break;
- case 4:
- // eob
- if (component.blockData[offset + z]) {
- component.blockData[offset + z] += readBit() << successive;
- }
- break;
- }
- k++;
- }
- if (successiveACState === 4) {
- eobrun--;
- if (eobrun === 0) {
- successiveACState = 0;
- }
- }
- }
- function decodeMcu(component, decode, mcu, row, col) {
- var mcuRow = mcu / mcusPerLine | 0;
- var mcuCol = mcu % mcusPerLine;
- var blockRow = mcuRow * component.v + row;
- var blockCol = mcuCol * component.h + col;
- var offset = getBlockBufferOffset(component, blockRow, blockCol);
- decode(component, offset);
- }
- function decodeBlock(component, decode, mcu) {
- var blockRow = mcu / component.blocksPerLine | 0;
- var blockCol = mcu % component.blocksPerLine;
- var offset = getBlockBufferOffset(component, blockRow, blockCol);
- decode(component, offset);
- }
- var componentsLength = components.length;
- var component, i, j, k, n;
- var decodeFn;
- if (progressive) {
- if (spectralStart === 0) {
- decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
- } else {
- decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive;
- }
- } else {
- decodeFn = decodeBaseline;
- }
- var mcu = 0, marker;
- var mcuExpected;
- if (componentsLength === 1) {
- mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
- } else {
- mcuExpected = mcusPerLine * frame.mcusPerColumn;
- }
- if (!resetInterval) {
- resetInterval = mcuExpected;
- }
- var h, v;
- while (mcu < mcuExpected) {
- // reset interval stuff
- for (i = 0; i < componentsLength; i++) {
- components[i].pred = 0;
- }
- eobrun = 0;
- if (componentsLength === 1) {
- component = components[0];
- for (n = 0; n < resetInterval; n++) {
- decodeBlock(component, decodeFn, mcu);
- mcu++;
- }
- } else {
- for (n = 0; n < resetInterval; n++) {
- for (i = 0; i < componentsLength; i++) {
- component = components[i];
- h = component.h;
- v = component.v;
- for (j = 0; j < v; j++) {
- for (k = 0; k < h; k++) {
- decodeMcu(component, decodeFn, mcu, j, k);
- }
- }
- }
- mcu++;
- }
- }
- // find marker
- bitsCount = 0;
- marker = data[offset] << 8 | data[offset + 1];
- // Some bad images seem to pad Scan blocks with zero bytes, skip past
- // those to attempt to find a valid marker (fixes issue4090.pdf).
- while (data[offset] === 0x00 && offset < data.length - 1) {
- offset++;
- marker = data[offset] << 8 | data[offset + 1];
- }
- if (marker <= 0xFF00) {
- error('JPEG error: marker was not found');
- }
- if (marker >= 0xFFD0 && marker <= 0xFFD7) {
- // RSTx
- offset += 2;
- } else {
- break;
- }
- }
- return offset - startOffset;
- }
- // A port of poppler's IDCT method which in turn is taken from:
- // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
- // 'Practical Fast 1-D DCT Algorithms with 11 Multiplications',
- // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
- // 988-991.
- function quantizeAndInverse(component, blockBufferOffset, p) {
- var qt = component.quantizationTable, blockData = component.blockData;
- var v0, v1, v2, v3, v4, v5, v6, v7;
- var p0, p1, p2, p3, p4, p5, p6, p7;
- var t;
- if (!qt) {
- error('JPEG error: missing required Quantization Table.');
- }
- // inverse DCT on rows
- for (var row = 0; row < 64; row += 8) {
- // gather block data
- p0 = blockData[blockBufferOffset + row];
- p1 = blockData[blockBufferOffset + row + 1];
- p2 = blockData[blockBufferOffset + row + 2];
- p3 = blockData[blockBufferOffset + row + 3];
- p4 = blockData[blockBufferOffset + row + 4];
- p5 = blockData[blockBufferOffset + row + 5];
- p6 = blockData[blockBufferOffset + row + 6];
- p7 = blockData[blockBufferOffset + row + 7];
- // dequant p0
- p0 *= qt[row];
- // check for all-zero AC coefficients
- if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
- t = dctSqrt2 * p0 + 512 >> 10;
- p[row] = t;
- p[row + 1] = t;
- p[row + 2] = t;
- p[row + 3] = t;
- p[row + 4] = t;
- p[row + 5] = t;
- p[row + 6] = t;
- p[row + 7] = t;
- continue;
- }
- // dequant p1 ... p7
- p1 *= qt[row + 1];
- p2 *= qt[row + 2];
- p3 *= qt[row + 3];
- p4 *= qt[row + 4];
- p5 *= qt[row + 5];
- p6 *= qt[row + 6];
- p7 *= qt[row + 7];
- // stage 4
- v0 = dctSqrt2 * p0 + 128 >> 8;
- v1 = dctSqrt2 * p4 + 128 >> 8;
- v2 = p2;
- v3 = p6;
- v4 = dctSqrt1d2 * (p1 - p7) + 128 >> 8;
- v7 = dctSqrt1d2 * (p1 + p7) + 128 >> 8;
- v5 = p3 << 4;
- v6 = p5 << 4;
- // stage 3
- v0 = v0 + v1 + 1 >> 1;
- v1 = v0 - v1;
- t = v2 * dctSin6 + v3 * dctCos6 + 128 >> 8;
- v2 = v2 * dctCos6 - v3 * dctSin6 + 128 >> 8;
- v3 = t;
- v4 = v4 + v6 + 1 >> 1;
- v6 = v4 - v6;
- v7 = v7 + v5 + 1 >> 1;
- v5 = v7 - v5;
- // stage 2
- v0 = v0 + v3 + 1 >> 1;
- v3 = v0 - v3;
- v1 = v1 + v2 + 1 >> 1;
- v2 = v1 - v2;
- t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;
- v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;
- v7 = t;
- t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;
- v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;
- v6 = t;
- // stage 1
- p[row] = v0 + v7;
- p[row + 7] = v0 - v7;
- p[row + 1] = v1 + v6;
- p[row + 6] = v1 - v6;
- p[row + 2] = v2 + v5;
- p[row + 5] = v2 - v5;
- p[row + 3] = v3 + v4;
- p[row + 4] = v3 - v4;
- }
- // inverse DCT on columns
- for (var col = 0; col < 8; ++col) {
- p0 = p[col];
- p1 = p[col + 8];
- p2 = p[col + 16];
- p3 = p[col + 24];
- p4 = p[col + 32];
- p5 = p[col + 40];
- p6 = p[col + 48];
- p7 = p[col + 56];
- // check for all-zero AC coefficients
- if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
- t = dctSqrt2 * p0 + 8192 >> 14;
- // convert to 8 bit
- t = t < -2040 ? 0 : t >= 2024 ? 255 : t + 2056 >> 4;
- blockData[blockBufferOffset + col] = t;
- blockData[blockBufferOffset + col + 8] = t;
- blockData[blockBufferOffset + col + 16] = t;
- blockData[blockBufferOffset + col + 24] = t;
- blockData[blockBufferOffset + col + 32] = t;
- blockData[blockBufferOffset + col + 40] = t;
- blockData[blockBufferOffset + col + 48] = t;
- blockData[blockBufferOffset + col + 56] = t;
- continue;
- }
- // stage 4
- v0 = dctSqrt2 * p0 + 2048 >> 12;
- v1 = dctSqrt2 * p4 + 2048 >> 12;
- v2 = p2;
- v3 = p6;
- v4 = dctSqrt1d2 * (p1 - p7) + 2048 >> 12;
- v7 = dctSqrt1d2 * (p1 + p7) + 2048 >> 12;
- v5 = p3;
- v6 = p5;
- // stage 3
- // Shift v0 by 128.5 << 5 here, so we don't need to shift p0...p7 when
- // converting to UInt8 range later.
- v0 = (v0 + v1 + 1 >> 1) + 4112;
- v1 = v0 - v1;
- t = v2 * dctSin6 + v3 * dctCos6 + 2048 >> 12;
- v2 = v2 * dctCos6 - v3 * dctSin6 + 2048 >> 12;
- v3 = t;
- v4 = v4 + v6 + 1 >> 1;
- v6 = v4 - v6;
- v7 = v7 + v5 + 1 >> 1;
- v5 = v7 - v5;
- // stage 2
- v0 = v0 + v3 + 1 >> 1;
- v3 = v0 - v3;
- v1 = v1 + v2 + 1 >> 1;
- v2 = v1 - v2;
- t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;
- v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;
- v7 = t;
- t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;
- v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;
- v6 = t;
- // stage 1
- p0 = v0 + v7;
- p7 = v0 - v7;
- p1 = v1 + v6;
- p6 = v1 - v6;
- p2 = v2 + v5;
- p5 = v2 - v5;
- p3 = v3 + v4;
- p4 = v3 - v4;
- // convert to 8-bit integers
- p0 = p0 < 16 ? 0 : p0 >= 4080 ? 255 : p0 >> 4;
- p1 = p1 < 16 ? 0 : p1 >= 4080 ? 255 : p1 >> 4;
- p2 = p2 < 16 ? 0 : p2 >= 4080 ? 255 : p2 >> 4;
- p3 = p3 < 16 ? 0 : p3 >= 4080 ? 255 : p3 >> 4;
- p4 = p4 < 16 ? 0 : p4 >= 4080 ? 255 : p4 >> 4;
- p5 = p5 < 16 ? 0 : p5 >= 4080 ? 255 : p5 >> 4;
- p6 = p6 < 16 ? 0 : p6 >= 4080 ? 255 : p6 >> 4;
- p7 = p7 < 16 ? 0 : p7 >= 4080 ? 255 : p7 >> 4;
- // store block data
- blockData[blockBufferOffset + col] = p0;
- blockData[blockBufferOffset + col + 8] = p1;
- blockData[blockBufferOffset + col + 16] = p2;
- blockData[blockBufferOffset + col + 24] = p3;
- blockData[blockBufferOffset + col + 32] = p4;
- blockData[blockBufferOffset + col + 40] = p5;
- blockData[blockBufferOffset + col + 48] = p6;
- blockData[blockBufferOffset + col + 56] = p7;
- }
- }
- function buildComponentData(frame, component) {
- var blocksPerLine = component.blocksPerLine;
- var blocksPerColumn = component.blocksPerColumn;
- var computationBuffer = new Int16Array(64);
- for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
- for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
- var offset = getBlockBufferOffset(component, blockRow, blockCol);
- quantizeAndInverse(component, offset, computationBuffer);
- }
- }
- return component.blockData;
- }
- function clamp0to255(a) {
- return a <= 0 ? 0 : a >= 255 ? 255 : a;
- }
- JpegImage.prototype = {
- parse: function parse(data) {
- function readUint16() {
- var value = data[offset] << 8 | data[offset + 1];
- offset += 2;
- return value;
- }
- function readDataBlock() {
- var length = readUint16();
- var array = data.subarray(offset, offset + length - 2);
- offset += array.length;
- return array;
- }
- function prepareComponents(frame) {
- var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH);
- var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);
- for (var i = 0; i < frame.components.length; i++) {
- component = frame.components[i];
- var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH);
- var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / frame.maxV);
- var blocksPerLineForMcu = mcusPerLine * component.h;
- var blocksPerColumnForMcu = mcusPerColumn * component.v;
- var blocksBufferSize = 64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1);
- component.blockData = new Int16Array(blocksBufferSize);
- component.blocksPerLine = blocksPerLine;
- component.blocksPerColumn = blocksPerColumn;
- }
- frame.mcusPerLine = mcusPerLine;
- frame.mcusPerColumn = mcusPerColumn;
- }
- var offset = 0;
- var jfif = null;
- var adobe = null;
- var frame, resetInterval;
- var quantizationTables = [];
- var huffmanTablesAC = [], huffmanTablesDC = [];
- var fileMarker = readUint16();
- if (fileMarker !== 0xFFD8) {
- // SOI (Start of Image)
- error('JPEG error: SOI not found');
- }
- fileMarker = readUint16();
- while (fileMarker !== 0xFFD9) {
- // EOI (End of image)
- var i, j, l;
- switch (fileMarker) {
- case 0xFFE0:
- // APP0 (Application Specific)
- case 0xFFE1:
- // APP1
- case 0xFFE2:
- // APP2
- case 0xFFE3:
- // APP3
- case 0xFFE4:
- // APP4
- case 0xFFE5:
- // APP5
- case 0xFFE6:
- // APP6
- case 0xFFE7:
- // APP7
- case 0xFFE8:
- // APP8
- case 0xFFE9:
- // APP9
- case 0xFFEA:
- // APP10
- case 0xFFEB:
- // APP11
- case 0xFFEC:
- // APP12
- case 0xFFED:
- // APP13
- case 0xFFEE:
- // APP14
- case 0xFFEF:
- // APP15
- case 0xFFFE:
- // COM (Comment)
- var appData = readDataBlock();
- if (fileMarker === 0xFFE0) {
- if (appData[0] === 0x4A && appData[1] === 0x46 && appData[2] === 0x49 && appData[3] === 0x46 && appData[4] === 0) {
- // 'JFIF\x00'
- jfif = {
- version: {
- major: appData[5],
- minor: appData[6]
- },
- densityUnits: appData[7],
- xDensity: appData[8] << 8 | appData[9],
- yDensity: appData[10] << 8 | appData[11],
- thumbWidth: appData[12],
- thumbHeight: appData[13],
- thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13])
- };
- }
- }
- // TODO APP1 - Exif
- if (fileMarker === 0xFFEE) {
- if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F && appData[3] === 0x62 && appData[4] === 0x65) {
- // 'Adobe'
- adobe = {
- version: appData[5] << 8 | appData[6],
- flags0: appData[7] << 8 | appData[8],
- flags1: appData[9] << 8 | appData[10],
- transformCode: appData[11]
- };
- }
- }
- break;
- case 0xFFDB:
- // DQT (Define Quantization Tables)
- var quantizationTablesLength = readUint16();
- var quantizationTablesEnd = quantizationTablesLength + offset - 2;
- var z;
- while (offset < quantizationTablesEnd) {
- var quantizationTableSpec = data[offset++];
- var tableData = new Uint16Array(64);
- if (quantizationTableSpec >> 4 === 0) {
- // 8 bit values
- for (j = 0; j < 64; j++) {
- z = dctZigZag[j];
- tableData[z] = data[offset++];
- }
- } else if (quantizationTableSpec >> 4 === 1) {
- //16 bit
- for (j = 0; j < 64; j++) {
- z = dctZigZag[j];
- tableData[z] = readUint16();
- }
- } else {
- error('JPEG error: DQT - invalid table spec');
- }
- quantizationTables[quantizationTableSpec & 15] = tableData;
- }
- break;
- case 0xFFC0:
- // SOF0 (Start of Frame, Baseline DCT)
- case 0xFFC1:
- // SOF1 (Start of Frame, Extended DCT)
- case 0xFFC2:
- // SOF2 (Start of Frame, Progressive DCT)
- if (frame) {
- error('JPEG error: Only single frame JPEGs supported');
- }
- readUint16();
- // skip data length
- frame = {};
- frame.extended = fileMarker === 0xFFC1;
- frame.progressive = fileMarker === 0xFFC2;
- frame.precision = data[offset++];
- frame.scanLines = readUint16();
- frame.samplesPerLine = readUint16();
- frame.components = [];
- frame.componentIds = {};
- var componentsCount = data[offset++], componentId;
- var maxH = 0, maxV = 0;
- for (i = 0; i < componentsCount; i++) {
- componentId = data[offset];
- var h = data[offset + 1] >> 4;
- var v = data[offset + 1] & 15;
- if (maxH < h) {
- maxH = h;
- }
- if (maxV < v) {
- maxV = v;
- }
- var qId = data[offset + 2];
- l = frame.components.push({
- h: h,
- v: v,
- quantizationId: qId,
- quantizationTable: null
- });
- // See comment below.
- frame.componentIds[componentId] = l - 1;
- offset += 3;
- }
- frame.maxH = maxH;
- frame.maxV = maxV;
- prepareComponents(frame);
- break;
- case 0xFFC4:
- // DHT (Define Huffman Tables)
- var huffmanLength = readUint16();
- for (i = 2; i < huffmanLength;) {
- var huffmanTableSpec = data[offset++];
- var codeLengths = new Uint8Array(16);
- var codeLengthSum = 0;
- for (j = 0; j < 16; j++, offset++) {
- codeLengthSum += codeLengths[j] = data[offset];
- }
- var huffmanValues = new Uint8Array(codeLengthSum);
- for (j = 0; j < codeLengthSum; j++, offset++) {
- huffmanValues[j] = data[offset];
- }
- i += 17 + codeLengthSum;
- (huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = buildHuffmanTable(codeLengths, huffmanValues);
- }
- break;
- case 0xFFDD:
- // DRI (Define Restart Interval)
- readUint16();
- // skip data length
- resetInterval = readUint16();
- break;
- case 0xFFDA:
- // SOS (Start of Scan)
- var scanLength = readUint16();
- var selectorsCount = data[offset++];
- var components = [], component;
- for (i = 0; i < selectorsCount; i++) {
- var componentIndex = frame.componentIds[data[offset++]];
- component = frame.components[componentIndex];
- var tableSpec = data[offset++];
- component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
- component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
- components.push(component);
- }
- var spectralStart = data[offset++];
- var spectralEnd = data[offset++];
- var successiveApproximation = data[offset++];
- var processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15);
- offset += processed;
- break;
- case 0xFFFF:
- // Fill bytes
- if (data[offset] !== 0xFF) {
- // Avoid skipping a valid marker.
- offset--;
- }
- break;
- default:
- if (data[offset - 3] === 0xFF && data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) {
- // could be incorrect encoding -- last 0xFF byte of the previous
- // block was eaten by the encoder
- offset -= 3;
- break;
- }
- error('JPEG error: unknown marker ' + fileMarker.toString(16));
- }
- fileMarker = readUint16();
- }
- this.width = frame.samplesPerLine;
- this.height = frame.scanLines;
- this.jfif = jfif;
- this.adobe = adobe;
- this.components = [];
- for (i = 0; i < frame.components.length; i++) {
- component = frame.components[i];
- // Prevent errors when DQT markers are placed after SOF{n} markers,
- // by assigning the `quantizationTable` entry after the entire image
- // has been parsed (fixes issue7406.pdf).
- var quantizationTable = quantizationTables[component.quantizationId];
- if (quantizationTable) {
- component.quantizationTable = quantizationTable;
- }
- this.components.push({
- output: buildComponentData(frame, component),
- scaleX: component.h / frame.maxH,
- scaleY: component.v / frame.maxV,
- blocksPerLine: component.blocksPerLine,
- blocksPerColumn: component.blocksPerColumn
- });
- }
- this.numComponents = this.components.length;
- },
- _getLinearizedBlockData: function getLinearizedBlockData(width, height) {
- var scaleX = this.width / width, scaleY = this.height / height;
- var component, componentScaleX, componentScaleY, blocksPerScanline;
- var x, y, i, j, k;
- var index;
- var offset = 0;
- var output;
- var numComponents = this.components.length;
- var dataLength = width * height * numComponents;
- var data = new Uint8Array(dataLength);
- var xScaleBlockOffset = new Uint32Array(width);
- var mask3LSB = 0xfffffff8;
- // used to clear the 3 LSBs
- for (i = 0; i < numComponents; i++) {
- component = this.components[i];
- componentScaleX = component.scaleX * scaleX;
- componentScaleY = component.scaleY * scaleY;
- offset = i;
- output = component.output;
- blocksPerScanline = component.blocksPerLine + 1 << 3;
- // precalculate the xScaleBlockOffset
- for (x = 0; x < width; x++) {
- j = 0 | x * componentScaleX;
- xScaleBlockOffset[x] = (j & mask3LSB) << 3 | j & 7;
- }
- // linearize the blocks of the component
- for (y = 0; y < height; y++) {
- j = 0 | y * componentScaleY;
- index = blocksPerScanline * (j & mask3LSB) | (j & 7) << 3;
- for (x = 0; x < width; x++) {
- data[offset] = output[index + xScaleBlockOffset[x]];
- offset += numComponents;
- }
- }
- }
- // decodeTransform contains pairs of multiplier (-256..256) and additive
- var transform = this.decodeTransform;
- if (transform) {
- for (i = 0; i < dataLength;) {
- for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) {
- data[i] = (data[i] * transform[k] >> 8) + transform[k + 1];
- }
- }
- }
- return data;
- },
- _isColorConversionNeeded: function isColorConversionNeeded() {
- if (this.adobe && this.adobe.transformCode) {
- // The adobe transform marker overrides any previous setting
- return true;
- } else if (this.numComponents === 3) {
- if (!this.adobe && this.colorTransform === 0) {
- // If the Adobe transform marker is not present and the image
- // dictionary has a 'ColorTransform' entry, explicitly set to `0`,
- // then the colours should *not* be transformed.
- return false;
- }
- return true;
- } else {
- // `this.numComponents !== 3`
- if (!this.adobe && this.colorTransform === 1) {
- // If the Adobe transform marker is not present and the image
- // dictionary has a 'ColorTransform' entry, explicitly set to `1`,
- // then the colours should be transformed.
- return true;
- }
- return false;
- }
- },
- _convertYccToRgb: function convertYccToRgb(data) {
- var Y, Cb, Cr;
- for (var i = 0, length = data.length; i < length; i += 3) {
- Y = data[i];
- Cb = data[i + 1];
- Cr = data[i + 2];
- data[i] = clamp0to255(Y - 179.456 + 1.402 * Cr);
- data[i + 1] = clamp0to255(Y + 135.459 - 0.344 * Cb - 0.714 * Cr);
- data[i + 2] = clamp0to255(Y - 226.816 + 1.772 * Cb);
- }
- return data;
- },
- _convertYcckToRgb: function convertYcckToRgb(data) {
- var Y, Cb, Cr, k;
- var offset = 0;
- for (var i = 0, length = data.length; i < length; i += 4) {
- Y = data[i];
- Cb = data[i + 1];
- Cr = data[i + 2];
- k = data[i + 3];
- var r = -122.67195406894 + Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - 5.4080610064599e-5 * Y + 0.00048449797120281 * k - 0.154362151871126) + Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - 0.00477271405408747 * k + 1.53380253221734) + Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + 0.48357088451265) + k * (-0.000336197177618394 * k + 0.484791561490776);
- var g = 107.268039397724 + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + 0.000659397001245577 * Y + 0.000426105652938837 * k - 0.176491792462875) + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + 0.000770482631801132 * k - 0.151051492775562) + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + 0.25802910206845) + k * (-0.000318913117588328 * k - 0.213742400323665);
- var b = -20.810012546947 + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + 0.0020741088115012 * Y - 0.00288260236853442 * k + 0.814272968359295) + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + 0.000560833691242812 * k - 0.195152027534049) + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + 0.116935020465145) + k * (-0.000343531996510555 * k + 0.24165260232407);
- data[offset++] = clamp0to255(r);
- data[offset++] = clamp0to255(g);
- data[offset++] = clamp0to255(b);
- }
- return data;
- },
- _convertYcckToCmyk: function convertYcckToCmyk(data) {
- var Y, Cb, Cr;
- for (var i = 0, length = data.length; i < length; i += 4) {
- Y = data[i];
- Cb = data[i + 1];
- Cr = data[i + 2];
- data[i] = clamp0to255(434.456 - Y - 1.402 * Cr);
- data[i + 1] = clamp0to255(119.541 - Y + 0.344 * Cb + 0.714 * Cr);
- data[i + 2] = clamp0to255(481.816 - Y - 1.772 * Cb);
- }
- // K in data[i + 3] is unchanged
- return data;
- },
- _convertCmykToRgb: function convertCmykToRgb(data) {
- var c, m, y, k;
- var offset = 0;
- var min = -255 * 255 * 255;
- var scale = 1 / 255 / 255;
- for (var i = 0, length = data.length; i < length; i += 4) {
- c = data[i];
- m = data[i + 1];
- y = data[i + 2];
- k = data[i + 3];
- var r = c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k - 72734.4411664936) + m * (1.7149763477362134 * m - 5.6096736904047315 * y - 17.873870861415444 * k - 1401.7366389350734) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 4465.541406466231) - k * (21.86122147463605 * k + 48317.86113160301);
- var g = c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k - 20220.756542821975) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 48691.05921601825) + y * (4.444339102852739 * y + 9.8632861493405 * k - 6341.191035517494) - k * (20.737325471181034 * k + 47890.15695978492);
- var b = c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k - 3616.812083916688) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 28620.90484698408) + y * (0.03296041114873217 * y + 115.60384449646641 * k - 49363.43385999684) - k * (22.33816807309886 * k + 45932.16563550634);
- data[offset++] = r >= 0 ? 255 : r <= min ? 0 : 255 + r * scale | 0;
- data[offset++] = g >= 0 ? 255 : g <= min ? 0 : 255 + g * scale | 0;
- data[offset++] = b >= 0 ? 255 : b <= min ? 0 : 255 + b * scale | 0;
- }
- return data;
- },
- getData: function getData(width, height, forceRGBoutput) {
- if (this.numComponents > 4) {
- error('JPEG error: Unsupported color mode');
- }
- // type of data: Uint8Array(width * height * numComponents)
- var data = this._getLinearizedBlockData(width, height);
- if (this.numComponents === 1 && forceRGBoutput) {
- var dataLength = data.length;
- var rgbData = new Uint8Array(dataLength * 3);
- var offset = 0;
- for (var i = 0; i < dataLength; i++) {
- var grayColor = data[i];
- rgbData[offset++] = grayColor;
- rgbData[offset++] = grayColor;
- rgbData[offset++] = grayColor;
- }
- return rgbData;
- } else if (this.numComponents === 3 && this._isColorConversionNeeded()) {
- return this._convertYccToRgb(data);
- } else if (this.numComponents === 4) {
- if (this._isColorConversionNeeded()) {
- if (forceRGBoutput) {
- return this._convertYcckToRgb(data);
- } else {
- return this._convertYcckToCmyk(data);
- }
- } else if (forceRGBoutput) {
- return this._convertCmykToRgb(data);
- }
- }
- return data;
- }
- };
- return JpegImage;
- }();
- exports.JpegImage = JpegImage;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreJpx = {}, root.pdfjsSharedUtil, root.pdfjsCoreArithmeticDecoder);
- }(this, function (exports, sharedUtil, coreArithmeticDecoder) {
- var info = sharedUtil.info;
- var warn = sharedUtil.warn;
- var error = sharedUtil.error;
- var log2 = sharedUtil.log2;
- var readUint16 = sharedUtil.readUint16;
- var readUint32 = sharedUtil.readUint32;
- var ArithmeticDecoder = coreArithmeticDecoder.ArithmeticDecoder;
- var JpxImage = function JpxImageClosure() {
- // Table E.1
- var SubbandsGainLog2 = {
- 'LL': 0,
- 'LH': 1,
- 'HL': 1,
- 'HH': 2
- };
- function JpxImage() {
- this.failOnCorruptedImage = false;
- }
- JpxImage.prototype = {
- parse: function JpxImage_parse(data) {
- var head = readUint16(data, 0);
- // No box header, immediate start of codestream (SOC)
- if (head === 0xFF4F) {
- this.parseCodestream(data, 0, data.length);
- return;
- }
- var position = 0, length = data.length;
- while (position < length) {
- var headerSize = 8;
- var lbox = readUint32(data, position);
- var tbox = readUint32(data, position + 4);
- position += headerSize;
- if (lbox === 1) {
- // XLBox: read UInt64 according to spec.
- // JavaScript's int precision of 53 bit should be sufficient here.
- lbox = readUint32(data, position) * 4294967296 + readUint32(data, position + 4);
- position += 8;
- headerSize += 8;
- }
- if (lbox === 0) {
- lbox = length - position + headerSize;
- }
- if (lbox < headerSize) {
- error('JPX Error: Invalid box field size');
- }
- var dataLength = lbox - headerSize;
- var jumpDataLength = true;
- switch (tbox) {
- case 0x6A703268:
- // 'jp2h'
- jumpDataLength = false;
- // parsing child boxes
- break;
- case 0x636F6C72:
- // 'colr'
- // Colorspaces are not used, the CS from the PDF is used.
- var method = data[position];
- if (method === 1) {
- // enumerated colorspace
- var colorspace = readUint32(data, position + 3);
- switch (colorspace) {
- case 16:
- // this indicates a sRGB colorspace
- case 17:
- // this indicates a grayscale colorspace
- case 18:
- // this indicates a YUV colorspace
- break;
- default:
- warn('Unknown colorspace ' + colorspace);
- break;
- }
- } else if (method === 2) {
- info('ICC profile not supported');
- }
- break;
- case 0x6A703263:
- // 'jp2c'
- this.parseCodestream(data, position, position + dataLength);
- break;
- case 0x6A502020:
- // 'jP\024\024'
- if (0x0d0a870a !== readUint32(data, position)) {
- warn('Invalid JP2 signature');
- }
- break;
- // The following header types are valid but currently not used:
- case 0x6A501A1A:
- // 'jP\032\032'
- case 0x66747970:
- // 'ftyp'
- case 0x72726571:
- // 'rreq'
- case 0x72657320:
- // 'res '
- case 0x69686472:
- // 'ihdr'
- break;
- default:
- var headerType = String.fromCharCode(tbox >> 24 & 0xFF, tbox >> 16 & 0xFF, tbox >> 8 & 0xFF, tbox & 0xFF);
- warn('Unsupported header type ' + tbox + ' (' + headerType + ')');
- break;
- }
- if (jumpDataLength) {
- position += dataLength;
- }
- }
- },
- parseImageProperties: function JpxImage_parseImageProperties(stream) {
- var newByte = stream.getByte();
- while (newByte >= 0) {
- var oldByte = newByte;
- newByte = stream.getByte();
- var code = oldByte << 8 | newByte;
- // Image and tile size (SIZ)
- if (code === 0xFF51) {
- stream.skip(4);
- var Xsiz = stream.getInt32() >>> 0;
- // Byte 4
- var Ysiz = stream.getInt32() >>> 0;
- // Byte 8
- var XOsiz = stream.getInt32() >>> 0;
- // Byte 12
- var YOsiz = stream.getInt32() >>> 0;
- // Byte 16
- stream.skip(16);
- var Csiz = stream.getUint16();
- // Byte 36
- this.width = Xsiz - XOsiz;
- this.height = Ysiz - YOsiz;
- this.componentsCount = Csiz;
- // Results are always returned as Uint8Arrays
- this.bitsPerComponent = 8;
- return;
- }
- }
- error('JPX Error: No size marker found in JPX stream');
- },
- parseCodestream: function JpxImage_parseCodestream(data, start, end) {
- var context = {};
- var doNotRecover = false;
- try {
- var position = start;
- while (position + 1 < end) {
- var code = readUint16(data, position);
- position += 2;
- var length = 0, j, sqcd, spqcds, spqcdSize, scalarExpounded, tile;
- switch (code) {
- case 0xFF4F:
- // Start of codestream (SOC)
- context.mainHeader = true;
- break;
- case 0xFFD9:
- // End of codestream (EOC)
- break;
- case 0xFF51:
- // Image and tile size (SIZ)
- length = readUint16(data, position);
- var siz = {};
- siz.Xsiz = readUint32(data, position + 4);
- siz.Ysiz = readUint32(data, position + 8);
- siz.XOsiz = readUint32(data, position + 12);
- siz.YOsiz = readUint32(data, position + 16);
- siz.XTsiz = readUint32(data, position + 20);
- siz.YTsiz = readUint32(data, position + 24);
- siz.XTOsiz = readUint32(data, position + 28);
- siz.YTOsiz = readUint32(data, position + 32);
- var componentsCount = readUint16(data, position + 36);
- siz.Csiz = componentsCount;
- var components = [];
- j = position + 38;
- for (var i = 0; i < componentsCount; i++) {
- var component = {
- precision: (data[j] & 0x7F) + 1,
- isSigned: !!(data[j] & 0x80),
- XRsiz: data[j + 1],
- YRsiz: data[j + 1]
- };
- calculateComponentDimensions(component, siz);
- components.push(component);
- }
- context.SIZ = siz;
- context.components = components;
- calculateTileGrids(context, components);
- context.QCC = [];
- context.COC = [];
- break;
- case 0xFF5C:
- // Quantization default (QCD)
- length = readUint16(data, position);
- var qcd = {};
- j = position + 2;
- sqcd = data[j++];
- switch (sqcd & 0x1F) {
- case 0:
- spqcdSize = 8;
- scalarExpounded = true;
- break;
- case 1:
- spqcdSize = 16;
- scalarExpounded = false;
- break;
- case 2:
- spqcdSize = 16;
- scalarExpounded = true;
- break;
- default:
- throw new Error('Invalid SQcd value ' + sqcd);
- }
- qcd.noQuantization = spqcdSize === 8;
- qcd.scalarExpounded = scalarExpounded;
- qcd.guardBits = sqcd >> 5;
- spqcds = [];
- while (j < length + position) {
- var spqcd = {};
- if (spqcdSize === 8) {
- spqcd.epsilon = data[j++] >> 3;
- spqcd.mu = 0;
- } else {
- spqcd.epsilon = data[j] >> 3;
- spqcd.mu = (data[j] & 0x7) << 8 | data[j + 1];
- j += 2;
- }
- spqcds.push(spqcd);
- }
- qcd.SPqcds = spqcds;
- if (context.mainHeader) {
- context.QCD = qcd;
- } else {
- context.currentTile.QCD = qcd;
- context.currentTile.QCC = [];
- }
- break;
- case 0xFF5D:
- // Quantization component (QCC)
- length = readUint16(data, position);
- var qcc = {};
- j = position + 2;
- var cqcc;
- if (context.SIZ.Csiz < 257) {
- cqcc = data[j++];
- } else {
- cqcc = readUint16(data, j);
- j += 2;
- }
- sqcd = data[j++];
- switch (sqcd & 0x1F) {
- case 0:
- spqcdSize = 8;
- scalarExpounded = true;
- break;
- case 1:
- spqcdSize = 16;
- scalarExpounded = false;
- break;
- case 2:
- spqcdSize = 16;
- scalarExpounded = true;
- break;
- default:
- throw new Error('Invalid SQcd value ' + sqcd);
- }
- qcc.noQuantization = spqcdSize === 8;
- qcc.scalarExpounded = scalarExpounded;
- qcc.guardBits = sqcd >> 5;
- spqcds = [];
- while (j < length + position) {
- spqcd = {};
- if (spqcdSize === 8) {
- spqcd.epsilon = data[j++] >> 3;
- spqcd.mu = 0;
- } else {
- spqcd.epsilon = data[j] >> 3;
- spqcd.mu = (data[j] & 0x7) << 8 | data[j + 1];
- j += 2;
- }
- spqcds.push(spqcd);
- }
- qcc.SPqcds = spqcds;
- if (context.mainHeader) {
- context.QCC[cqcc] = qcc;
- } else {
- context.currentTile.QCC[cqcc] = qcc;
- }
- break;
- case 0xFF52:
- // Coding style default (COD)
- length = readUint16(data, position);
- var cod = {};
- j = position + 2;
- var scod = data[j++];
- cod.entropyCoderWithCustomPrecincts = !!(scod & 1);
- cod.sopMarkerUsed = !!(scod & 2);
- cod.ephMarkerUsed = !!(scod & 4);
- cod.progressionOrder = data[j++];
- cod.layersCount = readUint16(data, j);
- j += 2;
- cod.multipleComponentTransform = data[j++];
- cod.decompositionLevelsCount = data[j++];
- cod.xcb = (data[j++] & 0xF) + 2;
- cod.ycb = (data[j++] & 0xF) + 2;
- var blockStyle = data[j++];
- cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1);
- cod.resetContextProbabilities = !!(blockStyle & 2);
- cod.terminationOnEachCodingPass = !!(blockStyle & 4);
- cod.verticalyStripe = !!(blockStyle & 8);
- cod.predictableTermination = !!(blockStyle & 16);
- cod.segmentationSymbolUsed = !!(blockStyle & 32);
- cod.reversibleTransformation = data[j++];
- if (cod.entropyCoderWithCustomPrecincts) {
- var precinctsSizes = [];
- while (j < length + position) {
- var precinctsSize = data[j++];
- precinctsSizes.push({
- PPx: precinctsSize & 0xF,
- PPy: precinctsSize >> 4
- });
- }
- cod.precinctsSizes = precinctsSizes;
- }
- var unsupported = [];
- if (cod.selectiveArithmeticCodingBypass) {
- unsupported.push('selectiveArithmeticCodingBypass');
- }
- if (cod.resetContextProbabilities) {
- unsupported.push('resetContextProbabilities');
- }
- if (cod.terminationOnEachCodingPass) {
- unsupported.push('terminationOnEachCodingPass');
- }
- if (cod.verticalyStripe) {
- unsupported.push('verticalyStripe');
- }
- if (cod.predictableTermination) {
- unsupported.push('predictableTermination');
- }
- if (unsupported.length > 0) {
- doNotRecover = true;
- throw new Error('Unsupported COD options (' + unsupported.join(', ') + ')');
- }
- if (context.mainHeader) {
- context.COD = cod;
- } else {
- context.currentTile.COD = cod;
- context.currentTile.COC = [];
- }
- break;
- case 0xFF90:
- // Start of tile-part (SOT)
- length = readUint16(data, position);
- tile = {};
- tile.index = readUint16(data, position + 2);
- tile.length = readUint32(data, position + 4);
- tile.dataEnd = tile.length + position - 2;
- tile.partIndex = data[position + 8];
- tile.partsCount = data[position + 9];
- context.mainHeader = false;
- if (tile.partIndex === 0) {
- // reset component specific settings
- tile.COD = context.COD;
- tile.COC = context.COC.slice(0);
- // clone of the global COC
- tile.QCD = context.QCD;
- tile.QCC = context.QCC.slice(0);
- }
- // clone of the global COC
- context.currentTile = tile;
- break;
- case 0xFF93:
- // Start of data (SOD)
- tile = context.currentTile;
- if (tile.partIndex === 0) {
- initializeTile(context, tile.index);
- buildPackets(context);
- }
- // moving to the end of the data
- length = tile.dataEnd - position;
- parseTilePackets(context, data, position, length);
- break;
- case 0xFF55:
- // Tile-part lengths, main header (TLM)
- case 0xFF57:
- // Packet length, main header (PLM)
- case 0xFF58:
- // Packet length, tile-part header (PLT)
- case 0xFF64:
- // Comment (COM)
- length = readUint16(data, position);
- // skipping content
- break;
- case 0xFF53:
- // Coding style component (COC)
- throw new Error('Codestream code 0xFF53 (COC) is ' + 'not implemented');
- default:
- throw new Error('Unknown codestream code: ' + code.toString(16));
- }
- position += length;
- }
- } catch (e) {
- if (doNotRecover || this.failOnCorruptedImage) {
- error('JPX Error: ' + e.message);
- } else {
- warn('JPX: Trying to recover from: ' + e.message);
- }
- }
- this.tiles = transformComponents(context);
- this.width = context.SIZ.Xsiz - context.SIZ.XOsiz;
- this.height = context.SIZ.Ysiz - context.SIZ.YOsiz;
- this.componentsCount = context.SIZ.Csiz;
- }
- };
- function calculateComponentDimensions(component, siz) {
- // Section B.2 Component mapping
- component.x0 = Math.ceil(siz.XOsiz / component.XRsiz);
- component.x1 = Math.ceil(siz.Xsiz / component.XRsiz);
- component.y0 = Math.ceil(siz.YOsiz / component.YRsiz);
- component.y1 = Math.ceil(siz.Ysiz / component.YRsiz);
- component.width = component.x1 - component.x0;
- component.height = component.y1 - component.y0;
- }
- function calculateTileGrids(context, components) {
- var siz = context.SIZ;
- // Section B.3 Division into tile and tile-components
- var tile, tiles = [];
- var numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz);
- var numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz);
- for (var q = 0; q < numYtiles; q++) {
- for (var p = 0; p < numXtiles; p++) {
- tile = {};
- tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz);
- tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz);
- tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz);
- tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz);
- tile.width = tile.tx1 - tile.tx0;
- tile.height = tile.ty1 - tile.ty0;
- tile.components = [];
- tiles.push(tile);
- }
- }
- context.tiles = tiles;
- var componentsCount = siz.Csiz;
- for (var i = 0, ii = componentsCount; i < ii; i++) {
- var component = components[i];
- for (var j = 0, jj = tiles.length; j < jj; j++) {
- var tileComponent = {};
- tile = tiles[j];
- tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz);
- tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz);
- tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz);
- tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz);
- tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0;
- tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0;
- tile.components[i] = tileComponent;
- }
- }
- }
- function getBlocksDimensions(context, component, r) {
- var codOrCoc = component.codingStyleParameters;
- var result = {};
- if (!codOrCoc.entropyCoderWithCustomPrecincts) {
- result.PPx = 15;
- result.PPy = 15;
- } else {
- result.PPx = codOrCoc.precinctsSizes[r].PPx;
- result.PPy = codOrCoc.precinctsSizes[r].PPy;
- }
- // calculate codeblock size as described in section B.7
- result.xcb_ = r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) : Math.min(codOrCoc.xcb, result.PPx);
- result.ycb_ = r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) : Math.min(codOrCoc.ycb, result.PPy);
- return result;
- }
- function buildPrecincts(context, resolution, dimensions) {
- // Section B.6 Division resolution to precincts
- var precinctWidth = 1 << dimensions.PPx;
- var precinctHeight = 1 << dimensions.PPy;
- // Jasper introduces codeblock groups for mapping each subband codeblocks
- // to precincts. Precinct partition divides a resolution according to width
- // and height parameters. The subband that belongs to the resolution level
- // has a different size than the level, unless it is the zero resolution.
- // From Jasper documentation: jpeg2000.pdf, section K: Tier-2 coding:
- // The precinct partitioning for a particular subband is derived from a
- // partitioning of its parent LL band (i.e., the LL band at the next higher
- // resolution level)... The LL band associated with each resolution level is
- // divided into precincts... Each of the resulting precinct regions is then
- // mapped into its child subbands (if any) at the next lower resolution
- // level. This is accomplished by using the coordinate transformation
- // (u, v) = (ceil(x/2), ceil(y/2)) where (x, y) and (u, v) are the
- // coordinates of a point in the LL band and child subband, respectively.
- var isZeroRes = resolution.resLevel === 0;
- var precinctWidthInSubband = 1 << dimensions.PPx + (isZeroRes ? 0 : -1);
- var precinctHeightInSubband = 1 << dimensions.PPy + (isZeroRes ? 0 : -1);
- var numprecinctswide = resolution.trx1 > resolution.trx0 ? Math.ceil(resolution.trx1 / precinctWidth) - Math.floor(resolution.trx0 / precinctWidth) : 0;
- var numprecinctshigh = resolution.try1 > resolution.try0 ? Math.ceil(resolution.try1 / precinctHeight) - Math.floor(resolution.try0 / precinctHeight) : 0;
- var numprecincts = numprecinctswide * numprecinctshigh;
- resolution.precinctParameters = {
- precinctWidth: precinctWidth,
- precinctHeight: precinctHeight,
- numprecinctswide: numprecinctswide,
- numprecinctshigh: numprecinctshigh,
- numprecincts: numprecincts,
- precinctWidthInSubband: precinctWidthInSubband,
- precinctHeightInSubband: precinctHeightInSubband
- };
- }
- function buildCodeblocks(context, subband, dimensions) {
- // Section B.7 Division sub-band into code-blocks
- var xcb_ = dimensions.xcb_;
- var ycb_ = dimensions.ycb_;
- var codeblockWidth = 1 << xcb_;
- var codeblockHeight = 1 << ycb_;
- var cbx0 = subband.tbx0 >> xcb_;
- var cby0 = subband.tby0 >> ycb_;
- var cbx1 = subband.tbx1 + codeblockWidth - 1 >> xcb_;
- var cby1 = subband.tby1 + codeblockHeight - 1 >> ycb_;
- var precinctParameters = subband.resolution.precinctParameters;
- var codeblocks = [];
- var precincts = [];
- var i, j, codeblock, precinctNumber;
- for (j = cby0; j < cby1; j++) {
- for (i = cbx0; i < cbx1; i++) {
- codeblock = {
- cbx: i,
- cby: j,
- tbx0: codeblockWidth * i,
- tby0: codeblockHeight * j,
- tbx1: codeblockWidth * (i + 1),
- tby1: codeblockHeight * (j + 1)
- };
- codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0);
- codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0);
- codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1);
- codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1);
- // Calculate precinct number for this codeblock, codeblock position
- // should be relative to its subband, use actual dimension and position
- // See comment about codeblock group width and height
- var pi = Math.floor((codeblock.tbx0_ - subband.tbx0) / precinctParameters.precinctWidthInSubband);
- var pj = Math.floor((codeblock.tby0_ - subband.tby0) / precinctParameters.precinctHeightInSubband);
- precinctNumber = pi + pj * precinctParameters.numprecinctswide;
- codeblock.precinctNumber = precinctNumber;
- codeblock.subbandType = subband.type;
- codeblock.Lblock = 3;
- if (codeblock.tbx1_ <= codeblock.tbx0_ || codeblock.tby1_ <= codeblock.tby0_) {
- continue;
- }
- codeblocks.push(codeblock);
- // building precinct for the sub-band
- var precinct = precincts[precinctNumber];
- if (precinct !== undefined) {
- if (i < precinct.cbxMin) {
- precinct.cbxMin = i;
- } else if (i > precinct.cbxMax) {
- precinct.cbxMax = i;
- }
- if (j < precinct.cbyMin) {
- precinct.cbxMin = j;
- } else if (j > precinct.cbyMax) {
- precinct.cbyMax = j;
- }
- } else {
- precincts[precinctNumber] = precinct = {
- cbxMin: i,
- cbyMin: j,
- cbxMax: i,
- cbyMax: j
- };
- }
- codeblock.precinct = precinct;
- }
- }
- subband.codeblockParameters = {
- codeblockWidth: xcb_,
- codeblockHeight: ycb_,
- numcodeblockwide: cbx1 - cbx0 + 1,
- numcodeblockhigh: cby1 - cby0 + 1
- };
- subband.codeblocks = codeblocks;
- subband.precincts = precincts;
- }
- function createPacket(resolution, precinctNumber, layerNumber) {
- var precinctCodeblocks = [];
- // Section B.10.8 Order of info in packet
- var subbands = resolution.subbands;
- // sub-bands already ordered in 'LL', 'HL', 'LH', and 'HH' sequence
- for (var i = 0, ii = subbands.length; i < ii; i++) {
- var subband = subbands[i];
- var codeblocks = subband.codeblocks;
- for (var j = 0, jj = codeblocks.length; j < jj; j++) {
- var codeblock = codeblocks[j];
- if (codeblock.precinctNumber !== precinctNumber) {
- continue;
- }
- precinctCodeblocks.push(codeblock);
- }
- }
- return {
- layerNumber: layerNumber,
- codeblocks: precinctCodeblocks
- };
- }
- function LayerResolutionComponentPositionIterator(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var layersCount = tile.codingStyleDefaultParameters.layersCount;
- var componentsCount = siz.Csiz;
- var maxDecompositionLevelsCount = 0;
- for (var q = 0; q < componentsCount; q++) {
- maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount);
- }
- var l = 0, r = 0, i = 0, k = 0;
- this.nextPacket = function JpxImage_nextPacket() {
- // Section B.12.1.1 Layer-resolution-component-position
- for (; l < layersCount; l++) {
- for (; r <= maxDecompositionLevelsCount; r++) {
- for (; i < componentsCount; i++) {
- var component = tile.components[i];
- if (r > component.codingStyleParameters.decompositionLevelsCount) {
- continue;
- }
- var resolution = component.resolutions[r];
- var numprecincts = resolution.precinctParameters.numprecincts;
- for (; k < numprecincts;) {
- var packet = createPacket(resolution, k, l);
- k++;
- return packet;
- }
- k = 0;
- }
- i = 0;
- }
- r = 0;
- }
- error('JPX Error: Out of packets');
- };
- }
- function ResolutionLayerComponentPositionIterator(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var layersCount = tile.codingStyleDefaultParameters.layersCount;
- var componentsCount = siz.Csiz;
- var maxDecompositionLevelsCount = 0;
- for (var q = 0; q < componentsCount; q++) {
- maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount);
- }
- var r = 0, l = 0, i = 0, k = 0;
- this.nextPacket = function JpxImage_nextPacket() {
- // Section B.12.1.2 Resolution-layer-component-position
- for (; r <= maxDecompositionLevelsCount; r++) {
- for (; l < layersCount; l++) {
- for (; i < componentsCount; i++) {
- var component = tile.components[i];
- if (r > component.codingStyleParameters.decompositionLevelsCount) {
- continue;
- }
- var resolution = component.resolutions[r];
- var numprecincts = resolution.precinctParameters.numprecincts;
- for (; k < numprecincts;) {
- var packet = createPacket(resolution, k, l);
- k++;
- return packet;
- }
- k = 0;
- }
- i = 0;
- }
- l = 0;
- }
- error('JPX Error: Out of packets');
- };
- }
- function ResolutionPositionComponentLayerIterator(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var layersCount = tile.codingStyleDefaultParameters.layersCount;
- var componentsCount = siz.Csiz;
- var l, r, c, p;
- var maxDecompositionLevelsCount = 0;
- for (c = 0; c < componentsCount; c++) {
- var component = tile.components[c];
- maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, component.codingStyleParameters.decompositionLevelsCount);
- }
- var maxNumPrecinctsInLevel = new Int32Array(maxDecompositionLevelsCount + 1);
- for (r = 0; r <= maxDecompositionLevelsCount; ++r) {
- var maxNumPrecincts = 0;
- for (c = 0; c < componentsCount; ++c) {
- var resolutions = tile.components[c].resolutions;
- if (r < resolutions.length) {
- maxNumPrecincts = Math.max(maxNumPrecincts, resolutions[r].precinctParameters.numprecincts);
- }
- }
- maxNumPrecinctsInLevel[r] = maxNumPrecincts;
- }
- l = 0;
- r = 0;
- c = 0;
- p = 0;
- this.nextPacket = function JpxImage_nextPacket() {
- // Section B.12.1.3 Resolution-position-component-layer
- for (; r <= maxDecompositionLevelsCount; r++) {
- for (; p < maxNumPrecinctsInLevel[r]; p++) {
- for (; c < componentsCount; c++) {
- var component = tile.components[c];
- if (r > component.codingStyleParameters.decompositionLevelsCount) {
- continue;
- }
- var resolution = component.resolutions[r];
- var numprecincts = resolution.precinctParameters.numprecincts;
- if (p >= numprecincts) {
- continue;
- }
- for (; l < layersCount;) {
- var packet = createPacket(resolution, p, l);
- l++;
- return packet;
- }
- l = 0;
- }
- c = 0;
- }
- p = 0;
- }
- error('JPX Error: Out of packets');
- };
- }
- function PositionComponentResolutionLayerIterator(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var layersCount = tile.codingStyleDefaultParameters.layersCount;
- var componentsCount = siz.Csiz;
- var precinctsSizes = getPrecinctSizesInImageScale(tile);
- var precinctsIterationSizes = precinctsSizes;
- var l = 0, r = 0, c = 0, px = 0, py = 0;
- this.nextPacket = function JpxImage_nextPacket() {
- // Section B.12.1.4 Position-component-resolution-layer
- for (; py < precinctsIterationSizes.maxNumHigh; py++) {
- for (; px < precinctsIterationSizes.maxNumWide; px++) {
- for (; c < componentsCount; c++) {
- var component = tile.components[c];
- var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
- for (; r <= decompositionLevelsCount; r++) {
- var resolution = component.resolutions[r];
- var sizeInImageScale = precinctsSizes.components[c].resolutions[r];
- var k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution);
- if (k === null) {
- continue;
- }
- for (; l < layersCount;) {
- var packet = createPacket(resolution, k, l);
- l++;
- return packet;
- }
- l = 0;
- }
- r = 0;
- }
- c = 0;
- }
- px = 0;
- }
- error('JPX Error: Out of packets');
- };
- }
- function ComponentPositionResolutionLayerIterator(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var layersCount = tile.codingStyleDefaultParameters.layersCount;
- var componentsCount = siz.Csiz;
- var precinctsSizes = getPrecinctSizesInImageScale(tile);
- var l = 0, r = 0, c = 0, px = 0, py = 0;
- this.nextPacket = function JpxImage_nextPacket() {
- // Section B.12.1.5 Component-position-resolution-layer
- for (; c < componentsCount; ++c) {
- var component = tile.components[c];
- var precinctsIterationSizes = precinctsSizes.components[c];
- var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
- for (; py < precinctsIterationSizes.maxNumHigh; py++) {
- for (; px < precinctsIterationSizes.maxNumWide; px++) {
- for (; r <= decompositionLevelsCount; r++) {
- var resolution = component.resolutions[r];
- var sizeInImageScale = precinctsIterationSizes.resolutions[r];
- var k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution);
- if (k === null) {
- continue;
- }
- for (; l < layersCount;) {
- var packet = createPacket(resolution, k, l);
- l++;
- return packet;
- }
- l = 0;
- }
- r = 0;
- }
- px = 0;
- }
- py = 0;
- }
- error('JPX Error: Out of packets');
- };
- }
- function getPrecinctIndexIfExist(pxIndex, pyIndex, sizeInImageScale, precinctIterationSizes, resolution) {
- var posX = pxIndex * precinctIterationSizes.minWidth;
- var posY = pyIndex * precinctIterationSizes.minHeight;
- if (posX % sizeInImageScale.width !== 0 || posY % sizeInImageScale.height !== 0) {
- return null;
- }
- var startPrecinctRowIndex = posY / sizeInImageScale.width * resolution.precinctParameters.numprecinctswide;
- return posX / sizeInImageScale.height + startPrecinctRowIndex;
- }
- function getPrecinctSizesInImageScale(tile) {
- var componentsCount = tile.components.length;
- var minWidth = Number.MAX_VALUE;
- var minHeight = Number.MAX_VALUE;
- var maxNumWide = 0;
- var maxNumHigh = 0;
- var sizePerComponent = new Array(componentsCount);
- for (var c = 0; c < componentsCount; c++) {
- var component = tile.components[c];
- var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
- var sizePerResolution = new Array(decompositionLevelsCount + 1);
- var minWidthCurrentComponent = Number.MAX_VALUE;
- var minHeightCurrentComponent = Number.MAX_VALUE;
- var maxNumWideCurrentComponent = 0;
- var maxNumHighCurrentComponent = 0;
- var scale = 1;
- for (var r = decompositionLevelsCount; r >= 0; --r) {
- var resolution = component.resolutions[r];
- var widthCurrentResolution = scale * resolution.precinctParameters.precinctWidth;
- var heightCurrentResolution = scale * resolution.precinctParameters.precinctHeight;
- minWidthCurrentComponent = Math.min(minWidthCurrentComponent, widthCurrentResolution);
- minHeightCurrentComponent = Math.min(minHeightCurrentComponent, heightCurrentResolution);
- maxNumWideCurrentComponent = Math.max(maxNumWideCurrentComponent, resolution.precinctParameters.numprecinctswide);
- maxNumHighCurrentComponent = Math.max(maxNumHighCurrentComponent, resolution.precinctParameters.numprecinctshigh);
- sizePerResolution[r] = {
- width: widthCurrentResolution,
- height: heightCurrentResolution
- };
- scale <<= 1;
- }
- minWidth = Math.min(minWidth, minWidthCurrentComponent);
- minHeight = Math.min(minHeight, minHeightCurrentComponent);
- maxNumWide = Math.max(maxNumWide, maxNumWideCurrentComponent);
- maxNumHigh = Math.max(maxNumHigh, maxNumHighCurrentComponent);
- sizePerComponent[c] = {
- resolutions: sizePerResolution,
- minWidth: minWidthCurrentComponent,
- minHeight: minHeightCurrentComponent,
- maxNumWide: maxNumWideCurrentComponent,
- maxNumHigh: maxNumHighCurrentComponent
- };
- }
- return {
- components: sizePerComponent,
- minWidth: minWidth,
- minHeight: minHeight,
- maxNumWide: maxNumWide,
- maxNumHigh: maxNumHigh
- };
- }
- function buildPackets(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var componentsCount = siz.Csiz;
- // Creating resolutions and sub-bands for each component
- for (var c = 0; c < componentsCount; c++) {
- var component = tile.components[c];
- var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
- // Section B.5 Resolution levels and sub-bands
- var resolutions = [];
- var subbands = [];
- for (var r = 0; r <= decompositionLevelsCount; r++) {
- var blocksDimensions = getBlocksDimensions(context, component, r);
- var resolution = {};
- var scale = 1 << decompositionLevelsCount - r;
- resolution.trx0 = Math.ceil(component.tcx0 / scale);
- resolution.try0 = Math.ceil(component.tcy0 / scale);
- resolution.trx1 = Math.ceil(component.tcx1 / scale);
- resolution.try1 = Math.ceil(component.tcy1 / scale);
- resolution.resLevel = r;
- buildPrecincts(context, resolution, blocksDimensions);
- resolutions.push(resolution);
- var subband;
- if (r === 0) {
- // one sub-band (LL) with last decomposition
- subband = {};
- subband.type = 'LL';
- subband.tbx0 = Math.ceil(component.tcx0 / scale);
- subband.tby0 = Math.ceil(component.tcy0 / scale);
- subband.tbx1 = Math.ceil(component.tcx1 / scale);
- subband.tby1 = Math.ceil(component.tcy1 / scale);
- subband.resolution = resolution;
- buildCodeblocks(context, subband, blocksDimensions);
- subbands.push(subband);
- resolution.subbands = [subband];
- } else {
- var bscale = 1 << decompositionLevelsCount - r + 1;
- var resolutionSubbands = [];
- // three sub-bands (HL, LH and HH) with rest of decompositions
- subband = {};
- subband.type = 'HL';
- subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
- subband.tby0 = Math.ceil(component.tcy0 / bscale);
- subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
- subband.tby1 = Math.ceil(component.tcy1 / bscale);
- subband.resolution = resolution;
- buildCodeblocks(context, subband, blocksDimensions);
- subbands.push(subband);
- resolutionSubbands.push(subband);
- subband = {};
- subband.type = 'LH';
- subband.tbx0 = Math.ceil(component.tcx0 / bscale);
- subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
- subband.tbx1 = Math.ceil(component.tcx1 / bscale);
- subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
- subband.resolution = resolution;
- buildCodeblocks(context, subband, blocksDimensions);
- subbands.push(subband);
- resolutionSubbands.push(subband);
- subband = {};
- subband.type = 'HH';
- subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
- subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
- subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
- subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
- subband.resolution = resolution;
- buildCodeblocks(context, subband, blocksDimensions);
- subbands.push(subband);
- resolutionSubbands.push(subband);
- resolution.subbands = resolutionSubbands;
- }
- }
- component.resolutions = resolutions;
- component.subbands = subbands;
- }
- // Generate the packets sequence
- var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder;
- switch (progressionOrder) {
- case 0:
- tile.packetsIterator = new LayerResolutionComponentPositionIterator(context);
- break;
- case 1:
- tile.packetsIterator = new ResolutionLayerComponentPositionIterator(context);
- break;
- case 2:
- tile.packetsIterator = new ResolutionPositionComponentLayerIterator(context);
- break;
- case 3:
- tile.packetsIterator = new PositionComponentResolutionLayerIterator(context);
- break;
- case 4:
- tile.packetsIterator = new ComponentPositionResolutionLayerIterator(context);
- break;
- default:
- error('JPX Error: Unsupported progression order ' + progressionOrder);
- }
- }
- function parseTilePackets(context, data, offset, dataLength) {
- var position = 0;
- var buffer, bufferSize = 0, skipNextBit = false;
- function readBits(count) {
- while (bufferSize < count) {
- var b = data[offset + position];
- position++;
- if (skipNextBit) {
- buffer = buffer << 7 | b;
- bufferSize += 7;
- skipNextBit = false;
- } else {
- buffer = buffer << 8 | b;
- bufferSize += 8;
- }
- if (b === 0xFF) {
- skipNextBit = true;
- }
- }
- bufferSize -= count;
- return buffer >>> bufferSize & (1 << count) - 1;
- }
- function skipMarkerIfEqual(value) {
- if (data[offset + position - 1] === 0xFF && data[offset + position] === value) {
- skipBytes(1);
- return true;
- } else if (data[offset + position] === 0xFF && data[offset + position + 1] === value) {
- skipBytes(2);
- return true;
- }
- return false;
- }
- function skipBytes(count) {
- position += count;
- }
- function alignToByte() {
- bufferSize = 0;
- if (skipNextBit) {
- position++;
- skipNextBit = false;
- }
- }
- function readCodingpasses() {
- if (readBits(1) === 0) {
- return 1;
- }
- if (readBits(1) === 0) {
- return 2;
- }
- var value = readBits(2);
- if (value < 3) {
- return value + 3;
- }
- value = readBits(5);
- if (value < 31) {
- return value + 6;
- }
- value = readBits(7);
- return value + 37;
- }
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var sopMarkerUsed = context.COD.sopMarkerUsed;
- var ephMarkerUsed = context.COD.ephMarkerUsed;
- var packetsIterator = tile.packetsIterator;
- while (position < dataLength) {
- alignToByte();
- if (sopMarkerUsed && skipMarkerIfEqual(0x91)) {
- // Skip also marker segment length and packet sequence ID
- skipBytes(4);
- }
- var packet = packetsIterator.nextPacket();
- if (!readBits(1)) {
- continue;
- }
- var layerNumber = packet.layerNumber;
- var queue = [], codeblock;
- for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) {
- codeblock = packet.codeblocks[i];
- var precinct = codeblock.precinct;
- var codeblockColumn = codeblock.cbx - precinct.cbxMin;
- var codeblockRow = codeblock.cby - precinct.cbyMin;
- var codeblockIncluded = false;
- var firstTimeInclusion = false;
- var valueReady;
- if (codeblock['included'] !== undefined) {
- codeblockIncluded = !!readBits(1);
- } else {
- // reading inclusion tree
- precinct = codeblock.precinct;
- var inclusionTree, zeroBitPlanesTree;
- if (precinct['inclusionTree'] !== undefined) {
- inclusionTree = precinct.inclusionTree;
- } else {
- // building inclusion and zero bit-planes trees
- var width = precinct.cbxMax - precinct.cbxMin + 1;
- var height = precinct.cbyMax - precinct.cbyMin + 1;
- inclusionTree = new InclusionTree(width, height, layerNumber);
- zeroBitPlanesTree = new TagTree(width, height);
- precinct.inclusionTree = inclusionTree;
- precinct.zeroBitPlanesTree = zeroBitPlanesTree;
- }
- if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) {
- while (true) {
- if (readBits(1)) {
- valueReady = !inclusionTree.nextLevel();
- if (valueReady) {
- codeblock.included = true;
- codeblockIncluded = firstTimeInclusion = true;
- break;
- }
- } else {
- inclusionTree.incrementValue(layerNumber);
- break;
- }
- }
- }
- }
- if (!codeblockIncluded) {
- continue;
- }
- if (firstTimeInclusion) {
- zeroBitPlanesTree = precinct.zeroBitPlanesTree;
- zeroBitPlanesTree.reset(codeblockColumn, codeblockRow);
- while (true) {
- if (readBits(1)) {
- valueReady = !zeroBitPlanesTree.nextLevel();
- if (valueReady) {
- break;
- }
- } else {
- zeroBitPlanesTree.incrementValue();
- }
- }
- codeblock.zeroBitPlanes = zeroBitPlanesTree.value;
- }
- var codingpasses = readCodingpasses();
- while (readBits(1)) {
- codeblock.Lblock++;
- }
- var codingpassesLog2 = log2(codingpasses);
- // rounding down log2
- var bits = (codingpasses < 1 << codingpassesLog2 ? codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock;
- var codedDataLength = readBits(bits);
- queue.push({
- codeblock: codeblock,
- codingpasses: codingpasses,
- dataLength: codedDataLength
- });
- }
- alignToByte();
- if (ephMarkerUsed) {
- skipMarkerIfEqual(0x92);
- }
- while (queue.length > 0) {
- var packetItem = queue.shift();
- codeblock = packetItem.codeblock;
- if (codeblock['data'] === undefined) {
- codeblock.data = [];
- }
- codeblock.data.push({
- data: data,
- start: offset + position,
- end: offset + position + packetItem.dataLength,
- codingpasses: packetItem.codingpasses
- });
- position += packetItem.dataLength;
- }
- }
- return position;
- }
- function copyCoefficients(coefficients, levelWidth, levelHeight, subband, delta, mb, reversible, segmentationSymbolUsed) {
- var x0 = subband.tbx0;
- var y0 = subband.tby0;
- var width = subband.tbx1 - subband.tbx0;
- var codeblocks = subband.codeblocks;
- var right = subband.type.charAt(0) === 'H' ? 1 : 0;
- var bottom = subband.type.charAt(1) === 'H' ? levelWidth : 0;
- for (var i = 0, ii = codeblocks.length; i < ii; ++i) {
- var codeblock = codeblocks[i];
- var blockWidth = codeblock.tbx1_ - codeblock.tbx0_;
- var blockHeight = codeblock.tby1_ - codeblock.tby0_;
- if (blockWidth === 0 || blockHeight === 0) {
- continue;
- }
- if (codeblock['data'] === undefined) {
- continue;
- }
- var bitModel, currentCodingpassType;
- bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType, codeblock.zeroBitPlanes, mb);
- currentCodingpassType = 2;
- // first bit plane starts from cleanup
- // collect data
- var data = codeblock.data, totalLength = 0, codingpasses = 0;
- var j, jj, dataItem;
- for (j = 0, jj = data.length; j < jj; j++) {
- dataItem = data[j];
- totalLength += dataItem.end - dataItem.start;
- codingpasses += dataItem.codingpasses;
- }
- var encodedData = new Uint8Array(totalLength);
- var position = 0;
- for (j = 0, jj = data.length; j < jj; j++) {
- dataItem = data[j];
- var chunk = dataItem.data.subarray(dataItem.start, dataItem.end);
- encodedData.set(chunk, position);
- position += chunk.length;
- }
- // decoding the item
- var decoder = new ArithmeticDecoder(encodedData, 0, totalLength);
- bitModel.setDecoder(decoder);
- for (j = 0; j < codingpasses; j++) {
- switch (currentCodingpassType) {
- case 0:
- bitModel.runSignificancePropagationPass();
- break;
- case 1:
- bitModel.runMagnitudeRefinementPass();
- break;
- case 2:
- bitModel.runCleanupPass();
- if (segmentationSymbolUsed) {
- bitModel.checkSegmentationSymbol();
- }
- break;
- }
- currentCodingpassType = (currentCodingpassType + 1) % 3;
- }
- var offset = codeblock.tbx0_ - x0 + (codeblock.tby0_ - y0) * width;
- var sign = bitModel.coefficentsSign;
- var magnitude = bitModel.coefficentsMagnitude;
- var bitsDecoded = bitModel.bitsDecoded;
- var magnitudeCorrection = reversible ? 0 : 0.5;
- var k, n, nb;
- position = 0;
- // Do the interleaving of Section F.3.3 here, so we do not need
- // to copy later. LL level is not interleaved, just copied.
- var interleave = subband.type !== 'LL';
- for (j = 0; j < blockHeight; j++) {
- var row = offset / width | 0;
- // row in the non-interleaved subband
- var levelOffset = 2 * row * (levelWidth - width) + right + bottom;
- for (k = 0; k < blockWidth; k++) {
- n = magnitude[position];
- if (n !== 0) {
- n = (n + magnitudeCorrection) * delta;
- if (sign[position] !== 0) {
- n = -n;
- }
- nb = bitsDecoded[position];
- var pos = interleave ? levelOffset + (offset << 1) : offset;
- if (reversible && nb >= mb) {
- coefficients[pos] = n;
- } else {
- coefficients[pos] = n * (1 << mb - nb);
- }
- }
- offset++;
- position++;
- }
- offset += width - blockWidth;
- }
- }
- }
- function transformTile(context, tile, c) {
- var component = tile.components[c];
- var codingStyleParameters = component.codingStyleParameters;
- var quantizationParameters = component.quantizationParameters;
- var decompositionLevelsCount = codingStyleParameters.decompositionLevelsCount;
- var spqcds = quantizationParameters.SPqcds;
- var scalarExpounded = quantizationParameters.scalarExpounded;
- var guardBits = quantizationParameters.guardBits;
- var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed;
- var precision = context.components[c].precision;
- var reversible = codingStyleParameters.reversibleTransformation;
- var transform = reversible ? new ReversibleTransform() : new IrreversibleTransform();
- var subbandCoefficients = [];
- var b = 0;
- for (var i = 0; i <= decompositionLevelsCount; i++) {
- var resolution = component.resolutions[i];
- var width = resolution.trx1 - resolution.trx0;
- var height = resolution.try1 - resolution.try0;
- // Allocate space for the whole sublevel.
- var coefficients = new Float32Array(width * height);
- for (var j = 0, jj = resolution.subbands.length; j < jj; j++) {
- var mu, epsilon;
- if (!scalarExpounded) {
- // formula E-5
- mu = spqcds[0].mu;
- epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0);
- } else {
- mu = spqcds[b].mu;
- epsilon = spqcds[b].epsilon;
- b++;
- }
- var subband = resolution.subbands[j];
- var gainLog2 = SubbandsGainLog2[subband.type];
- // calculate quantization coefficient (Section E.1.1.1)
- var delta = reversible ? 1 : Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048);
- var mb = guardBits + epsilon - 1;
- // In the first resolution level, copyCoefficients will fill the
- // whole array with coefficients. In the succeeding passes,
- // copyCoefficients will consecutively fill in the values that belong
- // to the interleaved positions of the HL, LH, and HH coefficients.
- // The LL coefficients will then be interleaved in Transform.iterate().
- copyCoefficients(coefficients, width, height, subband, delta, mb, reversible, segmentationSymbolUsed);
- }
- subbandCoefficients.push({
- width: width,
- height: height,
- items: coefficients
- });
- }
- var result = transform.calculate(subbandCoefficients, component.tcx0, component.tcy0);
- return {
- left: component.tcx0,
- top: component.tcy0,
- width: result.width,
- height: result.height,
- items: result.items
- };
- }
- function transformComponents(context) {
- var siz = context.SIZ;
- var components = context.components;
- var componentsCount = siz.Csiz;
- var resultImages = [];
- for (var i = 0, ii = context.tiles.length; i < ii; i++) {
- var tile = context.tiles[i];
- var transformedTiles = [];
- var c;
- for (c = 0; c < componentsCount; c++) {
- transformedTiles[c] = transformTile(context, tile, c);
- }
- var tile0 = transformedTiles[0];
- var out = new Uint8Array(tile0.items.length * componentsCount);
- var result = {
- left: tile0.left,
- top: tile0.top,
- width: tile0.width,
- height: tile0.height,
- items: out
- };
- // Section G.2.2 Inverse multi component transform
- var shift, offset, max, min, maxK;
- var pos = 0, j, jj, y0, y1, y2, r, g, b, k, val;
- if (tile.codingStyleDefaultParameters.multipleComponentTransform) {
- var fourComponents = componentsCount === 4;
- var y0items = transformedTiles[0].items;
- var y1items = transformedTiles[1].items;
- var y2items = transformedTiles[2].items;
- var y3items = fourComponents ? transformedTiles[3].items : null;
- // HACK: The multiple component transform formulas below assume that
- // all components have the same precision. With this in mind, we
- // compute shift and offset only once.
- shift = components[0].precision - 8;
- offset = (128 << shift) + 0.5;
- max = 255 * (1 << shift);
- maxK = max * 0.5;
- min = -maxK;
- var component0 = tile.components[0];
- var alpha01 = componentsCount - 3;
- jj = y0items.length;
- if (!component0.codingStyleParameters.reversibleTransformation) {
- // inverse irreversible multiple component transform
- for (j = 0; j < jj; j++, pos += alpha01) {
- y0 = y0items[j] + offset;
- y1 = y1items[j];
- y2 = y2items[j];
- r = y0 + 1.402 * y2;
- g = y0 - 0.34413 * y1 - 0.71414 * y2;
- b = y0 + 1.772 * y1;
- out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift;
- out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift;
- out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift;
- }
- } else {
- // inverse reversible multiple component transform
- for (j = 0; j < jj; j++, pos += alpha01) {
- y0 = y0items[j] + offset;
- y1 = y1items[j];
- y2 = y2items[j];
- g = y0 - (y2 + y1 >> 2);
- r = g + y2;
- b = g + y1;
- out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift;
- out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift;
- out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift;
- }
- }
- if (fourComponents) {
- for (j = 0, pos = 3; j < jj; j++, pos += 4) {
- k = y3items[j];
- out[pos] = k <= min ? 0 : k >= maxK ? 255 : k + offset >> shift;
- }
- }
- } else {
- // no multi-component transform
- for (c = 0; c < componentsCount; c++) {
- var items = transformedTiles[c].items;
- shift = components[c].precision - 8;
- offset = (128 << shift) + 0.5;
- max = 127.5 * (1 << shift);
- min = -max;
- for (pos = c, j = 0, jj = items.length; j < jj; j++) {
- val = items[j];
- out[pos] = val <= min ? 0 : val >= max ? 255 : val + offset >> shift;
- pos += componentsCount;
- }
- }
- }
- resultImages.push(result);
- }
- return resultImages;
- }
- function initializeTile(context, tileIndex) {
- var siz = context.SIZ;
- var componentsCount = siz.Csiz;
- var tile = context.tiles[tileIndex];
- for (var c = 0; c < componentsCount; c++) {
- var component = tile.components[c];
- var qcdOrQcc = context.currentTile.QCC[c] !== undefined ? context.currentTile.QCC[c] : context.currentTile.QCD;
- component.quantizationParameters = qcdOrQcc;
- var codOrCoc = context.currentTile.COC[c] !== undefined ? context.currentTile.COC[c] : context.currentTile.COD;
- component.codingStyleParameters = codOrCoc;
- }
- tile.codingStyleDefaultParameters = context.currentTile.COD;
- }
- // Section B.10.2 Tag trees
- var TagTree = function TagTreeClosure() {
- function TagTree(width, height) {
- var levelsLength = log2(Math.max(width, height)) + 1;
- this.levels = [];
- for (var i = 0; i < levelsLength; i++) {
- var level = {
- width: width,
- height: height,
- items: []
- };
- this.levels.push(level);
- width = Math.ceil(width / 2);
- height = Math.ceil(height / 2);
- }
- }
- TagTree.prototype = {
- reset: function TagTree_reset(i, j) {
- var currentLevel = 0, value = 0, level;
- while (currentLevel < this.levels.length) {
- level = this.levels[currentLevel];
- var index = i + j * level.width;
- if (level.items[index] !== undefined) {
- value = level.items[index];
- break;
- }
- level.index = index;
- i >>= 1;
- j >>= 1;
- currentLevel++;
- }
- currentLevel--;
- level = this.levels[currentLevel];
- level.items[level.index] = value;
- this.currentLevel = currentLevel;
- delete this.value;
- },
- incrementValue: function TagTree_incrementValue() {
- var level = this.levels[this.currentLevel];
- level.items[level.index]++;
- },
- nextLevel: function TagTree_nextLevel() {
- var currentLevel = this.currentLevel;
- var level = this.levels[currentLevel];
- var value = level.items[level.index];
- currentLevel--;
- if (currentLevel < 0) {
- this.value = value;
- return false;
- }
- this.currentLevel = currentLevel;
- level = this.levels[currentLevel];
- level.items[level.index] = value;
- return true;
- }
- };
- return TagTree;
- }();
- var InclusionTree = function InclusionTreeClosure() {
- function InclusionTree(width, height, defaultValue) {
- var levelsLength = log2(Math.max(width, height)) + 1;
- this.levels = [];
- for (var i = 0; i < levelsLength; i++) {
- var items = new Uint8Array(width * height);
- for (var j = 0, jj = items.length; j < jj; j++) {
- items[j] = defaultValue;
- }
- var level = {
- width: width,
- height: height,
- items: items
- };
- this.levels.push(level);
- width = Math.ceil(width / 2);
- height = Math.ceil(height / 2);
- }
- }
- InclusionTree.prototype = {
- reset: function InclusionTree_reset(i, j, stopValue) {
- var currentLevel = 0;
- while (currentLevel < this.levels.length) {
- var level = this.levels[currentLevel];
- var index = i + j * level.width;
- level.index = index;
- var value = level.items[index];
- if (value === 0xFF) {
- break;
- }
- if (value > stopValue) {
- this.currentLevel = currentLevel;
- // already know about this one, propagating the value to top levels
- this.propagateValues();
- return false;
- }
- i >>= 1;
- j >>= 1;
- currentLevel++;
- }
- this.currentLevel = currentLevel - 1;
- return true;
- },
- incrementValue: function InclusionTree_incrementValue(stopValue) {
- var level = this.levels[this.currentLevel];
- level.items[level.index] = stopValue + 1;
- this.propagateValues();
- },
- propagateValues: function InclusionTree_propagateValues() {
- var levelIndex = this.currentLevel;
- var level = this.levels[levelIndex];
- var currentValue = level.items[level.index];
- while (--levelIndex >= 0) {
- level = this.levels[levelIndex];
- level.items[level.index] = currentValue;
- }
- },
- nextLevel: function InclusionTree_nextLevel() {
- var currentLevel = this.currentLevel;
- var level = this.levels[currentLevel];
- var value = level.items[level.index];
- level.items[level.index] = 0xFF;
- currentLevel--;
- if (currentLevel < 0) {
- return false;
- }
- this.currentLevel = currentLevel;
- level = this.levels[currentLevel];
- level.items[level.index] = value;
- return true;
- }
- };
- return InclusionTree;
- }();
- // Section D. Coefficient bit modeling
- var BitModel = function BitModelClosure() {
- var UNIFORM_CONTEXT = 17;
- var RUNLENGTH_CONTEXT = 18;
- // Table D-1
- // The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4),
- // vv - sum of Vi (0..2), and hh - sum of Hi (0..2)
- var LLAndLHContextsLabel = new Uint8Array([
- 0,
- 5,
- 8,
- 0,
- 3,
- 7,
- 8,
- 0,
- 4,
- 7,
- 8,
- 0,
- 0,
- 0,
- 0,
- 0,
- 1,
- 6,
- 8,
- 0,
- 3,
- 7,
- 8,
- 0,
- 4,
- 7,
- 8,
- 0,
- 0,
- 0,
- 0,
- 0,
- 2,
- 6,
- 8,
- 0,
- 3,
- 7,
- 8,
- 0,
- 4,
- 7,
- 8,
- 0,
- 0,
- 0,
- 0,
- 0,
- 2,
- 6,
- 8,
- 0,
- 3,
- 7,
- 8,
- 0,
- 4,
- 7,
- 8,
- 0,
- 0,
- 0,
- 0,
- 0,
- 2,
- 6,
- 8,
- 0,
- 3,
- 7,
- 8,
- 0,
- 4,
- 7,
- 8
- ]);
- var HLContextLabel = new Uint8Array([
- 0,
- 3,
- 4,
- 0,
- 5,
- 7,
- 7,
- 0,
- 8,
- 8,
- 8,
- 0,
- 0,
- 0,
- 0,
- 0,
- 1,
- 3,
- 4,
- 0,
- 6,
- 7,
- 7,
- 0,
- 8,
- 8,
- 8,
- 0,
- 0,
- 0,
- 0,
- 0,
- 2,
- 3,
- 4,
- 0,
- 6,
- 7,
- 7,
- 0,
- 8,
- 8,
- 8,
- 0,
- 0,
- 0,
- 0,
- 0,
- 2,
- 3,
- 4,
- 0,
- 6,
- 7,
- 7,
- 0,
- 8,
- 8,
- 8,
- 0,
- 0,
- 0,
- 0,
- 0,
- 2,
- 3,
- 4,
- 0,
- 6,
- 7,
- 7,
- 0,
- 8,
- 8,
- 8
- ]);
- var HHContextLabel = new Uint8Array([
- 0,
- 1,
- 2,
- 0,
- 1,
- 2,
- 2,
- 0,
- 2,
- 2,
- 2,
- 0,
- 0,
- 0,
- 0,
- 0,
- 3,
- 4,
- 5,
- 0,
- 4,
- 5,
- 5,
- 0,
- 5,
- 5,
- 5,
- 0,
- 0,
- 0,
- 0,
- 0,
- 6,
- 7,
- 7,
- 0,
- 7,
- 7,
- 7,
- 0,
- 7,
- 7,
- 7,
- 0,
- 0,
- 0,
- 0,
- 0,
- 8,
- 8,
- 8,
- 0,
- 8,
- 8,
- 8,
- 0,
- 8,
- 8,
- 8,
- 0,
- 0,
- 0,
- 0,
- 0,
- 8,
- 8,
- 8,
- 0,
- 8,
- 8,
- 8,
- 0,
- 8,
- 8,
- 8
- ]);
- function BitModel(width, height, subband, zeroBitPlanes, mb) {
- this.width = width;
- this.height = height;
- this.contextLabelTable = subband === 'HH' ? HHContextLabel : subband === 'HL' ? HLContextLabel : LLAndLHContextsLabel;
- var coefficientCount = width * height;
- // coefficients outside the encoding region treated as insignificant
- // add border state cells for significanceState
- this.neighborsSignificance = new Uint8Array(coefficientCount);
- this.coefficentsSign = new Uint8Array(coefficientCount);
- this.coefficentsMagnitude = mb > 14 ? new Uint32Array(coefficientCount) : mb > 6 ? new Uint16Array(coefficientCount) : new Uint8Array(coefficientCount);
- this.processingFlags = new Uint8Array(coefficientCount);
- var bitsDecoded = new Uint8Array(coefficientCount);
- if (zeroBitPlanes !== 0) {
- for (var i = 0; i < coefficientCount; i++) {
- bitsDecoded[i] = zeroBitPlanes;
- }
- }
- this.bitsDecoded = bitsDecoded;
- this.reset();
- }
- BitModel.prototype = {
- setDecoder: function BitModel_setDecoder(decoder) {
- this.decoder = decoder;
- },
- reset: function BitModel_reset() {
- // We have 17 contexts that are accessed via context labels,
- // plus the uniform and runlength context.
- this.contexts = new Int8Array(19);
- // Contexts are packed into 1 byte:
- // highest 7 bits carry the index, lowest bit carries mps
- this.contexts[0] = 4 << 1 | 0;
- this.contexts[UNIFORM_CONTEXT] = 46 << 1 | 0;
- this.contexts[RUNLENGTH_CONTEXT] = 3 << 1 | 0;
- },
- setNeighborsSignificance: function BitModel_setNeighborsSignificance(row, column, index) {
- var neighborsSignificance = this.neighborsSignificance;
- var width = this.width, height = this.height;
- var left = column > 0;
- var right = column + 1 < width;
- var i;
- if (row > 0) {
- i = index - width;
- if (left) {
- neighborsSignificance[i - 1] += 0x10;
- }
- if (right) {
- neighborsSignificance[i + 1] += 0x10;
- }
- neighborsSignificance[i] += 0x04;
- }
- if (row + 1 < height) {
- i = index + width;
- if (left) {
- neighborsSignificance[i - 1] += 0x10;
- }
- if (right) {
- neighborsSignificance[i + 1] += 0x10;
- }
- neighborsSignificance[i] += 0x04;
- }
- if (left) {
- neighborsSignificance[index - 1] += 0x01;
- }
- if (right) {
- neighborsSignificance[index + 1] += 0x01;
- }
- neighborsSignificance[index] |= 0x80;
- },
- runSignificancePropagationPass: function BitModel_runSignificancePropagationPass() {
- var decoder = this.decoder;
- var width = this.width, height = this.height;
- var coefficentsMagnitude = this.coefficentsMagnitude;
- var coefficentsSign = this.coefficentsSign;
- var neighborsSignificance = this.neighborsSignificance;
- var processingFlags = this.processingFlags;
- var contexts = this.contexts;
- var labels = this.contextLabelTable;
- var bitsDecoded = this.bitsDecoded;
- var processedInverseMask = ~1;
- var processedMask = 1;
- var firstMagnitudeBitMask = 2;
- for (var i0 = 0; i0 < height; i0 += 4) {
- for (var j = 0; j < width; j++) {
- var index = i0 * width + j;
- for (var i1 = 0; i1 < 4; i1++, index += width) {
- var i = i0 + i1;
- if (i >= height) {
- break;
- }
- // clear processed flag first
- processingFlags[index] &= processedInverseMask;
- if (coefficentsMagnitude[index] || !neighborsSignificance[index]) {
- continue;
- }
- var contextLabel = labels[neighborsSignificance[index]];
- var decision = decoder.readBit(contexts, contextLabel);
- if (decision) {
- var sign = this.decodeSignBit(i, j, index);
- coefficentsSign[index] = sign;
- coefficentsMagnitude[index] = 1;
- this.setNeighborsSignificance(i, j, index);
- processingFlags[index] |= firstMagnitudeBitMask;
- }
- bitsDecoded[index]++;
- processingFlags[index] |= processedMask;
- }
- }
- }
- },
- decodeSignBit: function BitModel_decodeSignBit(row, column, index) {
- var width = this.width, height = this.height;
- var coefficentsMagnitude = this.coefficentsMagnitude;
- var coefficentsSign = this.coefficentsSign;
- var contribution, sign0, sign1, significance1;
- var contextLabel, decoded;
- // calculate horizontal contribution
- significance1 = column > 0 && coefficentsMagnitude[index - 1] !== 0;
- if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) {
- sign1 = coefficentsSign[index + 1];
- if (significance1) {
- sign0 = coefficentsSign[index - 1];
- contribution = 1 - sign1 - sign0;
- } else {
- contribution = 1 - sign1 - sign1;
- }
- } else if (significance1) {
- sign0 = coefficentsSign[index - 1];
- contribution = 1 - sign0 - sign0;
- } else {
- contribution = 0;
- }
- var horizontalContribution = 3 * contribution;
- // calculate vertical contribution and combine with the horizontal
- significance1 = row > 0 && coefficentsMagnitude[index - width] !== 0;
- if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) {
- sign1 = coefficentsSign[index + width];
- if (significance1) {
- sign0 = coefficentsSign[index - width];
- contribution = 1 - sign1 - sign0 + horizontalContribution;
- } else {
- contribution = 1 - sign1 - sign1 + horizontalContribution;
- }
- } else if (significance1) {
- sign0 = coefficentsSign[index - width];
- contribution = 1 - sign0 - sign0 + horizontalContribution;
- } else {
- contribution = horizontalContribution;
- }
- if (contribution >= 0) {
- contextLabel = 9 + contribution;
- decoded = this.decoder.readBit(this.contexts, contextLabel);
- } else {
- contextLabel = 9 - contribution;
- decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1;
- }
- return decoded;
- },
- runMagnitudeRefinementPass: function BitModel_runMagnitudeRefinementPass() {
- var decoder = this.decoder;
- var width = this.width, height = this.height;
- var coefficentsMagnitude = this.coefficentsMagnitude;
- var neighborsSignificance = this.neighborsSignificance;
- var contexts = this.contexts;
- var bitsDecoded = this.bitsDecoded;
- var processingFlags = this.processingFlags;
- var processedMask = 1;
- var firstMagnitudeBitMask = 2;
- var length = width * height;
- var width4 = width * 4;
- for (var index0 = 0, indexNext; index0 < length; index0 = indexNext) {
- indexNext = Math.min(length, index0 + width4);
- for (var j = 0; j < width; j++) {
- for (var index = index0 + j; index < indexNext; index += width) {
- // significant but not those that have just become
- if (!coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) {
- continue;
- }
- var contextLabel = 16;
- if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) {
- processingFlags[index] ^= firstMagnitudeBitMask;
- // first refinement
- var significance = neighborsSignificance[index] & 127;
- contextLabel = significance === 0 ? 15 : 14;
- }
- var bit = decoder.readBit(contexts, contextLabel);
- coefficentsMagnitude[index] = coefficentsMagnitude[index] << 1 | bit;
- bitsDecoded[index]++;
- processingFlags[index] |= processedMask;
- }
- }
- }
- },
- runCleanupPass: function BitModel_runCleanupPass() {
- var decoder = this.decoder;
- var width = this.width, height = this.height;
- var neighborsSignificance = this.neighborsSignificance;
- var coefficentsMagnitude = this.coefficentsMagnitude;
- var coefficentsSign = this.coefficentsSign;
- var contexts = this.contexts;
- var labels = this.contextLabelTable;
- var bitsDecoded = this.bitsDecoded;
- var processingFlags = this.processingFlags;
- var processedMask = 1;
- var firstMagnitudeBitMask = 2;
- var oneRowDown = width;
- var twoRowsDown = width * 2;
- var threeRowsDown = width * 3;
- var iNext;
- for (var i0 = 0; i0 < height; i0 = iNext) {
- iNext = Math.min(i0 + 4, height);
- var indexBase = i0 * width;
- var checkAllEmpty = i0 + 3 < height;
- for (var j = 0; j < width; j++) {
- var index0 = indexBase + j;
- // using the property: labels[neighborsSignificance[index]] === 0
- // when neighborsSignificance[index] === 0
- var allEmpty = checkAllEmpty && processingFlags[index0] === 0 && processingFlags[index0 + oneRowDown] === 0 && processingFlags[index0 + twoRowsDown] === 0 && processingFlags[index0 + threeRowsDown] === 0 && neighborsSignificance[index0] === 0 && neighborsSignificance[index0 + oneRowDown] === 0 && neighborsSignificance[index0 + twoRowsDown] === 0 && neighborsSignificance[index0 + threeRowsDown] === 0;
- var i1 = 0, index = index0;
- var i = i0, sign;
- if (allEmpty) {
- var hasSignificantCoefficent = decoder.readBit(contexts, RUNLENGTH_CONTEXT);
- if (!hasSignificantCoefficent) {
- bitsDecoded[index0]++;
- bitsDecoded[index0 + oneRowDown]++;
- bitsDecoded[index0 + twoRowsDown]++;
- bitsDecoded[index0 + threeRowsDown]++;
- continue;
- }
- // next column
- i1 = decoder.readBit(contexts, UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, UNIFORM_CONTEXT);
- if (i1 !== 0) {
- i = i0 + i1;
- index += i1 * width;
- }
- sign = this.decodeSignBit(i, j, index);
- coefficentsSign[index] = sign;
- coefficentsMagnitude[index] = 1;
- this.setNeighborsSignificance(i, j, index);
- processingFlags[index] |= firstMagnitudeBitMask;
- index = index0;
- for (var i2 = i0; i2 <= i; i2++, index += width) {
- bitsDecoded[index]++;
- }
- i1++;
- }
- for (i = i0 + i1; i < iNext; i++, index += width) {
- if (coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) {
- continue;
- }
- var contextLabel = labels[neighborsSignificance[index]];
- var decision = decoder.readBit(contexts, contextLabel);
- if (decision === 1) {
- sign = this.decodeSignBit(i, j, index);
- coefficentsSign[index] = sign;
- coefficentsMagnitude[index] = 1;
- this.setNeighborsSignificance(i, j, index);
- processingFlags[index] |= firstMagnitudeBitMask;
- }
- bitsDecoded[index]++;
- }
- }
- }
- },
- checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() {
- var decoder = this.decoder;
- var contexts = this.contexts;
- var symbol = decoder.readBit(contexts, UNIFORM_CONTEXT) << 3 | decoder.readBit(contexts, UNIFORM_CONTEXT) << 2 | decoder.readBit(contexts, UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, UNIFORM_CONTEXT);
- if (symbol !== 0xA) {
- error('JPX Error: Invalid segmentation symbol');
- }
- }
- };
- return BitModel;
- }();
- // Section F, Discrete wavelet transformation
- var Transform = function TransformClosure() {
- function Transform() {
- }
- Transform.prototype.calculate = function transformCalculate(subbands, u0, v0) {
- var ll = subbands[0];
- for (var i = 1, ii = subbands.length; i < ii; i++) {
- ll = this.iterate(ll, subbands[i], u0, v0);
- }
- return ll;
- };
- Transform.prototype.extend = function extend(buffer, offset, size) {
- // Section F.3.7 extending... using max extension of 4
- var i1 = offset - 1, j1 = offset + 1;
- var i2 = offset + size - 2, j2 = offset + size;
- buffer[i1--] = buffer[j1++];
- buffer[j2++] = buffer[i2--];
- buffer[i1--] = buffer[j1++];
- buffer[j2++] = buffer[i2--];
- buffer[i1--] = buffer[j1++];
- buffer[j2++] = buffer[i2--];
- buffer[i1] = buffer[j1];
- buffer[j2] = buffer[i2];
- };
- Transform.prototype.iterate = function Transform_iterate(ll, hl_lh_hh, u0, v0) {
- var llWidth = ll.width, llHeight = ll.height, llItems = ll.items;
- var width = hl_lh_hh.width;
- var height = hl_lh_hh.height;
- var items = hl_lh_hh.items;
- var i, j, k, l, u, v;
- // Interleave LL according to Section F.3.3
- for (k = 0, i = 0; i < llHeight; i++) {
- l = i * 2 * width;
- for (j = 0; j < llWidth; j++, k++, l += 2) {
- items[l] = llItems[k];
- }
- }
- // The LL band is not needed anymore.
- llItems = ll.items = null;
- var bufferPadding = 4;
- var rowBuffer = new Float32Array(width + 2 * bufferPadding);
- // Section F.3.4 HOR_SR
- if (width === 1) {
- // if width = 1, when u0 even keep items as is, when odd divide by 2
- if ((u0 & 1) !== 0) {
- for (v = 0, k = 0; v < height; v++, k += width) {
- items[k] *= 0.5;
- }
- }
- } else {
- for (v = 0, k = 0; v < height; v++, k += width) {
- rowBuffer.set(items.subarray(k, k + width), bufferPadding);
- this.extend(rowBuffer, bufferPadding, width);
- this.filter(rowBuffer, bufferPadding, width);
- items.set(rowBuffer.subarray(bufferPadding, bufferPadding + width), k);
- }
- }
- // Accesses to the items array can take long, because it may not fit into
- // CPU cache and has to be fetched from main memory. Since subsequent
- // accesses to the items array are not local when reading columns, we
- // have a cache miss every time. To reduce cache misses, get up to
- // 'numBuffers' items at a time and store them into the individual
- // buffers. The colBuffers should be small enough to fit into CPU cache.
- var numBuffers = 16;
- var colBuffers = [];
- for (i = 0; i < numBuffers; i++) {
- colBuffers.push(new Float32Array(height + 2 * bufferPadding));
- }
- var b, currentBuffer = 0;
- ll = bufferPadding + height;
- // Section F.3.5 VER_SR
- if (height === 1) {
- // if height = 1, when v0 even keep items as is, when odd divide by 2
- if ((v0 & 1) !== 0) {
- for (u = 0; u < width; u++) {
- items[u] *= 0.5;
- }
- }
- } else {
- for (u = 0; u < width; u++) {
- // if we ran out of buffers, copy several image columns at once
- if (currentBuffer === 0) {
- numBuffers = Math.min(width - u, numBuffers);
- for (k = u, l = bufferPadding; l < ll; k += width, l++) {
- for (b = 0; b < numBuffers; b++) {
- colBuffers[b][l] = items[k + b];
- }
- }
- currentBuffer = numBuffers;
- }
- currentBuffer--;
- var buffer = colBuffers[currentBuffer];
- this.extend(buffer, bufferPadding, height);
- this.filter(buffer, bufferPadding, height);
- // If this is last buffer in this group of buffers, flush all buffers.
- if (currentBuffer === 0) {
- k = u - numBuffers + 1;
- for (l = bufferPadding; l < ll; k += width, l++) {
- for (b = 0; b < numBuffers; b++) {
- items[k + b] = colBuffers[b][l];
- }
- }
- }
- }
- }
- return {
- width: width,
- height: height,
- items: items
- };
- };
- return Transform;
- }();
- // Section 3.8.2 Irreversible 9-7 filter
- var IrreversibleTransform = function IrreversibleTransformClosure() {
- function IrreversibleTransform() {
- Transform.call(this);
- }
- IrreversibleTransform.prototype = Object.create(Transform.prototype);
- IrreversibleTransform.prototype.filter = function irreversibleTransformFilter(x, offset, length) {
- var len = length >> 1;
- offset = offset | 0;
- var j, n, current, next;
- var alpha = -1.586134342059924;
- var beta = -0.052980118572961;
- var gamma = 0.882911075530934;
- var delta = 0.443506852043971;
- var K = 1.230174104914001;
- var K_ = 1 / K;
- // step 1 is combined with step 3
- // step 2
- j = offset - 3;
- for (n = len + 4; n--; j += 2) {
- x[j] *= K_;
- }
- // step 1 & 3
- j = offset - 2;
- current = delta * x[j - 1];
- for (n = len + 3; n--; j += 2) {
- next = delta * x[j + 1];
- x[j] = K * x[j] - current - next;
- if (n--) {
- j += 2;
- current = delta * x[j + 1];
- x[j] = K * x[j] - current - next;
- } else {
- break;
- }
- }
- // step 4
- j = offset - 1;
- current = gamma * x[j - 1];
- for (n = len + 2; n--; j += 2) {
- next = gamma * x[j + 1];
- x[j] -= current + next;
- if (n--) {
- j += 2;
- current = gamma * x[j + 1];
- x[j] -= current + next;
- } else {
- break;
- }
- }
- // step 5
- j = offset;
- current = beta * x[j - 1];
- for (n = len + 1; n--; j += 2) {
- next = beta * x[j + 1];
- x[j] -= current + next;
- if (n--) {
- j += 2;
- current = beta * x[j + 1];
- x[j] -= current + next;
- } else {
- break;
- }
- }
- // step 6
- if (len !== 0) {
- j = offset + 1;
- current = alpha * x[j - 1];
- for (n = len; n--; j += 2) {
- next = alpha * x[j + 1];
- x[j] -= current + next;
- if (n--) {
- j += 2;
- current = alpha * x[j + 1];
- x[j] -= current + next;
- } else {
- break;
- }
- }
- }
- };
- return IrreversibleTransform;
- }();
- // Section 3.8.1 Reversible 5-3 filter
- var ReversibleTransform = function ReversibleTransformClosure() {
- function ReversibleTransform() {
- Transform.call(this);
- }
- ReversibleTransform.prototype = Object.create(Transform.prototype);
- ReversibleTransform.prototype.filter = function reversibleTransformFilter(x, offset, length) {
- var len = length >> 1;
- offset = offset | 0;
- var j, n;
- for (j = offset, n = len + 1; n--; j += 2) {
- x[j] -= x[j - 1] + x[j + 1] + 2 >> 2;
- }
- for (j = offset + 1, n = len; n--; j += 2) {
- x[j] += x[j - 1] + x[j + 1] >> 1;
- }
- };
- return ReversibleTransform;
- }();
- return JpxImage;
- }();
- exports.JpxImage = JpxImage;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreMetrics = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- var getLookupTableFactory = sharedUtil.getLookupTableFactory;
- // The Metrics object contains glyph widths (in glyph space units).
- // As per PDF spec, for most fonts (Type 3 being an exception) a glyph
- // space unit corresponds to 1/1000th of text space unit.
- var getMetrics = getLookupTableFactory(function (t) {
- t['Courier'] = 600;
- t['Courier-Bold'] = 600;
- t['Courier-BoldOblique'] = 600;
- t['Courier-Oblique'] = 600;
- t['Helvetica'] = getLookupTableFactory(function (t) {
- t['space'] = 278;
- t['exclam'] = 278;
- t['quotedbl'] = 355;
- t['numbersign'] = 556;
- t['dollar'] = 556;
- t['percent'] = 889;
- t['ampersand'] = 667;
- t['quoteright'] = 222;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 389;
- t['plus'] = 584;
- t['comma'] = 278;
- t['hyphen'] = 333;
- t['period'] = 278;
- t['slash'] = 278;
- t['zero'] = 556;
- t['one'] = 556;
- t['two'] = 556;
- t['three'] = 556;
- t['four'] = 556;
- t['five'] = 556;
- t['six'] = 556;
- t['seven'] = 556;
- t['eight'] = 556;
- t['nine'] = 556;
- t['colon'] = 278;
- t['semicolon'] = 278;
- t['less'] = 584;
- t['equal'] = 584;
- t['greater'] = 584;
- t['question'] = 556;
- t['at'] = 1015;
- t['A'] = 667;
- t['B'] = 667;
- t['C'] = 722;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 611;
- t['G'] = 778;
- t['H'] = 722;
- t['I'] = 278;
- t['J'] = 500;
- t['K'] = 667;
- t['L'] = 556;
- t['M'] = 833;
- t['N'] = 722;
- t['O'] = 778;
- t['P'] = 667;
- t['Q'] = 778;
- t['R'] = 722;
- t['S'] = 667;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 667;
- t['W'] = 944;
- t['X'] = 667;
- t['Y'] = 667;
- t['Z'] = 611;
- t['bracketleft'] = 278;
- t['backslash'] = 278;
- t['bracketright'] = 278;
- t['asciicircum'] = 469;
- t['underscore'] = 556;
- t['quoteleft'] = 222;
- t['a'] = 556;
- t['b'] = 556;
- t['c'] = 500;
- t['d'] = 556;
- t['e'] = 556;
- t['f'] = 278;
- t['g'] = 556;
- t['h'] = 556;
- t['i'] = 222;
- t['j'] = 222;
- t['k'] = 500;
- t['l'] = 222;
- t['m'] = 833;
- t['n'] = 556;
- t['o'] = 556;
- t['p'] = 556;
- t['q'] = 556;
- t['r'] = 333;
- t['s'] = 500;
- t['t'] = 278;
- t['u'] = 556;
- t['v'] = 500;
- t['w'] = 722;
- t['x'] = 500;
- t['y'] = 500;
- t['z'] = 500;
- t['braceleft'] = 334;
- t['bar'] = 260;
- t['braceright'] = 334;
- t['asciitilde'] = 584;
- t['exclamdown'] = 333;
- t['cent'] = 556;
- t['sterling'] = 556;
- t['fraction'] = 167;
- t['yen'] = 556;
- t['florin'] = 556;
- t['section'] = 556;
- t['currency'] = 556;
- t['quotesingle'] = 191;
- t['quotedblleft'] = 333;
- t['guillemotleft'] = 556;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 500;
- t['fl'] = 500;
- t['endash'] = 556;
- t['dagger'] = 556;
- t['daggerdbl'] = 556;
- t['periodcentered'] = 278;
- t['paragraph'] = 537;
- t['bullet'] = 350;
- t['quotesinglbase'] = 222;
- t['quotedblbase'] = 333;
- t['quotedblright'] = 333;
- t['guillemotright'] = 556;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 611;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 1000;
- t['ordfeminine'] = 370;
- t['Lslash'] = 556;
- t['Oslash'] = 778;
- t['OE'] = 1000;
- t['ordmasculine'] = 365;
- t['ae'] = 889;
- t['dotlessi'] = 278;
- t['lslash'] = 222;
- t['oslash'] = 611;
- t['oe'] = 944;
- t['germandbls'] = 611;
- t['Idieresis'] = 278;
- t['eacute'] = 556;
- t['abreve'] = 556;
- t['uhungarumlaut'] = 556;
- t['ecaron'] = 556;
- t['Ydieresis'] = 667;
- t['divide'] = 584;
- t['Yacute'] = 667;
- t['Acircumflex'] = 667;
- t['aacute'] = 556;
- t['Ucircumflex'] = 722;
- t['yacute'] = 500;
- t['scommaaccent'] = 500;
- t['ecircumflex'] = 556;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 556;
- t['Uacute'] = 722;
- t['uogonek'] = 556;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 737;
- t['Emacron'] = 667;
- t['ccaron'] = 500;
- t['aring'] = 556;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 222;
- t['agrave'] = 556;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 722;
- t['atilde'] = 556;
- t['Edotaccent'] = 667;
- t['scaron'] = 500;
- t['scedilla'] = 500;
- t['iacute'] = 278;
- t['lozenge'] = 471;
- t['Rcaron'] = 722;
- t['Gcommaaccent'] = 778;
- t['ucircumflex'] = 556;
- t['acircumflex'] = 556;
- t['Amacron'] = 667;
- t['rcaron'] = 333;
- t['ccedilla'] = 500;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 667;
- t['Omacron'] = 778;
- t['Racute'] = 722;
- t['Sacute'] = 667;
- t['dcaron'] = 643;
- t['Umacron'] = 722;
- t['uring'] = 556;
- t['threesuperior'] = 333;
- t['Ograve'] = 778;
- t['Agrave'] = 667;
- t['Abreve'] = 667;
- t['multiply'] = 584;
- t['uacute'] = 556;
- t['Tcaron'] = 611;
- t['partialdiff'] = 476;
- t['ydieresis'] = 500;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 556;
- t['edieresis'] = 556;
- t['cacute'] = 500;
- t['nacute'] = 556;
- t['umacron'] = 556;
- t['Ncaron'] = 722;
- t['Iacute'] = 278;
- t['plusminus'] = 584;
- t['brokenbar'] = 260;
- t['registered'] = 737;
- t['Gbreve'] = 778;
- t['Idotaccent'] = 278;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 333;
- t['omacron'] = 556;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 722;
- t['lcommaaccent'] = 222;
- t['tcaron'] = 317;
- t['eogonek'] = 556;
- t['Uogonek'] = 722;
- t['Aacute'] = 667;
- t['Adieresis'] = 667;
- t['egrave'] = 556;
- t['zacute'] = 500;
- t['iogonek'] = 222;
- t['Oacute'] = 778;
- t['oacute'] = 556;
- t['amacron'] = 556;
- t['sacute'] = 500;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 778;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 556;
- t['twosuperior'] = 333;
- t['Odieresis'] = 778;
- t['mu'] = 556;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 556;
- t['Eogonek'] = 667;
- t['dcroat'] = 556;
- t['threequarters'] = 834;
- t['Scedilla'] = 667;
- t['lcaron'] = 299;
- t['Kcommaaccent'] = 667;
- t['Lacute'] = 556;
- t['trademark'] = 1000;
- t['edotaccent'] = 556;
- t['Igrave'] = 278;
- t['Imacron'] = 278;
- t['Lcaron'] = 556;
- t['onehalf'] = 834;
- t['lessequal'] = 549;
- t['ocircumflex'] = 556;
- t['ntilde'] = 556;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 556;
- t['gbreve'] = 556;
- t['onequarter'] = 834;
- t['Scaron'] = 667;
- t['Scommaaccent'] = 667;
- t['Ohungarumlaut'] = 778;
- t['degree'] = 400;
- t['ograve'] = 556;
- t['Ccaron'] = 722;
- t['ugrave'] = 556;
- t['radical'] = 453;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 333;
- t['Ntilde'] = 722;
- t['otilde'] = 556;
- t['Rcommaaccent'] = 722;
- t['Lcommaaccent'] = 556;
- t['Atilde'] = 667;
- t['Aogonek'] = 667;
- t['Aring'] = 667;
- t['Otilde'] = 778;
- t['zdotaccent'] = 500;
- t['Ecaron'] = 667;
- t['Iogonek'] = 278;
- t['kcommaaccent'] = 500;
- t['minus'] = 584;
- t['Icircumflex'] = 278;
- t['ncaron'] = 556;
- t['tcommaaccent'] = 278;
- t['logicalnot'] = 584;
- t['odieresis'] = 556;
- t['udieresis'] = 556;
- t['notequal'] = 549;
- t['gcommaaccent'] = 556;
- t['eth'] = 556;
- t['zcaron'] = 500;
- t['ncommaaccent'] = 556;
- t['onesuperior'] = 333;
- t['imacron'] = 278;
- t['Euro'] = 556;
- });
- t['Helvetica-Bold'] = getLookupTableFactory(function (t) {
- t['space'] = 278;
- t['exclam'] = 333;
- t['quotedbl'] = 474;
- t['numbersign'] = 556;
- t['dollar'] = 556;
- t['percent'] = 889;
- t['ampersand'] = 722;
- t['quoteright'] = 278;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 389;
- t['plus'] = 584;
- t['comma'] = 278;
- t['hyphen'] = 333;
- t['period'] = 278;
- t['slash'] = 278;
- t['zero'] = 556;
- t['one'] = 556;
- t['two'] = 556;
- t['three'] = 556;
- t['four'] = 556;
- t['five'] = 556;
- t['six'] = 556;
- t['seven'] = 556;
- t['eight'] = 556;
- t['nine'] = 556;
- t['colon'] = 333;
- t['semicolon'] = 333;
- t['less'] = 584;
- t['equal'] = 584;
- t['greater'] = 584;
- t['question'] = 611;
- t['at'] = 975;
- t['A'] = 722;
- t['B'] = 722;
- t['C'] = 722;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 611;
- t['G'] = 778;
- t['H'] = 722;
- t['I'] = 278;
- t['J'] = 556;
- t['K'] = 722;
- t['L'] = 611;
- t['M'] = 833;
- t['N'] = 722;
- t['O'] = 778;
- t['P'] = 667;
- t['Q'] = 778;
- t['R'] = 722;
- t['S'] = 667;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 667;
- t['W'] = 944;
- t['X'] = 667;
- t['Y'] = 667;
- t['Z'] = 611;
- t['bracketleft'] = 333;
- t['backslash'] = 278;
- t['bracketright'] = 333;
- t['asciicircum'] = 584;
- t['underscore'] = 556;
- t['quoteleft'] = 278;
- t['a'] = 556;
- t['b'] = 611;
- t['c'] = 556;
- t['d'] = 611;
- t['e'] = 556;
- t['f'] = 333;
- t['g'] = 611;
- t['h'] = 611;
- t['i'] = 278;
- t['j'] = 278;
- t['k'] = 556;
- t['l'] = 278;
- t['m'] = 889;
- t['n'] = 611;
- t['o'] = 611;
- t['p'] = 611;
- t['q'] = 611;
- t['r'] = 389;
- t['s'] = 556;
- t['t'] = 333;
- t['u'] = 611;
- t['v'] = 556;
- t['w'] = 778;
- t['x'] = 556;
- t['y'] = 556;
- t['z'] = 500;
- t['braceleft'] = 389;
- t['bar'] = 280;
- t['braceright'] = 389;
- t['asciitilde'] = 584;
- t['exclamdown'] = 333;
- t['cent'] = 556;
- t['sterling'] = 556;
- t['fraction'] = 167;
- t['yen'] = 556;
- t['florin'] = 556;
- t['section'] = 556;
- t['currency'] = 556;
- t['quotesingle'] = 238;
- t['quotedblleft'] = 500;
- t['guillemotleft'] = 556;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 611;
- t['fl'] = 611;
- t['endash'] = 556;
- t['dagger'] = 556;
- t['daggerdbl'] = 556;
- t['periodcentered'] = 278;
- t['paragraph'] = 556;
- t['bullet'] = 350;
- t['quotesinglbase'] = 278;
- t['quotedblbase'] = 500;
- t['quotedblright'] = 500;
- t['guillemotright'] = 556;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 611;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 1000;
- t['ordfeminine'] = 370;
- t['Lslash'] = 611;
- t['Oslash'] = 778;
- t['OE'] = 1000;
- t['ordmasculine'] = 365;
- t['ae'] = 889;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 611;
- t['oe'] = 944;
- t['germandbls'] = 611;
- t['Idieresis'] = 278;
- t['eacute'] = 556;
- t['abreve'] = 556;
- t['uhungarumlaut'] = 611;
- t['ecaron'] = 556;
- t['Ydieresis'] = 667;
- t['divide'] = 584;
- t['Yacute'] = 667;
- t['Acircumflex'] = 722;
- t['aacute'] = 556;
- t['Ucircumflex'] = 722;
- t['yacute'] = 556;
- t['scommaaccent'] = 556;
- t['ecircumflex'] = 556;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 556;
- t['Uacute'] = 722;
- t['uogonek'] = 611;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 737;
- t['Emacron'] = 667;
- t['ccaron'] = 556;
- t['aring'] = 556;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 278;
- t['agrave'] = 556;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 722;
- t['atilde'] = 556;
- t['Edotaccent'] = 667;
- t['scaron'] = 556;
- t['scedilla'] = 556;
- t['iacute'] = 278;
- t['lozenge'] = 494;
- t['Rcaron'] = 722;
- t['Gcommaaccent'] = 778;
- t['ucircumflex'] = 611;
- t['acircumflex'] = 556;
- t['Amacron'] = 722;
- t['rcaron'] = 389;
- t['ccedilla'] = 556;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 667;
- t['Omacron'] = 778;
- t['Racute'] = 722;
- t['Sacute'] = 667;
- t['dcaron'] = 743;
- t['Umacron'] = 722;
- t['uring'] = 611;
- t['threesuperior'] = 333;
- t['Ograve'] = 778;
- t['Agrave'] = 722;
- t['Abreve'] = 722;
- t['multiply'] = 584;
- t['uacute'] = 611;
- t['Tcaron'] = 611;
- t['partialdiff'] = 494;
- t['ydieresis'] = 556;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 556;
- t['edieresis'] = 556;
- t['cacute'] = 556;
- t['nacute'] = 611;
- t['umacron'] = 611;
- t['Ncaron'] = 722;
- t['Iacute'] = 278;
- t['plusminus'] = 584;
- t['brokenbar'] = 280;
- t['registered'] = 737;
- t['Gbreve'] = 778;
- t['Idotaccent'] = 278;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 389;
- t['omacron'] = 611;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 722;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 389;
- t['eogonek'] = 556;
- t['Uogonek'] = 722;
- t['Aacute'] = 722;
- t['Adieresis'] = 722;
- t['egrave'] = 556;
- t['zacute'] = 500;
- t['iogonek'] = 278;
- t['Oacute'] = 778;
- t['oacute'] = 611;
- t['amacron'] = 556;
- t['sacute'] = 556;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 778;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 611;
- t['twosuperior'] = 333;
- t['Odieresis'] = 778;
- t['mu'] = 611;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 611;
- t['Eogonek'] = 667;
- t['dcroat'] = 611;
- t['threequarters'] = 834;
- t['Scedilla'] = 667;
- t['lcaron'] = 400;
- t['Kcommaaccent'] = 722;
- t['Lacute'] = 611;
- t['trademark'] = 1000;
- t['edotaccent'] = 556;
- t['Igrave'] = 278;
- t['Imacron'] = 278;
- t['Lcaron'] = 611;
- t['onehalf'] = 834;
- t['lessequal'] = 549;
- t['ocircumflex'] = 611;
- t['ntilde'] = 611;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 556;
- t['gbreve'] = 611;
- t['onequarter'] = 834;
- t['Scaron'] = 667;
- t['Scommaaccent'] = 667;
- t['Ohungarumlaut'] = 778;
- t['degree'] = 400;
- t['ograve'] = 611;
- t['Ccaron'] = 722;
- t['ugrave'] = 611;
- t['radical'] = 549;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 389;
- t['Ntilde'] = 722;
- t['otilde'] = 611;
- t['Rcommaaccent'] = 722;
- t['Lcommaaccent'] = 611;
- t['Atilde'] = 722;
- t['Aogonek'] = 722;
- t['Aring'] = 722;
- t['Otilde'] = 778;
- t['zdotaccent'] = 500;
- t['Ecaron'] = 667;
- t['Iogonek'] = 278;
- t['kcommaaccent'] = 556;
- t['minus'] = 584;
- t['Icircumflex'] = 278;
- t['ncaron'] = 611;
- t['tcommaaccent'] = 333;
- t['logicalnot'] = 584;
- t['odieresis'] = 611;
- t['udieresis'] = 611;
- t['notequal'] = 549;
- t['gcommaaccent'] = 611;
- t['eth'] = 611;
- t['zcaron'] = 500;
- t['ncommaaccent'] = 611;
- t['onesuperior'] = 333;
- t['imacron'] = 278;
- t['Euro'] = 556;
- });
- t['Helvetica-BoldOblique'] = getLookupTableFactory(function (t) {
- t['space'] = 278;
- t['exclam'] = 333;
- t['quotedbl'] = 474;
- t['numbersign'] = 556;
- t['dollar'] = 556;
- t['percent'] = 889;
- t['ampersand'] = 722;
- t['quoteright'] = 278;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 389;
- t['plus'] = 584;
- t['comma'] = 278;
- t['hyphen'] = 333;
- t['period'] = 278;
- t['slash'] = 278;
- t['zero'] = 556;
- t['one'] = 556;
- t['two'] = 556;
- t['three'] = 556;
- t['four'] = 556;
- t['five'] = 556;
- t['six'] = 556;
- t['seven'] = 556;
- t['eight'] = 556;
- t['nine'] = 556;
- t['colon'] = 333;
- t['semicolon'] = 333;
- t['less'] = 584;
- t['equal'] = 584;
- t['greater'] = 584;
- t['question'] = 611;
- t['at'] = 975;
- t['A'] = 722;
- t['B'] = 722;
- t['C'] = 722;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 611;
- t['G'] = 778;
- t['H'] = 722;
- t['I'] = 278;
- t['J'] = 556;
- t['K'] = 722;
- t['L'] = 611;
- t['M'] = 833;
- t['N'] = 722;
- t['O'] = 778;
- t['P'] = 667;
- t['Q'] = 778;
- t['R'] = 722;
- t['S'] = 667;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 667;
- t['W'] = 944;
- t['X'] = 667;
- t['Y'] = 667;
- t['Z'] = 611;
- t['bracketleft'] = 333;
- t['backslash'] = 278;
- t['bracketright'] = 333;
- t['asciicircum'] = 584;
- t['underscore'] = 556;
- t['quoteleft'] = 278;
- t['a'] = 556;
- t['b'] = 611;
- t['c'] = 556;
- t['d'] = 611;
- t['e'] = 556;
- t['f'] = 333;
- t['g'] = 611;
- t['h'] = 611;
- t['i'] = 278;
- t['j'] = 278;
- t['k'] = 556;
- t['l'] = 278;
- t['m'] = 889;
- t['n'] = 611;
- t['o'] = 611;
- t['p'] = 611;
- t['q'] = 611;
- t['r'] = 389;
- t['s'] = 556;
- t['t'] = 333;
- t['u'] = 611;
- t['v'] = 556;
- t['w'] = 778;
- t['x'] = 556;
- t['y'] = 556;
- t['z'] = 500;
- t['braceleft'] = 389;
- t['bar'] = 280;
- t['braceright'] = 389;
- t['asciitilde'] = 584;
- t['exclamdown'] = 333;
- t['cent'] = 556;
- t['sterling'] = 556;
- t['fraction'] = 167;
- t['yen'] = 556;
- t['florin'] = 556;
- t['section'] = 556;
- t['currency'] = 556;
- t['quotesingle'] = 238;
- t['quotedblleft'] = 500;
- t['guillemotleft'] = 556;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 611;
- t['fl'] = 611;
- t['endash'] = 556;
- t['dagger'] = 556;
- t['daggerdbl'] = 556;
- t['periodcentered'] = 278;
- t['paragraph'] = 556;
- t['bullet'] = 350;
- t['quotesinglbase'] = 278;
- t['quotedblbase'] = 500;
- t['quotedblright'] = 500;
- t['guillemotright'] = 556;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 611;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 1000;
- t['ordfeminine'] = 370;
- t['Lslash'] = 611;
- t['Oslash'] = 778;
- t['OE'] = 1000;
- t['ordmasculine'] = 365;
- t['ae'] = 889;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 611;
- t['oe'] = 944;
- t['germandbls'] = 611;
- t['Idieresis'] = 278;
- t['eacute'] = 556;
- t['abreve'] = 556;
- t['uhungarumlaut'] = 611;
- t['ecaron'] = 556;
- t['Ydieresis'] = 667;
- t['divide'] = 584;
- t['Yacute'] = 667;
- t['Acircumflex'] = 722;
- t['aacute'] = 556;
- t['Ucircumflex'] = 722;
- t['yacute'] = 556;
- t['scommaaccent'] = 556;
- t['ecircumflex'] = 556;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 556;
- t['Uacute'] = 722;
- t['uogonek'] = 611;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 737;
- t['Emacron'] = 667;
- t['ccaron'] = 556;
- t['aring'] = 556;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 278;
- t['agrave'] = 556;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 722;
- t['atilde'] = 556;
- t['Edotaccent'] = 667;
- t['scaron'] = 556;
- t['scedilla'] = 556;
- t['iacute'] = 278;
- t['lozenge'] = 494;
- t['Rcaron'] = 722;
- t['Gcommaaccent'] = 778;
- t['ucircumflex'] = 611;
- t['acircumflex'] = 556;
- t['Amacron'] = 722;
- t['rcaron'] = 389;
- t['ccedilla'] = 556;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 667;
- t['Omacron'] = 778;
- t['Racute'] = 722;
- t['Sacute'] = 667;
- t['dcaron'] = 743;
- t['Umacron'] = 722;
- t['uring'] = 611;
- t['threesuperior'] = 333;
- t['Ograve'] = 778;
- t['Agrave'] = 722;
- t['Abreve'] = 722;
- t['multiply'] = 584;
- t['uacute'] = 611;
- t['Tcaron'] = 611;
- t['partialdiff'] = 494;
- t['ydieresis'] = 556;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 556;
- t['edieresis'] = 556;
- t['cacute'] = 556;
- t['nacute'] = 611;
- t['umacron'] = 611;
- t['Ncaron'] = 722;
- t['Iacute'] = 278;
- t['plusminus'] = 584;
- t['brokenbar'] = 280;
- t['registered'] = 737;
- t['Gbreve'] = 778;
- t['Idotaccent'] = 278;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 389;
- t['omacron'] = 611;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 722;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 389;
- t['eogonek'] = 556;
- t['Uogonek'] = 722;
- t['Aacute'] = 722;
- t['Adieresis'] = 722;
- t['egrave'] = 556;
- t['zacute'] = 500;
- t['iogonek'] = 278;
- t['Oacute'] = 778;
- t['oacute'] = 611;
- t['amacron'] = 556;
- t['sacute'] = 556;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 778;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 611;
- t['twosuperior'] = 333;
- t['Odieresis'] = 778;
- t['mu'] = 611;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 611;
- t['Eogonek'] = 667;
- t['dcroat'] = 611;
- t['threequarters'] = 834;
- t['Scedilla'] = 667;
- t['lcaron'] = 400;
- t['Kcommaaccent'] = 722;
- t['Lacute'] = 611;
- t['trademark'] = 1000;
- t['edotaccent'] = 556;
- t['Igrave'] = 278;
- t['Imacron'] = 278;
- t['Lcaron'] = 611;
- t['onehalf'] = 834;
- t['lessequal'] = 549;
- t['ocircumflex'] = 611;
- t['ntilde'] = 611;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 556;
- t['gbreve'] = 611;
- t['onequarter'] = 834;
- t['Scaron'] = 667;
- t['Scommaaccent'] = 667;
- t['Ohungarumlaut'] = 778;
- t['degree'] = 400;
- t['ograve'] = 611;
- t['Ccaron'] = 722;
- t['ugrave'] = 611;
- t['radical'] = 549;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 389;
- t['Ntilde'] = 722;
- t['otilde'] = 611;
- t['Rcommaaccent'] = 722;
- t['Lcommaaccent'] = 611;
- t['Atilde'] = 722;
- t['Aogonek'] = 722;
- t['Aring'] = 722;
- t['Otilde'] = 778;
- t['zdotaccent'] = 500;
- t['Ecaron'] = 667;
- t['Iogonek'] = 278;
- t['kcommaaccent'] = 556;
- t['minus'] = 584;
- t['Icircumflex'] = 278;
- t['ncaron'] = 611;
- t['tcommaaccent'] = 333;
- t['logicalnot'] = 584;
- t['odieresis'] = 611;
- t['udieresis'] = 611;
- t['notequal'] = 549;
- t['gcommaaccent'] = 611;
- t['eth'] = 611;
- t['zcaron'] = 500;
- t['ncommaaccent'] = 611;
- t['onesuperior'] = 333;
- t['imacron'] = 278;
- t['Euro'] = 556;
- });
- t['Helvetica-Oblique'] = getLookupTableFactory(function (t) {
- t['space'] = 278;
- t['exclam'] = 278;
- t['quotedbl'] = 355;
- t['numbersign'] = 556;
- t['dollar'] = 556;
- t['percent'] = 889;
- t['ampersand'] = 667;
- t['quoteright'] = 222;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 389;
- t['plus'] = 584;
- t['comma'] = 278;
- t['hyphen'] = 333;
- t['period'] = 278;
- t['slash'] = 278;
- t['zero'] = 556;
- t['one'] = 556;
- t['two'] = 556;
- t['three'] = 556;
- t['four'] = 556;
- t['five'] = 556;
- t['six'] = 556;
- t['seven'] = 556;
- t['eight'] = 556;
- t['nine'] = 556;
- t['colon'] = 278;
- t['semicolon'] = 278;
- t['less'] = 584;
- t['equal'] = 584;
- t['greater'] = 584;
- t['question'] = 556;
- t['at'] = 1015;
- t['A'] = 667;
- t['B'] = 667;
- t['C'] = 722;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 611;
- t['G'] = 778;
- t['H'] = 722;
- t['I'] = 278;
- t['J'] = 500;
- t['K'] = 667;
- t['L'] = 556;
- t['M'] = 833;
- t['N'] = 722;
- t['O'] = 778;
- t['P'] = 667;
- t['Q'] = 778;
- t['R'] = 722;
- t['S'] = 667;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 667;
- t['W'] = 944;
- t['X'] = 667;
- t['Y'] = 667;
- t['Z'] = 611;
- t['bracketleft'] = 278;
- t['backslash'] = 278;
- t['bracketright'] = 278;
- t['asciicircum'] = 469;
- t['underscore'] = 556;
- t['quoteleft'] = 222;
- t['a'] = 556;
- t['b'] = 556;
- t['c'] = 500;
- t['d'] = 556;
- t['e'] = 556;
- t['f'] = 278;
- t['g'] = 556;
- t['h'] = 556;
- t['i'] = 222;
- t['j'] = 222;
- t['k'] = 500;
- t['l'] = 222;
- t['m'] = 833;
- t['n'] = 556;
- t['o'] = 556;
- t['p'] = 556;
- t['q'] = 556;
- t['r'] = 333;
- t['s'] = 500;
- t['t'] = 278;
- t['u'] = 556;
- t['v'] = 500;
- t['w'] = 722;
- t['x'] = 500;
- t['y'] = 500;
- t['z'] = 500;
- t['braceleft'] = 334;
- t['bar'] = 260;
- t['braceright'] = 334;
- t['asciitilde'] = 584;
- t['exclamdown'] = 333;
- t['cent'] = 556;
- t['sterling'] = 556;
- t['fraction'] = 167;
- t['yen'] = 556;
- t['florin'] = 556;
- t['section'] = 556;
- t['currency'] = 556;
- t['quotesingle'] = 191;
- t['quotedblleft'] = 333;
- t['guillemotleft'] = 556;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 500;
- t['fl'] = 500;
- t['endash'] = 556;
- t['dagger'] = 556;
- t['daggerdbl'] = 556;
- t['periodcentered'] = 278;
- t['paragraph'] = 537;
- t['bullet'] = 350;
- t['quotesinglbase'] = 222;
- t['quotedblbase'] = 333;
- t['quotedblright'] = 333;
- t['guillemotright'] = 556;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 611;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 1000;
- t['ordfeminine'] = 370;
- t['Lslash'] = 556;
- t['Oslash'] = 778;
- t['OE'] = 1000;
- t['ordmasculine'] = 365;
- t['ae'] = 889;
- t['dotlessi'] = 278;
- t['lslash'] = 222;
- t['oslash'] = 611;
- t['oe'] = 944;
- t['germandbls'] = 611;
- t['Idieresis'] = 278;
- t['eacute'] = 556;
- t['abreve'] = 556;
- t['uhungarumlaut'] = 556;
- t['ecaron'] = 556;
- t['Ydieresis'] = 667;
- t['divide'] = 584;
- t['Yacute'] = 667;
- t['Acircumflex'] = 667;
- t['aacute'] = 556;
- t['Ucircumflex'] = 722;
- t['yacute'] = 500;
- t['scommaaccent'] = 500;
- t['ecircumflex'] = 556;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 556;
- t['Uacute'] = 722;
- t['uogonek'] = 556;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 737;
- t['Emacron'] = 667;
- t['ccaron'] = 500;
- t['aring'] = 556;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 222;
- t['agrave'] = 556;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 722;
- t['atilde'] = 556;
- t['Edotaccent'] = 667;
- t['scaron'] = 500;
- t['scedilla'] = 500;
- t['iacute'] = 278;
- t['lozenge'] = 471;
- t['Rcaron'] = 722;
- t['Gcommaaccent'] = 778;
- t['ucircumflex'] = 556;
- t['acircumflex'] = 556;
- t['Amacron'] = 667;
- t['rcaron'] = 333;
- t['ccedilla'] = 500;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 667;
- t['Omacron'] = 778;
- t['Racute'] = 722;
- t['Sacute'] = 667;
- t['dcaron'] = 643;
- t['Umacron'] = 722;
- t['uring'] = 556;
- t['threesuperior'] = 333;
- t['Ograve'] = 778;
- t['Agrave'] = 667;
- t['Abreve'] = 667;
- t['multiply'] = 584;
- t['uacute'] = 556;
- t['Tcaron'] = 611;
- t['partialdiff'] = 476;
- t['ydieresis'] = 500;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 556;
- t['edieresis'] = 556;
- t['cacute'] = 500;
- t['nacute'] = 556;
- t['umacron'] = 556;
- t['Ncaron'] = 722;
- t['Iacute'] = 278;
- t['plusminus'] = 584;
- t['brokenbar'] = 260;
- t['registered'] = 737;
- t['Gbreve'] = 778;
- t['Idotaccent'] = 278;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 333;
- t['omacron'] = 556;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 722;
- t['lcommaaccent'] = 222;
- t['tcaron'] = 317;
- t['eogonek'] = 556;
- t['Uogonek'] = 722;
- t['Aacute'] = 667;
- t['Adieresis'] = 667;
- t['egrave'] = 556;
- t['zacute'] = 500;
- t['iogonek'] = 222;
- t['Oacute'] = 778;
- t['oacute'] = 556;
- t['amacron'] = 556;
- t['sacute'] = 500;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 778;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 556;
- t['twosuperior'] = 333;
- t['Odieresis'] = 778;
- t['mu'] = 556;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 556;
- t['Eogonek'] = 667;
- t['dcroat'] = 556;
- t['threequarters'] = 834;
- t['Scedilla'] = 667;
- t['lcaron'] = 299;
- t['Kcommaaccent'] = 667;
- t['Lacute'] = 556;
- t['trademark'] = 1000;
- t['edotaccent'] = 556;
- t['Igrave'] = 278;
- t['Imacron'] = 278;
- t['Lcaron'] = 556;
- t['onehalf'] = 834;
- t['lessequal'] = 549;
- t['ocircumflex'] = 556;
- t['ntilde'] = 556;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 556;
- t['gbreve'] = 556;
- t['onequarter'] = 834;
- t['Scaron'] = 667;
- t['Scommaaccent'] = 667;
- t['Ohungarumlaut'] = 778;
- t['degree'] = 400;
- t['ograve'] = 556;
- t['Ccaron'] = 722;
- t['ugrave'] = 556;
- t['radical'] = 453;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 333;
- t['Ntilde'] = 722;
- t['otilde'] = 556;
- t['Rcommaaccent'] = 722;
- t['Lcommaaccent'] = 556;
- t['Atilde'] = 667;
- t['Aogonek'] = 667;
- t['Aring'] = 667;
- t['Otilde'] = 778;
- t['zdotaccent'] = 500;
- t['Ecaron'] = 667;
- t['Iogonek'] = 278;
- t['kcommaaccent'] = 500;
- t['minus'] = 584;
- t['Icircumflex'] = 278;
- t['ncaron'] = 556;
- t['tcommaaccent'] = 278;
- t['logicalnot'] = 584;
- t['odieresis'] = 556;
- t['udieresis'] = 556;
- t['notequal'] = 549;
- t['gcommaaccent'] = 556;
- t['eth'] = 556;
- t['zcaron'] = 500;
- t['ncommaaccent'] = 556;
- t['onesuperior'] = 333;
- t['imacron'] = 278;
- t['Euro'] = 556;
- });
- t['Symbol'] = getLookupTableFactory(function (t) {
- t['space'] = 250;
- t['exclam'] = 333;
- t['universal'] = 713;
- t['numbersign'] = 500;
- t['existential'] = 549;
- t['percent'] = 833;
- t['ampersand'] = 778;
- t['suchthat'] = 439;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asteriskmath'] = 500;
- t['plus'] = 549;
- t['comma'] = 250;
- t['minus'] = 549;
- t['period'] = 250;
- t['slash'] = 278;
- t['zero'] = 500;
- t['one'] = 500;
- t['two'] = 500;
- t['three'] = 500;
- t['four'] = 500;
- t['five'] = 500;
- t['six'] = 500;
- t['seven'] = 500;
- t['eight'] = 500;
- t['nine'] = 500;
- t['colon'] = 278;
- t['semicolon'] = 278;
- t['less'] = 549;
- t['equal'] = 549;
- t['greater'] = 549;
- t['question'] = 444;
- t['congruent'] = 549;
- t['Alpha'] = 722;
- t['Beta'] = 667;
- t['Chi'] = 722;
- t['Delta'] = 612;
- t['Epsilon'] = 611;
- t['Phi'] = 763;
- t['Gamma'] = 603;
- t['Eta'] = 722;
- t['Iota'] = 333;
- t['theta1'] = 631;
- t['Kappa'] = 722;
- t['Lambda'] = 686;
- t['Mu'] = 889;
- t['Nu'] = 722;
- t['Omicron'] = 722;
- t['Pi'] = 768;
- t['Theta'] = 741;
- t['Rho'] = 556;
- t['Sigma'] = 592;
- t['Tau'] = 611;
- t['Upsilon'] = 690;
- t['sigma1'] = 439;
- t['Omega'] = 768;
- t['Xi'] = 645;
- t['Psi'] = 795;
- t['Zeta'] = 611;
- t['bracketleft'] = 333;
- t['therefore'] = 863;
- t['bracketright'] = 333;
- t['perpendicular'] = 658;
- t['underscore'] = 500;
- t['radicalex'] = 500;
- t['alpha'] = 631;
- t['beta'] = 549;
- t['chi'] = 549;
- t['delta'] = 494;
- t['epsilon'] = 439;
- t['phi'] = 521;
- t['gamma'] = 411;
- t['eta'] = 603;
- t['iota'] = 329;
- t['phi1'] = 603;
- t['kappa'] = 549;
- t['lambda'] = 549;
- t['mu'] = 576;
- t['nu'] = 521;
- t['omicron'] = 549;
- t['pi'] = 549;
- t['theta'] = 521;
- t['rho'] = 549;
- t['sigma'] = 603;
- t['tau'] = 439;
- t['upsilon'] = 576;
- t['omega1'] = 713;
- t['omega'] = 686;
- t['xi'] = 493;
- t['psi'] = 686;
- t['zeta'] = 494;
- t['braceleft'] = 480;
- t['bar'] = 200;
- t['braceright'] = 480;
- t['similar'] = 549;
- t['Euro'] = 750;
- t['Upsilon1'] = 620;
- t['minute'] = 247;
- t['lessequal'] = 549;
- t['fraction'] = 167;
- t['infinity'] = 713;
- t['florin'] = 500;
- t['club'] = 753;
- t['diamond'] = 753;
- t['heart'] = 753;
- t['spade'] = 753;
- t['arrowboth'] = 1042;
- t['arrowleft'] = 987;
- t['arrowup'] = 603;
- t['arrowright'] = 987;
- t['arrowdown'] = 603;
- t['degree'] = 400;
- t['plusminus'] = 549;
- t['second'] = 411;
- t['greaterequal'] = 549;
- t['multiply'] = 549;
- t['proportional'] = 713;
- t['partialdiff'] = 494;
- t['bullet'] = 460;
- t['divide'] = 549;
- t['notequal'] = 549;
- t['equivalence'] = 549;
- t['approxequal'] = 549;
- t['ellipsis'] = 1000;
- t['arrowvertex'] = 603;
- t['arrowhorizex'] = 1000;
- t['carriagereturn'] = 658;
- t['aleph'] = 823;
- t['Ifraktur'] = 686;
- t['Rfraktur'] = 795;
- t['weierstrass'] = 987;
- t['circlemultiply'] = 768;
- t['circleplus'] = 768;
- t['emptyset'] = 823;
- t['intersection'] = 768;
- t['union'] = 768;
- t['propersuperset'] = 713;
- t['reflexsuperset'] = 713;
- t['notsubset'] = 713;
- t['propersubset'] = 713;
- t['reflexsubset'] = 713;
- t['element'] = 713;
- t['notelement'] = 713;
- t['angle'] = 768;
- t['gradient'] = 713;
- t['registerserif'] = 790;
- t['copyrightserif'] = 790;
- t['trademarkserif'] = 890;
- t['product'] = 823;
- t['radical'] = 549;
- t['dotmath'] = 250;
- t['logicalnot'] = 713;
- t['logicaland'] = 603;
- t['logicalor'] = 603;
- t['arrowdblboth'] = 1042;
- t['arrowdblleft'] = 987;
- t['arrowdblup'] = 603;
- t['arrowdblright'] = 987;
- t['arrowdbldown'] = 603;
- t['lozenge'] = 494;
- t['angleleft'] = 329;
- t['registersans'] = 790;
- t['copyrightsans'] = 790;
- t['trademarksans'] = 786;
- t['summation'] = 713;
- t['parenlefttp'] = 384;
- t['parenleftex'] = 384;
- t['parenleftbt'] = 384;
- t['bracketlefttp'] = 384;
- t['bracketleftex'] = 384;
- t['bracketleftbt'] = 384;
- t['bracelefttp'] = 494;
- t['braceleftmid'] = 494;
- t['braceleftbt'] = 494;
- t['braceex'] = 494;
- t['angleright'] = 329;
- t['integral'] = 274;
- t['integraltp'] = 686;
- t['integralex'] = 686;
- t['integralbt'] = 686;
- t['parenrighttp'] = 384;
- t['parenrightex'] = 384;
- t['parenrightbt'] = 384;
- t['bracketrighttp'] = 384;
- t['bracketrightex'] = 384;
- t['bracketrightbt'] = 384;
- t['bracerighttp'] = 494;
- t['bracerightmid'] = 494;
- t['bracerightbt'] = 494;
- t['apple'] = 790;
- });
- t['Times-Roman'] = getLookupTableFactory(function (t) {
- t['space'] = 250;
- t['exclam'] = 333;
- t['quotedbl'] = 408;
- t['numbersign'] = 500;
- t['dollar'] = 500;
- t['percent'] = 833;
- t['ampersand'] = 778;
- t['quoteright'] = 333;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 500;
- t['plus'] = 564;
- t['comma'] = 250;
- t['hyphen'] = 333;
- t['period'] = 250;
- t['slash'] = 278;
- t['zero'] = 500;
- t['one'] = 500;
- t['two'] = 500;
- t['three'] = 500;
- t['four'] = 500;
- t['five'] = 500;
- t['six'] = 500;
- t['seven'] = 500;
- t['eight'] = 500;
- t['nine'] = 500;
- t['colon'] = 278;
- t['semicolon'] = 278;
- t['less'] = 564;
- t['equal'] = 564;
- t['greater'] = 564;
- t['question'] = 444;
- t['at'] = 921;
- t['A'] = 722;
- t['B'] = 667;
- t['C'] = 667;
- t['D'] = 722;
- t['E'] = 611;
- t['F'] = 556;
- t['G'] = 722;
- t['H'] = 722;
- t['I'] = 333;
- t['J'] = 389;
- t['K'] = 722;
- t['L'] = 611;
- t['M'] = 889;
- t['N'] = 722;
- t['O'] = 722;
- t['P'] = 556;
- t['Q'] = 722;
- t['R'] = 667;
- t['S'] = 556;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 722;
- t['W'] = 944;
- t['X'] = 722;
- t['Y'] = 722;
- t['Z'] = 611;
- t['bracketleft'] = 333;
- t['backslash'] = 278;
- t['bracketright'] = 333;
- t['asciicircum'] = 469;
- t['underscore'] = 500;
- t['quoteleft'] = 333;
- t['a'] = 444;
- t['b'] = 500;
- t['c'] = 444;
- t['d'] = 500;
- t['e'] = 444;
- t['f'] = 333;
- t['g'] = 500;
- t['h'] = 500;
- t['i'] = 278;
- t['j'] = 278;
- t['k'] = 500;
- t['l'] = 278;
- t['m'] = 778;
- t['n'] = 500;
- t['o'] = 500;
- t['p'] = 500;
- t['q'] = 500;
- t['r'] = 333;
- t['s'] = 389;
- t['t'] = 278;
- t['u'] = 500;
- t['v'] = 500;
- t['w'] = 722;
- t['x'] = 500;
- t['y'] = 500;
- t['z'] = 444;
- t['braceleft'] = 480;
- t['bar'] = 200;
- t['braceright'] = 480;
- t['asciitilde'] = 541;
- t['exclamdown'] = 333;
- t['cent'] = 500;
- t['sterling'] = 500;
- t['fraction'] = 167;
- t['yen'] = 500;
- t['florin'] = 500;
- t['section'] = 500;
- t['currency'] = 500;
- t['quotesingle'] = 180;
- t['quotedblleft'] = 444;
- t['guillemotleft'] = 500;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 556;
- t['fl'] = 556;
- t['endash'] = 500;
- t['dagger'] = 500;
- t['daggerdbl'] = 500;
- t['periodcentered'] = 250;
- t['paragraph'] = 453;
- t['bullet'] = 350;
- t['quotesinglbase'] = 333;
- t['quotedblbase'] = 444;
- t['quotedblright'] = 444;
- t['guillemotright'] = 500;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 444;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 889;
- t['ordfeminine'] = 276;
- t['Lslash'] = 611;
- t['Oslash'] = 722;
- t['OE'] = 889;
- t['ordmasculine'] = 310;
- t['ae'] = 667;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 500;
- t['oe'] = 722;
- t['germandbls'] = 500;
- t['Idieresis'] = 333;
- t['eacute'] = 444;
- t['abreve'] = 444;
- t['uhungarumlaut'] = 500;
- t['ecaron'] = 444;
- t['Ydieresis'] = 722;
- t['divide'] = 564;
- t['Yacute'] = 722;
- t['Acircumflex'] = 722;
- t['aacute'] = 444;
- t['Ucircumflex'] = 722;
- t['yacute'] = 500;
- t['scommaaccent'] = 389;
- t['ecircumflex'] = 444;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 444;
- t['Uacute'] = 722;
- t['uogonek'] = 500;
- t['Edieresis'] = 611;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 760;
- t['Emacron'] = 611;
- t['ccaron'] = 444;
- t['aring'] = 444;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 278;
- t['agrave'] = 444;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 667;
- t['atilde'] = 444;
- t['Edotaccent'] = 611;
- t['scaron'] = 389;
- t['scedilla'] = 389;
- t['iacute'] = 278;
- t['lozenge'] = 471;
- t['Rcaron'] = 667;
- t['Gcommaaccent'] = 722;
- t['ucircumflex'] = 500;
- t['acircumflex'] = 444;
- t['Amacron'] = 722;
- t['rcaron'] = 333;
- t['ccedilla'] = 444;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 556;
- t['Omacron'] = 722;
- t['Racute'] = 667;
- t['Sacute'] = 556;
- t['dcaron'] = 588;
- t['Umacron'] = 722;
- t['uring'] = 500;
- t['threesuperior'] = 300;
- t['Ograve'] = 722;
- t['Agrave'] = 722;
- t['Abreve'] = 722;
- t['multiply'] = 564;
- t['uacute'] = 500;
- t['Tcaron'] = 611;
- t['partialdiff'] = 476;
- t['ydieresis'] = 500;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 611;
- t['adieresis'] = 444;
- t['edieresis'] = 444;
- t['cacute'] = 444;
- t['nacute'] = 500;
- t['umacron'] = 500;
- t['Ncaron'] = 722;
- t['Iacute'] = 333;
- t['plusminus'] = 564;
- t['brokenbar'] = 200;
- t['registered'] = 760;
- t['Gbreve'] = 722;
- t['Idotaccent'] = 333;
- t['summation'] = 600;
- t['Egrave'] = 611;
- t['racute'] = 333;
- t['omacron'] = 500;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 667;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 326;
- t['eogonek'] = 444;
- t['Uogonek'] = 722;
- t['Aacute'] = 722;
- t['Adieresis'] = 722;
- t['egrave'] = 444;
- t['zacute'] = 444;
- t['iogonek'] = 278;
- t['Oacute'] = 722;
- t['oacute'] = 500;
- t['amacron'] = 444;
- t['sacute'] = 389;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 722;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 500;
- t['twosuperior'] = 300;
- t['Odieresis'] = 722;
- t['mu'] = 500;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 500;
- t['Eogonek'] = 611;
- t['dcroat'] = 500;
- t['threequarters'] = 750;
- t['Scedilla'] = 556;
- t['lcaron'] = 344;
- t['Kcommaaccent'] = 722;
- t['Lacute'] = 611;
- t['trademark'] = 980;
- t['edotaccent'] = 444;
- t['Igrave'] = 333;
- t['Imacron'] = 333;
- t['Lcaron'] = 611;
- t['onehalf'] = 750;
- t['lessequal'] = 549;
- t['ocircumflex'] = 500;
- t['ntilde'] = 500;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 611;
- t['emacron'] = 444;
- t['gbreve'] = 500;
- t['onequarter'] = 750;
- t['Scaron'] = 556;
- t['Scommaaccent'] = 556;
- t['Ohungarumlaut'] = 722;
- t['degree'] = 400;
- t['ograve'] = 500;
- t['Ccaron'] = 667;
- t['ugrave'] = 500;
- t['radical'] = 453;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 333;
- t['Ntilde'] = 722;
- t['otilde'] = 500;
- t['Rcommaaccent'] = 667;
- t['Lcommaaccent'] = 611;
- t['Atilde'] = 722;
- t['Aogonek'] = 722;
- t['Aring'] = 722;
- t['Otilde'] = 722;
- t['zdotaccent'] = 444;
- t['Ecaron'] = 611;
- t['Iogonek'] = 333;
- t['kcommaaccent'] = 500;
- t['minus'] = 564;
- t['Icircumflex'] = 333;
- t['ncaron'] = 500;
- t['tcommaaccent'] = 278;
- t['logicalnot'] = 564;
- t['odieresis'] = 500;
- t['udieresis'] = 500;
- t['notequal'] = 549;
- t['gcommaaccent'] = 500;
- t['eth'] = 500;
- t['zcaron'] = 444;
- t['ncommaaccent'] = 500;
- t['onesuperior'] = 300;
- t['imacron'] = 278;
- t['Euro'] = 500;
- });
- t['Times-Bold'] = getLookupTableFactory(function (t) {
- t['space'] = 250;
- t['exclam'] = 333;
- t['quotedbl'] = 555;
- t['numbersign'] = 500;
- t['dollar'] = 500;
- t['percent'] = 1000;
- t['ampersand'] = 833;
- t['quoteright'] = 333;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 500;
- t['plus'] = 570;
- t['comma'] = 250;
- t['hyphen'] = 333;
- t['period'] = 250;
- t['slash'] = 278;
- t['zero'] = 500;
- t['one'] = 500;
- t['two'] = 500;
- t['three'] = 500;
- t['four'] = 500;
- t['five'] = 500;
- t['six'] = 500;
- t['seven'] = 500;
- t['eight'] = 500;
- t['nine'] = 500;
- t['colon'] = 333;
- t['semicolon'] = 333;
- t['less'] = 570;
- t['equal'] = 570;
- t['greater'] = 570;
- t['question'] = 500;
- t['at'] = 930;
- t['A'] = 722;
- t['B'] = 667;
- t['C'] = 722;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 611;
- t['G'] = 778;
- t['H'] = 778;
- t['I'] = 389;
- t['J'] = 500;
- t['K'] = 778;
- t['L'] = 667;
- t['M'] = 944;
- t['N'] = 722;
- t['O'] = 778;
- t['P'] = 611;
- t['Q'] = 778;
- t['R'] = 722;
- t['S'] = 556;
- t['T'] = 667;
- t['U'] = 722;
- t['V'] = 722;
- t['W'] = 1000;
- t['X'] = 722;
- t['Y'] = 722;
- t['Z'] = 667;
- t['bracketleft'] = 333;
- t['backslash'] = 278;
- t['bracketright'] = 333;
- t['asciicircum'] = 581;
- t['underscore'] = 500;
- t['quoteleft'] = 333;
- t['a'] = 500;
- t['b'] = 556;
- t['c'] = 444;
- t['d'] = 556;
- t['e'] = 444;
- t['f'] = 333;
- t['g'] = 500;
- t['h'] = 556;
- t['i'] = 278;
- t['j'] = 333;
- t['k'] = 556;
- t['l'] = 278;
- t['m'] = 833;
- t['n'] = 556;
- t['o'] = 500;
- t['p'] = 556;
- t['q'] = 556;
- t['r'] = 444;
- t['s'] = 389;
- t['t'] = 333;
- t['u'] = 556;
- t['v'] = 500;
- t['w'] = 722;
- t['x'] = 500;
- t['y'] = 500;
- t['z'] = 444;
- t['braceleft'] = 394;
- t['bar'] = 220;
- t['braceright'] = 394;
- t['asciitilde'] = 520;
- t['exclamdown'] = 333;
- t['cent'] = 500;
- t['sterling'] = 500;
- t['fraction'] = 167;
- t['yen'] = 500;
- t['florin'] = 500;
- t['section'] = 500;
- t['currency'] = 500;
- t['quotesingle'] = 278;
- t['quotedblleft'] = 500;
- t['guillemotleft'] = 500;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 556;
- t['fl'] = 556;
- t['endash'] = 500;
- t['dagger'] = 500;
- t['daggerdbl'] = 500;
- t['periodcentered'] = 250;
- t['paragraph'] = 540;
- t['bullet'] = 350;
- t['quotesinglbase'] = 333;
- t['quotedblbase'] = 500;
- t['quotedblright'] = 500;
- t['guillemotright'] = 500;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 500;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 1000;
- t['ordfeminine'] = 300;
- t['Lslash'] = 667;
- t['Oslash'] = 778;
- t['OE'] = 1000;
- t['ordmasculine'] = 330;
- t['ae'] = 722;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 500;
- t['oe'] = 722;
- t['germandbls'] = 556;
- t['Idieresis'] = 389;
- t['eacute'] = 444;
- t['abreve'] = 500;
- t['uhungarumlaut'] = 556;
- t['ecaron'] = 444;
- t['Ydieresis'] = 722;
- t['divide'] = 570;
- t['Yacute'] = 722;
- t['Acircumflex'] = 722;
- t['aacute'] = 500;
- t['Ucircumflex'] = 722;
- t['yacute'] = 500;
- t['scommaaccent'] = 389;
- t['ecircumflex'] = 444;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 500;
- t['Uacute'] = 722;
- t['uogonek'] = 556;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 747;
- t['Emacron'] = 667;
- t['ccaron'] = 444;
- t['aring'] = 500;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 278;
- t['agrave'] = 500;
- t['Tcommaaccent'] = 667;
- t['Cacute'] = 722;
- t['atilde'] = 500;
- t['Edotaccent'] = 667;
- t['scaron'] = 389;
- t['scedilla'] = 389;
- t['iacute'] = 278;
- t['lozenge'] = 494;
- t['Rcaron'] = 722;
- t['Gcommaaccent'] = 778;
- t['ucircumflex'] = 556;
- t['acircumflex'] = 500;
- t['Amacron'] = 722;
- t['rcaron'] = 444;
- t['ccedilla'] = 444;
- t['Zdotaccent'] = 667;
- t['Thorn'] = 611;
- t['Omacron'] = 778;
- t['Racute'] = 722;
- t['Sacute'] = 556;
- t['dcaron'] = 672;
- t['Umacron'] = 722;
- t['uring'] = 556;
- t['threesuperior'] = 300;
- t['Ograve'] = 778;
- t['Agrave'] = 722;
- t['Abreve'] = 722;
- t['multiply'] = 570;
- t['uacute'] = 556;
- t['Tcaron'] = 667;
- t['partialdiff'] = 494;
- t['ydieresis'] = 500;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 500;
- t['edieresis'] = 444;
- t['cacute'] = 444;
- t['nacute'] = 556;
- t['umacron'] = 556;
- t['Ncaron'] = 722;
- t['Iacute'] = 389;
- t['plusminus'] = 570;
- t['brokenbar'] = 220;
- t['registered'] = 747;
- t['Gbreve'] = 778;
- t['Idotaccent'] = 389;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 444;
- t['omacron'] = 500;
- t['Zacute'] = 667;
- t['Zcaron'] = 667;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 722;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 416;
- t['eogonek'] = 444;
- t['Uogonek'] = 722;
- t['Aacute'] = 722;
- t['Adieresis'] = 722;
- t['egrave'] = 444;
- t['zacute'] = 444;
- t['iogonek'] = 278;
- t['Oacute'] = 778;
- t['oacute'] = 500;
- t['amacron'] = 500;
- t['sacute'] = 389;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 778;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 556;
- t['twosuperior'] = 300;
- t['Odieresis'] = 778;
- t['mu'] = 556;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 500;
- t['Eogonek'] = 667;
- t['dcroat'] = 556;
- t['threequarters'] = 750;
- t['Scedilla'] = 556;
- t['lcaron'] = 394;
- t['Kcommaaccent'] = 778;
- t['Lacute'] = 667;
- t['trademark'] = 1000;
- t['edotaccent'] = 444;
- t['Igrave'] = 389;
- t['Imacron'] = 389;
- t['Lcaron'] = 667;
- t['onehalf'] = 750;
- t['lessequal'] = 549;
- t['ocircumflex'] = 500;
- t['ntilde'] = 556;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 444;
- t['gbreve'] = 500;
- t['onequarter'] = 750;
- t['Scaron'] = 556;
- t['Scommaaccent'] = 556;
- t['Ohungarumlaut'] = 778;
- t['degree'] = 400;
- t['ograve'] = 500;
- t['Ccaron'] = 722;
- t['ugrave'] = 556;
- t['radical'] = 549;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 444;
- t['Ntilde'] = 722;
- t['otilde'] = 500;
- t['Rcommaaccent'] = 722;
- t['Lcommaaccent'] = 667;
- t['Atilde'] = 722;
- t['Aogonek'] = 722;
- t['Aring'] = 722;
- t['Otilde'] = 778;
- t['zdotaccent'] = 444;
- t['Ecaron'] = 667;
- t['Iogonek'] = 389;
- t['kcommaaccent'] = 556;
- t['minus'] = 570;
- t['Icircumflex'] = 389;
- t['ncaron'] = 556;
- t['tcommaaccent'] = 333;
- t['logicalnot'] = 570;
- t['odieresis'] = 500;
- t['udieresis'] = 556;
- t['notequal'] = 549;
- t['gcommaaccent'] = 500;
- t['eth'] = 500;
- t['zcaron'] = 444;
- t['ncommaaccent'] = 556;
- t['onesuperior'] = 300;
- t['imacron'] = 278;
- t['Euro'] = 500;
- });
- t['Times-BoldItalic'] = getLookupTableFactory(function (t) {
- t['space'] = 250;
- t['exclam'] = 389;
- t['quotedbl'] = 555;
- t['numbersign'] = 500;
- t['dollar'] = 500;
- t['percent'] = 833;
- t['ampersand'] = 778;
- t['quoteright'] = 333;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 500;
- t['plus'] = 570;
- t['comma'] = 250;
- t['hyphen'] = 333;
- t['period'] = 250;
- t['slash'] = 278;
- t['zero'] = 500;
- t['one'] = 500;
- t['two'] = 500;
- t['three'] = 500;
- t['four'] = 500;
- t['five'] = 500;
- t['six'] = 500;
- t['seven'] = 500;
- t['eight'] = 500;
- t['nine'] = 500;
- t['colon'] = 333;
- t['semicolon'] = 333;
- t['less'] = 570;
- t['equal'] = 570;
- t['greater'] = 570;
- t['question'] = 500;
- t['at'] = 832;
- t['A'] = 667;
- t['B'] = 667;
- t['C'] = 667;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 667;
- t['G'] = 722;
- t['H'] = 778;
- t['I'] = 389;
- t['J'] = 500;
- t['K'] = 667;
- t['L'] = 611;
- t['M'] = 889;
- t['N'] = 722;
- t['O'] = 722;
- t['P'] = 611;
- t['Q'] = 722;
- t['R'] = 667;
- t['S'] = 556;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 667;
- t['W'] = 889;
- t['X'] = 667;
- t['Y'] = 611;
- t['Z'] = 611;
- t['bracketleft'] = 333;
- t['backslash'] = 278;
- t['bracketright'] = 333;
- t['asciicircum'] = 570;
- t['underscore'] = 500;
- t['quoteleft'] = 333;
- t['a'] = 500;
- t['b'] = 500;
- t['c'] = 444;
- t['d'] = 500;
- t['e'] = 444;
- t['f'] = 333;
- t['g'] = 500;
- t['h'] = 556;
- t['i'] = 278;
- t['j'] = 278;
- t['k'] = 500;
- t['l'] = 278;
- t['m'] = 778;
- t['n'] = 556;
- t['o'] = 500;
- t['p'] = 500;
- t['q'] = 500;
- t['r'] = 389;
- t['s'] = 389;
- t['t'] = 278;
- t['u'] = 556;
- t['v'] = 444;
- t['w'] = 667;
- t['x'] = 500;
- t['y'] = 444;
- t['z'] = 389;
- t['braceleft'] = 348;
- t['bar'] = 220;
- t['braceright'] = 348;
- t['asciitilde'] = 570;
- t['exclamdown'] = 389;
- t['cent'] = 500;
- t['sterling'] = 500;
- t['fraction'] = 167;
- t['yen'] = 500;
- t['florin'] = 500;
- t['section'] = 500;
- t['currency'] = 500;
- t['quotesingle'] = 278;
- t['quotedblleft'] = 500;
- t['guillemotleft'] = 500;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 556;
- t['fl'] = 556;
- t['endash'] = 500;
- t['dagger'] = 500;
- t['daggerdbl'] = 500;
- t['periodcentered'] = 250;
- t['paragraph'] = 500;
- t['bullet'] = 350;
- t['quotesinglbase'] = 333;
- t['quotedblbase'] = 500;
- t['quotedblright'] = 500;
- t['guillemotright'] = 500;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 500;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 944;
- t['ordfeminine'] = 266;
- t['Lslash'] = 611;
- t['Oslash'] = 722;
- t['OE'] = 944;
- t['ordmasculine'] = 300;
- t['ae'] = 722;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 500;
- t['oe'] = 722;
- t['germandbls'] = 500;
- t['Idieresis'] = 389;
- t['eacute'] = 444;
- t['abreve'] = 500;
- t['uhungarumlaut'] = 556;
- t['ecaron'] = 444;
- t['Ydieresis'] = 611;
- t['divide'] = 570;
- t['Yacute'] = 611;
- t['Acircumflex'] = 667;
- t['aacute'] = 500;
- t['Ucircumflex'] = 722;
- t['yacute'] = 444;
- t['scommaaccent'] = 389;
- t['ecircumflex'] = 444;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 500;
- t['Uacute'] = 722;
- t['uogonek'] = 556;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 747;
- t['Emacron'] = 667;
- t['ccaron'] = 444;
- t['aring'] = 500;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 278;
- t['agrave'] = 500;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 667;
- t['atilde'] = 500;
- t['Edotaccent'] = 667;
- t['scaron'] = 389;
- t['scedilla'] = 389;
- t['iacute'] = 278;
- t['lozenge'] = 494;
- t['Rcaron'] = 667;
- t['Gcommaaccent'] = 722;
- t['ucircumflex'] = 556;
- t['acircumflex'] = 500;
- t['Amacron'] = 667;
- t['rcaron'] = 389;
- t['ccedilla'] = 444;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 611;
- t['Omacron'] = 722;
- t['Racute'] = 667;
- t['Sacute'] = 556;
- t['dcaron'] = 608;
- t['Umacron'] = 722;
- t['uring'] = 556;
- t['threesuperior'] = 300;
- t['Ograve'] = 722;
- t['Agrave'] = 667;
- t['Abreve'] = 667;
- t['multiply'] = 570;
- t['uacute'] = 556;
- t['Tcaron'] = 611;
- t['partialdiff'] = 494;
- t['ydieresis'] = 444;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 500;
- t['edieresis'] = 444;
- t['cacute'] = 444;
- t['nacute'] = 556;
- t['umacron'] = 556;
- t['Ncaron'] = 722;
- t['Iacute'] = 389;
- t['plusminus'] = 570;
- t['brokenbar'] = 220;
- t['registered'] = 747;
- t['Gbreve'] = 722;
- t['Idotaccent'] = 389;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 389;
- t['omacron'] = 500;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 667;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 366;
- t['eogonek'] = 444;
- t['Uogonek'] = 722;
- t['Aacute'] = 667;
- t['Adieresis'] = 667;
- t['egrave'] = 444;
- t['zacute'] = 389;
- t['iogonek'] = 278;
- t['Oacute'] = 722;
- t['oacute'] = 500;
- t['amacron'] = 500;
- t['sacute'] = 389;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 722;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 500;
- t['twosuperior'] = 300;
- t['Odieresis'] = 722;
- t['mu'] = 576;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 500;
- t['Eogonek'] = 667;
- t['dcroat'] = 500;
- t['threequarters'] = 750;
- t['Scedilla'] = 556;
- t['lcaron'] = 382;
- t['Kcommaaccent'] = 667;
- t['Lacute'] = 611;
- t['trademark'] = 1000;
- t['edotaccent'] = 444;
- t['Igrave'] = 389;
- t['Imacron'] = 389;
- t['Lcaron'] = 611;
- t['onehalf'] = 750;
- t['lessequal'] = 549;
- t['ocircumflex'] = 500;
- t['ntilde'] = 556;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 444;
- t['gbreve'] = 500;
- t['onequarter'] = 750;
- t['Scaron'] = 556;
- t['Scommaaccent'] = 556;
- t['Ohungarumlaut'] = 722;
- t['degree'] = 400;
- t['ograve'] = 500;
- t['Ccaron'] = 667;
- t['ugrave'] = 556;
- t['radical'] = 549;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 389;
- t['Ntilde'] = 722;
- t['otilde'] = 500;
- t['Rcommaaccent'] = 667;
- t['Lcommaaccent'] = 611;
- t['Atilde'] = 667;
- t['Aogonek'] = 667;
- t['Aring'] = 667;
- t['Otilde'] = 722;
- t['zdotaccent'] = 389;
- t['Ecaron'] = 667;
- t['Iogonek'] = 389;
- t['kcommaaccent'] = 500;
- t['minus'] = 606;
- t['Icircumflex'] = 389;
- t['ncaron'] = 556;
- t['tcommaaccent'] = 278;
- t['logicalnot'] = 606;
- t['odieresis'] = 500;
- t['udieresis'] = 556;
- t['notequal'] = 549;
- t['gcommaaccent'] = 500;
- t['eth'] = 500;
- t['zcaron'] = 389;
- t['ncommaaccent'] = 556;
- t['onesuperior'] = 300;
- t['imacron'] = 278;
- t['Euro'] = 500;
- });
- t['Times-Italic'] = getLookupTableFactory(function (t) {
- t['space'] = 250;
- t['exclam'] = 333;
- t['quotedbl'] = 420;
- t['numbersign'] = 500;
- t['dollar'] = 500;
- t['percent'] = 833;
- t['ampersand'] = 778;
- t['quoteright'] = 333;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 500;
- t['plus'] = 675;
- t['comma'] = 250;
- t['hyphen'] = 333;
- t['period'] = 250;
- t['slash'] = 278;
- t['zero'] = 500;
- t['one'] = 500;
- t['two'] = 500;
- t['three'] = 500;
- t['four'] = 500;
- t['five'] = 500;
- t['six'] = 500;
- t['seven'] = 500;
- t['eight'] = 500;
- t['nine'] = 500;
- t['colon'] = 333;
- t['semicolon'] = 333;
- t['less'] = 675;
- t['equal'] = 675;
- t['greater'] = 675;
- t['question'] = 500;
- t['at'] = 920;
- t['A'] = 611;
- t['B'] = 611;
- t['C'] = 667;
- t['D'] = 722;
- t['E'] = 611;
- t['F'] = 611;
- t['G'] = 722;
- t['H'] = 722;
- t['I'] = 333;
- t['J'] = 444;
- t['K'] = 667;
- t['L'] = 556;
- t['M'] = 833;
- t['N'] = 667;
- t['O'] = 722;
- t['P'] = 611;
- t['Q'] = 722;
- t['R'] = 611;
- t['S'] = 500;
- t['T'] = 556;
- t['U'] = 722;
- t['V'] = 611;
- t['W'] = 833;
- t['X'] = 611;
- t['Y'] = 556;
- t['Z'] = 556;
- t['bracketleft'] = 389;
- t['backslash'] = 278;
- t['bracketright'] = 389;
- t['asciicircum'] = 422;
- t['underscore'] = 500;
- t['quoteleft'] = 333;
- t['a'] = 500;
- t['b'] = 500;
- t['c'] = 444;
- t['d'] = 500;
- t['e'] = 444;
- t['f'] = 278;
- t['g'] = 500;
- t['h'] = 500;
- t['i'] = 278;
- t['j'] = 278;
- t['k'] = 444;
- t['l'] = 278;
- t['m'] = 722;
- t['n'] = 500;
- t['o'] = 500;
- t['p'] = 500;
- t['q'] = 500;
- t['r'] = 389;
- t['s'] = 389;
- t['t'] = 278;
- t['u'] = 500;
- t['v'] = 444;
- t['w'] = 667;
- t['x'] = 444;
- t['y'] = 444;
- t['z'] = 389;
- t['braceleft'] = 400;
- t['bar'] = 275;
- t['braceright'] = 400;
- t['asciitilde'] = 541;
- t['exclamdown'] = 389;
- t['cent'] = 500;
- t['sterling'] = 500;
- t['fraction'] = 167;
- t['yen'] = 500;
- t['florin'] = 500;
- t['section'] = 500;
- t['currency'] = 500;
- t['quotesingle'] = 214;
- t['quotedblleft'] = 556;
- t['guillemotleft'] = 500;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 500;
- t['fl'] = 500;
- t['endash'] = 500;
- t['dagger'] = 500;
- t['daggerdbl'] = 500;
- t['periodcentered'] = 250;
- t['paragraph'] = 523;
- t['bullet'] = 350;
- t['quotesinglbase'] = 333;
- t['quotedblbase'] = 556;
- t['quotedblright'] = 556;
- t['guillemotright'] = 500;
- t['ellipsis'] = 889;
- t['perthousand'] = 1000;
- t['questiondown'] = 500;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 889;
- t['AE'] = 889;
- t['ordfeminine'] = 276;
- t['Lslash'] = 556;
- t['Oslash'] = 722;
- t['OE'] = 944;
- t['ordmasculine'] = 310;
- t['ae'] = 667;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 500;
- t['oe'] = 667;
- t['germandbls'] = 500;
- t['Idieresis'] = 333;
- t['eacute'] = 444;
- t['abreve'] = 500;
- t['uhungarumlaut'] = 500;
- t['ecaron'] = 444;
- t['Ydieresis'] = 556;
- t['divide'] = 675;
- t['Yacute'] = 556;
- t['Acircumflex'] = 611;
- t['aacute'] = 500;
- t['Ucircumflex'] = 722;
- t['yacute'] = 444;
- t['scommaaccent'] = 389;
- t['ecircumflex'] = 444;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 500;
- t['Uacute'] = 722;
- t['uogonek'] = 500;
- t['Edieresis'] = 611;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 760;
- t['Emacron'] = 611;
- t['ccaron'] = 444;
- t['aring'] = 500;
- t['Ncommaaccent'] = 667;
- t['lacute'] = 278;
- t['agrave'] = 500;
- t['Tcommaaccent'] = 556;
- t['Cacute'] = 667;
- t['atilde'] = 500;
- t['Edotaccent'] = 611;
- t['scaron'] = 389;
- t['scedilla'] = 389;
- t['iacute'] = 278;
- t['lozenge'] = 471;
- t['Rcaron'] = 611;
- t['Gcommaaccent'] = 722;
- t['ucircumflex'] = 500;
- t['acircumflex'] = 500;
- t['Amacron'] = 611;
- t['rcaron'] = 389;
- t['ccedilla'] = 444;
- t['Zdotaccent'] = 556;
- t['Thorn'] = 611;
- t['Omacron'] = 722;
- t['Racute'] = 611;
- t['Sacute'] = 500;
- t['dcaron'] = 544;
- t['Umacron'] = 722;
- t['uring'] = 500;
- t['threesuperior'] = 300;
- t['Ograve'] = 722;
- t['Agrave'] = 611;
- t['Abreve'] = 611;
- t['multiply'] = 675;
- t['uacute'] = 500;
- t['Tcaron'] = 556;
- t['partialdiff'] = 476;
- t['ydieresis'] = 444;
- t['Nacute'] = 667;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 611;
- t['adieresis'] = 500;
- t['edieresis'] = 444;
- t['cacute'] = 444;
- t['nacute'] = 500;
- t['umacron'] = 500;
- t['Ncaron'] = 667;
- t['Iacute'] = 333;
- t['plusminus'] = 675;
- t['brokenbar'] = 275;
- t['registered'] = 760;
- t['Gbreve'] = 722;
- t['Idotaccent'] = 333;
- t['summation'] = 600;
- t['Egrave'] = 611;
- t['racute'] = 389;
- t['omacron'] = 500;
- t['Zacute'] = 556;
- t['Zcaron'] = 556;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 667;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 300;
- t['eogonek'] = 444;
- t['Uogonek'] = 722;
- t['Aacute'] = 611;
- t['Adieresis'] = 611;
- t['egrave'] = 444;
- t['zacute'] = 389;
- t['iogonek'] = 278;
- t['Oacute'] = 722;
- t['oacute'] = 500;
- t['amacron'] = 500;
- t['sacute'] = 389;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 722;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 500;
- t['twosuperior'] = 300;
- t['Odieresis'] = 722;
- t['mu'] = 500;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 500;
- t['Eogonek'] = 611;
- t['dcroat'] = 500;
- t['threequarters'] = 750;
- t['Scedilla'] = 500;
- t['lcaron'] = 300;
- t['Kcommaaccent'] = 667;
- t['Lacute'] = 556;
- t['trademark'] = 980;
- t['edotaccent'] = 444;
- t['Igrave'] = 333;
- t['Imacron'] = 333;
- t['Lcaron'] = 611;
- t['onehalf'] = 750;
- t['lessequal'] = 549;
- t['ocircumflex'] = 500;
- t['ntilde'] = 500;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 611;
- t['emacron'] = 444;
- t['gbreve'] = 500;
- t['onequarter'] = 750;
- t['Scaron'] = 500;
- t['Scommaaccent'] = 500;
- t['Ohungarumlaut'] = 722;
- t['degree'] = 400;
- t['ograve'] = 500;
- t['Ccaron'] = 667;
- t['ugrave'] = 500;
- t['radical'] = 453;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 389;
- t['Ntilde'] = 667;
- t['otilde'] = 500;
- t['Rcommaaccent'] = 611;
- t['Lcommaaccent'] = 556;
- t['Atilde'] = 611;
- t['Aogonek'] = 611;
- t['Aring'] = 611;
- t['Otilde'] = 722;
- t['zdotaccent'] = 389;
- t['Ecaron'] = 611;
- t['Iogonek'] = 333;
- t['kcommaaccent'] = 444;
- t['minus'] = 675;
- t['Icircumflex'] = 333;
- t['ncaron'] = 500;
- t['tcommaaccent'] = 278;
- t['logicalnot'] = 675;
- t['odieresis'] = 500;
- t['udieresis'] = 500;
- t['notequal'] = 549;
- t['gcommaaccent'] = 500;
- t['eth'] = 500;
- t['zcaron'] = 389;
- t['ncommaaccent'] = 500;
- t['onesuperior'] = 300;
- t['imacron'] = 278;
- t['Euro'] = 500;
- });
- t['ZapfDingbats'] = getLookupTableFactory(function (t) {
- t['space'] = 278;
- t['a1'] = 974;
- t['a2'] = 961;
- t['a202'] = 974;
- t['a3'] = 980;
- t['a4'] = 719;
- t['a5'] = 789;
- t['a119'] = 790;
- t['a118'] = 791;
- t['a117'] = 690;
- t['a11'] = 960;
- t['a12'] = 939;
- t['a13'] = 549;
- t['a14'] = 855;
- t['a15'] = 911;
- t['a16'] = 933;
- t['a105'] = 911;
- t['a17'] = 945;
- t['a18'] = 974;
- t['a19'] = 755;
- t['a20'] = 846;
- t['a21'] = 762;
- t['a22'] = 761;
- t['a23'] = 571;
- t['a24'] = 677;
- t['a25'] = 763;
- t['a26'] = 760;
- t['a27'] = 759;
- t['a28'] = 754;
- t['a6'] = 494;
- t['a7'] = 552;
- t['a8'] = 537;
- t['a9'] = 577;
- t['a10'] = 692;
- t['a29'] = 786;
- t['a30'] = 788;
- t['a31'] = 788;
- t['a32'] = 790;
- t['a33'] = 793;
- t['a34'] = 794;
- t['a35'] = 816;
- t['a36'] = 823;
- t['a37'] = 789;
- t['a38'] = 841;
- t['a39'] = 823;
- t['a40'] = 833;
- t['a41'] = 816;
- t['a42'] = 831;
- t['a43'] = 923;
- t['a44'] = 744;
- t['a45'] = 723;
- t['a46'] = 749;
- t['a47'] = 790;
- t['a48'] = 792;
- t['a49'] = 695;
- t['a50'] = 776;
- t['a51'] = 768;
- t['a52'] = 792;
- t['a53'] = 759;
- t['a54'] = 707;
- t['a55'] = 708;
- t['a56'] = 682;
- t['a57'] = 701;
- t['a58'] = 826;
- t['a59'] = 815;
- t['a60'] = 789;
- t['a61'] = 789;
- t['a62'] = 707;
- t['a63'] = 687;
- t['a64'] = 696;
- t['a65'] = 689;
- t['a66'] = 786;
- t['a67'] = 787;
- t['a68'] = 713;
- t['a69'] = 791;
- t['a70'] = 785;
- t['a71'] = 791;
- t['a72'] = 873;
- t['a73'] = 761;
- t['a74'] = 762;
- t['a203'] = 762;
- t['a75'] = 759;
- t['a204'] = 759;
- t['a76'] = 892;
- t['a77'] = 892;
- t['a78'] = 788;
- t['a79'] = 784;
- t['a81'] = 438;
- t['a82'] = 138;
- t['a83'] = 277;
- t['a84'] = 415;
- t['a97'] = 392;
- t['a98'] = 392;
- t['a99'] = 668;
- t['a100'] = 668;
- t['a89'] = 390;
- t['a90'] = 390;
- t['a93'] = 317;
- t['a94'] = 317;
- t['a91'] = 276;
- t['a92'] = 276;
- t['a205'] = 509;
- t['a85'] = 509;
- t['a206'] = 410;
- t['a86'] = 410;
- t['a87'] = 234;
- t['a88'] = 234;
- t['a95'] = 334;
- t['a96'] = 334;
- t['a101'] = 732;
- t['a102'] = 544;
- t['a103'] = 544;
- t['a104'] = 910;
- t['a106'] = 667;
- t['a107'] = 760;
- t['a108'] = 760;
- t['a112'] = 776;
- t['a111'] = 595;
- t['a110'] = 694;
- t['a109'] = 626;
- t['a120'] = 788;
- t['a121'] = 788;
- t['a122'] = 788;
- t['a123'] = 788;
- t['a124'] = 788;
- t['a125'] = 788;
- t['a126'] = 788;
- t['a127'] = 788;
- t['a128'] = 788;
- t['a129'] = 788;
- t['a130'] = 788;
- t['a131'] = 788;
- t['a132'] = 788;
- t['a133'] = 788;
- t['a134'] = 788;
- t['a135'] = 788;
- t['a136'] = 788;
- t['a137'] = 788;
- t['a138'] = 788;
- t['a139'] = 788;
- t['a140'] = 788;
- t['a141'] = 788;
- t['a142'] = 788;
- t['a143'] = 788;
- t['a144'] = 788;
- t['a145'] = 788;
- t['a146'] = 788;
- t['a147'] = 788;
- t['a148'] = 788;
- t['a149'] = 788;
- t['a150'] = 788;
- t['a151'] = 788;
- t['a152'] = 788;
- t['a153'] = 788;
- t['a154'] = 788;
- t['a155'] = 788;
- t['a156'] = 788;
- t['a157'] = 788;
- t['a158'] = 788;
- t['a159'] = 788;
- t['a160'] = 894;
- t['a161'] = 838;
- t['a163'] = 1016;
- t['a164'] = 458;
- t['a196'] = 748;
- t['a165'] = 924;
- t['a192'] = 748;
- t['a166'] = 918;
- t['a167'] = 927;
- t['a168'] = 928;
- t['a169'] = 928;
- t['a170'] = 834;
- t['a171'] = 873;
- t['a172'] = 828;
- t['a173'] = 924;
- t['a162'] = 924;
- t['a174'] = 917;
- t['a175'] = 930;
- t['a176'] = 931;
- t['a177'] = 463;
- t['a178'] = 883;
- t['a179'] = 836;
- t['a193'] = 836;
- t['a180'] = 867;
- t['a199'] = 867;
- t['a181'] = 696;
- t['a200'] = 696;
- t['a182'] = 874;
- t['a201'] = 874;
- t['a183'] = 760;
- t['a184'] = 946;
- t['a197'] = 771;
- t['a185'] = 865;
- t['a194'] = 771;
- t['a198'] = 888;
- t['a186'] = 967;
- t['a195'] = 888;
- t['a187'] = 831;
- t['a188'] = 873;
- t['a189'] = 927;
- t['a190'] = 970;
- t['a191'] = 918;
- });
- });
- exports.getMetrics = getMetrics;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreMurmurHash3 = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- var Uint32ArrayView = sharedUtil.Uint32ArrayView;
- var MurmurHash3_64 = function MurmurHash3_64Closure(seed) {
- // Workaround for missing math precision in JS.
- var MASK_HIGH = 0xffff0000;
- var MASK_LOW = 0xffff;
- function MurmurHash3_64(seed) {
- var SEED = 0xc3d2e1f0;
- this.h1 = seed ? seed & 0xffffffff : SEED;
- this.h2 = seed ? seed & 0xffffffff : SEED;
- }
- var alwaysUseUint32ArrayView = false;
- MurmurHash3_64.prototype = {
- update: function MurmurHash3_64_update(input) {
- var useUint32ArrayView = alwaysUseUint32ArrayView;
- var i;
- if (typeof input === 'string') {
- var data = new Uint8Array(input.length * 2);
- var length = 0;
- for (i = 0; i < input.length; i++) {
- var code = input.charCodeAt(i);
- if (code <= 0xff) {
- data[length++] = code;
- } else {
- data[length++] = code >>> 8;
- data[length++] = code & 0xff;
- }
- }
- } else if (input instanceof Uint8Array) {
- data = input;
- length = data.length;
- } else if (typeof input === 'object' && 'length' in input) {
- // processing regular arrays as well, e.g. for IE9
- data = input;
- length = data.length;
- useUint32ArrayView = true;
- } else {
- throw new Error('Wrong data format in MurmurHash3_64_update. ' + 'Input must be a string or array.');
- }
- var blockCounts = length >> 2;
- var tailLength = length - blockCounts * 4;
- // we don't care about endianness here
- var dataUint32 = useUint32ArrayView ? new Uint32ArrayView(data, blockCounts) : new Uint32Array(data.buffer, 0, blockCounts);
- var k1 = 0;
- var k2 = 0;
- var h1 = this.h1;
- var h2 = this.h2;
- var C1 = 0xcc9e2d51;
- var C2 = 0x1b873593;
- var C1_LOW = C1 & MASK_LOW;
- var C2_LOW = C2 & MASK_LOW;
- for (i = 0; i < blockCounts; i++) {
- if (i & 1) {
- k1 = dataUint32[i];
- k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
- k1 = k1 << 15 | k1 >>> 17;
- k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
- h1 ^= k1;
- h1 = h1 << 13 | h1 >>> 19;
- h1 = h1 * 5 + 0xe6546b64;
- } else {
- k2 = dataUint32[i];
- k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW;
- k2 = k2 << 15 | k2 >>> 17;
- k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW;
- h2 ^= k2;
- h2 = h2 << 13 | h2 >>> 19;
- h2 = h2 * 5 + 0xe6546b64;
- }
- }
- k1 = 0;
- switch (tailLength) {
- case 3:
- k1 ^= data[blockCounts * 4 + 2] << 16;
- case 2:
- k1 ^= data[blockCounts * 4 + 1] << 8;
- case 1:
- k1 ^= data[blockCounts * 4];
- k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
- k1 = k1 << 15 | k1 >>> 17;
- k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
- if (blockCounts & 1) {
- h1 ^= k1;
- } else {
- h2 ^= k1;
- }
- }
- this.h1 = h1;
- this.h2 = h2;
- return this;
- },
- hexdigest: function MurmurHash3_64_hexdigest() {
- var h1 = this.h1;
- var h2 = this.h2;
- h1 ^= h2 >>> 1;
- h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW;
- h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16;
- h1 ^= h2 >>> 1;
- h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW;
- h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16;
- h1 ^= h2 >>> 1;
- for (var i = 0, arr = [
- h1,
- h2
- ], str = ''; i < arr.length; i++) {
- var hex = (arr[i] >>> 0).toString(16);
- while (hex.length < 8) {
- hex = '0' + hex;
- }
- str += hex;
- }
- return str;
- }
- };
- return MurmurHash3_64;
- }();
- exports.MurmurHash3_64 = MurmurHash3_64;
- }));
- (function (root, factory) {
- factory(root.pdfjsCorePrimitives = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- var isArray = sharedUtil.isArray;
- var Name = function NameClosure() {
- function Name(name) {
- this.name = name;
- }
- Name.prototype = {};
- var nameCache = Object.create(null);
- Name.get = function Name_get(name) {
- var nameValue = nameCache[name];
- return nameValue ? nameValue : nameCache[name] = new Name(name);
- };
- return Name;
- }();
- var Cmd = function CmdClosure() {
- function Cmd(cmd) {
- this.cmd = cmd;
- }
- Cmd.prototype = {};
- var cmdCache = Object.create(null);
- Cmd.get = function Cmd_get(cmd) {
- var cmdValue = cmdCache[cmd];
- return cmdValue ? cmdValue : cmdCache[cmd] = new Cmd(cmd);
- };
- return Cmd;
- }();
- var Dict = function DictClosure() {
- var nonSerializable = function nonSerializableClosure() {
- return nonSerializable;
- };
- // creating closure on some variable
- // xref is optional
- function Dict(xref) {
- // Map should only be used internally, use functions below to access.
- this.map = Object.create(null);
- this.xref = xref;
- this.objId = null;
- this.suppressEncryption = false;
- this.__nonSerializable__ = nonSerializable;
- }
- // disable cloning of the Dict
- Dict.prototype = {
- assignXref: function Dict_assignXref(newXref) {
- this.xref = newXref;
- },
- // automatically dereferences Ref objects
- get: function Dict_get(key1, key2, key3) {
- var value;
- var xref = this.xref, suppressEncryption = this.suppressEncryption;
- if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || typeof key2 === 'undefined') {
- return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
- }
- if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || typeof key3 === 'undefined') {
- return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
- }
- value = this.map[key3] || null;
- return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
- },
- // Same as get(), but returns a promise and uses fetchIfRefAsync().
- getAsync: function Dict_getAsync(key1, key2, key3) {
- var value;
- var xref = this.xref, suppressEncryption = this.suppressEncryption;
- if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || typeof key2 === 'undefined') {
- if (xref) {
- return xref.fetchIfRefAsync(value, suppressEncryption);
- }
- return Promise.resolve(value);
- }
- if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || typeof key3 === 'undefined') {
- if (xref) {
- return xref.fetchIfRefAsync(value, suppressEncryption);
- }
- return Promise.resolve(value);
- }
- value = this.map[key3] || null;
- if (xref) {
- return xref.fetchIfRefAsync(value, suppressEncryption);
- }
- return Promise.resolve(value);
- },
- // Same as get(), but dereferences all elements if the result is an Array.
- getArray: function Dict_getArray(key1, key2, key3) {
- var value = this.get(key1, key2, key3);
- var xref = this.xref, suppressEncryption = this.suppressEncryption;
- if (!isArray(value) || !xref) {
- return value;
- }
- value = value.slice();
- // Ensure that we don't modify the Dict data.
- for (var i = 0, ii = value.length; i < ii; i++) {
- if (!isRef(value[i])) {
- continue;
- }
- value[i] = xref.fetch(value[i], suppressEncryption);
- }
- return value;
- },
- // no dereferencing
- getRaw: function Dict_getRaw(key) {
- return this.map[key];
- },
- getKeys: function Dict_getKeys() {
- return Object.keys(this.map);
- },
- set: function Dict_set(key, value) {
- this.map[key] = value;
- },
- has: function Dict_has(key) {
- return key in this.map;
- },
- forEach: function Dict_forEach(callback) {
- for (var key in this.map) {
- callback(key, this.get(key));
- }
- }
- };
- Dict.empty = new Dict(null);
- Dict.merge = function Dict_merge(xref, dictArray) {
- var mergedDict = new Dict(xref);
- for (var i = 0, ii = dictArray.length; i < ii; i++) {
- var dict = dictArray[i];
- if (!isDict(dict)) {
- continue;
- }
- for (var keyName in dict.map) {
- if (mergedDict.map[keyName]) {
- continue;
- }
- mergedDict.map[keyName] = dict.map[keyName];
- }
- }
- return mergedDict;
- };
- return Dict;
- }();
- var Ref = function RefClosure() {
- function Ref(num, gen) {
- this.num = num;
- this.gen = gen;
- }
- Ref.prototype = {
- toString: function Ref_toString() {
- // This function is hot, so we make the string as compact as possible.
- // |this.gen| is almost always zero, so we treat that case specially.
- var str = this.num + 'R';
- if (this.gen !== 0) {
- str += this.gen;
- }
- return str;
- }
- };
- return Ref;
- }();
- // The reference is identified by number and generation.
- // This structure stores only one instance of the reference.
- var RefSet = function RefSetClosure() {
- function RefSet() {
- this.dict = Object.create(null);
- }
- RefSet.prototype = {
- has: function RefSet_has(ref) {
- return ref.toString() in this.dict;
- },
- put: function RefSet_put(ref) {
- this.dict[ref.toString()] = true;
- },
- remove: function RefSet_remove(ref) {
- delete this.dict[ref.toString()];
- }
- };
- return RefSet;
- }();
- var RefSetCache = function RefSetCacheClosure() {
- function RefSetCache() {
- this.dict = Object.create(null);
- }
- RefSetCache.prototype = {
- get: function RefSetCache_get(ref) {
- return this.dict[ref.toString()];
- },
- has: function RefSetCache_has(ref) {
- return ref.toString() in this.dict;
- },
- put: function RefSetCache_put(ref, obj) {
- this.dict[ref.toString()] = obj;
- },
- putAlias: function RefSetCache_putAlias(ref, aliasRef) {
- this.dict[ref.toString()] = this.get(aliasRef);
- },
- forEach: function RefSetCache_forEach(fn, thisArg) {
- for (var i in this.dict) {
- fn.call(thisArg, this.dict[i]);
- }
- },
- clear: function RefSetCache_clear() {
- this.dict = Object.create(null);
- }
- };
- return RefSetCache;
- }();
- function isName(v, name) {
- return v instanceof Name && (name === undefined || v.name === name);
- }
- function isCmd(v, cmd) {
- return v instanceof Cmd && (cmd === undefined || v.cmd === cmd);
- }
- function isDict(v, type) {
- return v instanceof Dict && (type === undefined || isName(v.get('Type'), type));
- }
- function isRef(v) {
- return v instanceof Ref;
- }
- function isRefsEqual(v1, v2) {
- return v1.num === v2.num && v1.gen === v2.gen;
- }
- function isStream(v) {
- return typeof v === 'object' && v !== null && v.getBytes !== undefined;
- }
- exports.Cmd = Cmd;
- exports.Dict = Dict;
- exports.Name = Name;
- exports.Ref = Ref;
- exports.RefSet = RefSet;
- exports.RefSetCache = RefSetCache;
- exports.isCmd = isCmd;
- exports.isDict = isDict;
- exports.isName = isName;
- exports.isRef = isRef;
- exports.isRefsEqual = isRefsEqual;
- exports.isStream = isStream;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreStandardFonts = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- var getLookupTableFactory = sharedUtil.getLookupTableFactory;
- /**
- * Hold a map of decoded fonts and of the standard fourteen Type1
- * fonts and their acronyms.
- */
- var getStdFontMap = getLookupTableFactory(function (t) {
- t['ArialNarrow'] = 'Helvetica';
- t['ArialNarrow-Bold'] = 'Helvetica-Bold';
- t['ArialNarrow-BoldItalic'] = 'Helvetica-BoldOblique';
- t['ArialNarrow-Italic'] = 'Helvetica-Oblique';
- t['ArialBlack'] = 'Helvetica';
- t['ArialBlack-Bold'] = 'Helvetica-Bold';
- t['ArialBlack-BoldItalic'] = 'Helvetica-BoldOblique';
- t['ArialBlack-Italic'] = 'Helvetica-Oblique';
- t['Arial'] = 'Helvetica';
- t['Arial-Bold'] = 'Helvetica-Bold';
- t['Arial-BoldItalic'] = 'Helvetica-BoldOblique';
- t['Arial-Italic'] = 'Helvetica-Oblique';
- t['Arial-BoldItalicMT'] = 'Helvetica-BoldOblique';
- t['Arial-BoldMT'] = 'Helvetica-Bold';
- t['Arial-ItalicMT'] = 'Helvetica-Oblique';
- t['ArialMT'] = 'Helvetica';
- t['Courier-Bold'] = 'Courier-Bold';
- t['Courier-BoldItalic'] = 'Courier-BoldOblique';
- t['Courier-Italic'] = 'Courier-Oblique';
- t['CourierNew'] = 'Courier';
- t['CourierNew-Bold'] = 'Courier-Bold';
- t['CourierNew-BoldItalic'] = 'Courier-BoldOblique';
- t['CourierNew-Italic'] = 'Courier-Oblique';
- t['CourierNewPS-BoldItalicMT'] = 'Courier-BoldOblique';
- t['CourierNewPS-BoldMT'] = 'Courier-Bold';
- t['CourierNewPS-ItalicMT'] = 'Courier-Oblique';
- t['CourierNewPSMT'] = 'Courier';
- t['Helvetica'] = 'Helvetica';
- t['Helvetica-Bold'] = 'Helvetica-Bold';
- t['Helvetica-BoldItalic'] = 'Helvetica-BoldOblique';
- t['Helvetica-BoldOblique'] = 'Helvetica-BoldOblique';
- t['Helvetica-Italic'] = 'Helvetica-Oblique';
- t['Helvetica-Oblique'] = 'Helvetica-Oblique';
- t['Symbol-Bold'] = 'Symbol';
- t['Symbol-BoldItalic'] = 'Symbol';
- t['Symbol-Italic'] = 'Symbol';
- t['TimesNewRoman'] = 'Times-Roman';
- t['TimesNewRoman-Bold'] = 'Times-Bold';
- t['TimesNewRoman-BoldItalic'] = 'Times-BoldItalic';
- t['TimesNewRoman-Italic'] = 'Times-Italic';
- t['TimesNewRomanPS'] = 'Times-Roman';
- t['TimesNewRomanPS-Bold'] = 'Times-Bold';
- t['TimesNewRomanPS-BoldItalic'] = 'Times-BoldItalic';
- t['TimesNewRomanPS-BoldItalicMT'] = 'Times-BoldItalic';
- t['TimesNewRomanPS-BoldMT'] = 'Times-Bold';
- t['TimesNewRomanPS-Italic'] = 'Times-Italic';
- t['TimesNewRomanPS-ItalicMT'] = 'Times-Italic';
- t['TimesNewRomanPSMT'] = 'Times-Roman';
- t['TimesNewRomanPSMT-Bold'] = 'Times-Bold';
- t['TimesNewRomanPSMT-BoldItalic'] = 'Times-BoldItalic';
- t['TimesNewRomanPSMT-Italic'] = 'Times-Italic';
- });
- /**
- * Holds the map of the non-standard fonts that might be included as
- * a standard fonts without glyph data.
- */
- var getNonStdFontMap = getLookupTableFactory(function (t) {
- t['CenturyGothic'] = 'Helvetica';
- t['CenturyGothic-Bold'] = 'Helvetica-Bold';
- t['CenturyGothic-BoldItalic'] = 'Helvetica-BoldOblique';
- t['CenturyGothic-Italic'] = 'Helvetica-Oblique';
- t['ComicSansMS'] = 'Comic Sans MS';
- t['ComicSansMS-Bold'] = 'Comic Sans MS-Bold';
- t['ComicSansMS-BoldItalic'] = 'Comic Sans MS-BoldItalic';
- t['ComicSansMS-Italic'] = 'Comic Sans MS-Italic';
- t['LucidaConsole'] = 'Courier';
- t['LucidaConsole-Bold'] = 'Courier-Bold';
- t['LucidaConsole-BoldItalic'] = 'Courier-BoldOblique';
- t['LucidaConsole-Italic'] = 'Courier-Oblique';
- t['MS-Gothic'] = 'MS Gothic';
- t['MS-Gothic-Bold'] = 'MS Gothic-Bold';
- t['MS-Gothic-BoldItalic'] = 'MS Gothic-BoldItalic';
- t['MS-Gothic-Italic'] = 'MS Gothic-Italic';
- t['MS-Mincho'] = 'MS Mincho';
- t['MS-Mincho-Bold'] = 'MS Mincho-Bold';
- t['MS-Mincho-BoldItalic'] = 'MS Mincho-BoldItalic';
- t['MS-Mincho-Italic'] = 'MS Mincho-Italic';
- t['MS-PGothic'] = 'MS PGothic';
- t['MS-PGothic-Bold'] = 'MS PGothic-Bold';
- t['MS-PGothic-BoldItalic'] = 'MS PGothic-BoldItalic';
- t['MS-PGothic-Italic'] = 'MS PGothic-Italic';
- t['MS-PMincho'] = 'MS PMincho';
- t['MS-PMincho-Bold'] = 'MS PMincho-Bold';
- t['MS-PMincho-BoldItalic'] = 'MS PMincho-BoldItalic';
- t['MS-PMincho-Italic'] = 'MS PMincho-Italic';
- t['Wingdings'] = 'ZapfDingbats';
- });
- var getSerifFonts = getLookupTableFactory(function (t) {
- t['Adobe Jenson'] = true;
- t['Adobe Text'] = true;
- t['Albertus'] = true;
- t['Aldus'] = true;
- t['Alexandria'] = true;
- t['Algerian'] = true;
- t['American Typewriter'] = true;
- t['Antiqua'] = true;
- t['Apex'] = true;
- t['Arno'] = true;
- t['Aster'] = true;
- t['Aurora'] = true;
- t['Baskerville'] = true;
- t['Bell'] = true;
- t['Bembo'] = true;
- t['Bembo Schoolbook'] = true;
- t['Benguiat'] = true;
- t['Berkeley Old Style'] = true;
- t['Bernhard Modern'] = true;
- t['Berthold City'] = true;
- t['Bodoni'] = true;
- t['Bauer Bodoni'] = true;
- t['Book Antiqua'] = true;
- t['Bookman'] = true;
- t['Bordeaux Roman'] = true;
- t['Californian FB'] = true;
- t['Calisto'] = true;
- t['Calvert'] = true;
- t['Capitals'] = true;
- t['Cambria'] = true;
- t['Cartier'] = true;
- t['Caslon'] = true;
- t['Catull'] = true;
- t['Centaur'] = true;
- t['Century Old Style'] = true;
- t['Century Schoolbook'] = true;
- t['Chaparral'] = true;
- t['Charis SIL'] = true;
- t['Cheltenham'] = true;
- t['Cholla Slab'] = true;
- t['Clarendon'] = true;
- t['Clearface'] = true;
- t['Cochin'] = true;
- t['Colonna'] = true;
- t['Computer Modern'] = true;
- t['Concrete Roman'] = true;
- t['Constantia'] = true;
- t['Cooper Black'] = true;
- t['Corona'] = true;
- t['Ecotype'] = true;
- t['Egyptienne'] = true;
- t['Elephant'] = true;
- t['Excelsior'] = true;
- t['Fairfield'] = true;
- t['FF Scala'] = true;
- t['Folkard'] = true;
- t['Footlight'] = true;
- t['FreeSerif'] = true;
- t['Friz Quadrata'] = true;
- t['Garamond'] = true;
- t['Gentium'] = true;
- t['Georgia'] = true;
- t['Gloucester'] = true;
- t['Goudy Old Style'] = true;
- t['Goudy Schoolbook'] = true;
- t['Goudy Pro Font'] = true;
- t['Granjon'] = true;
- t['Guardian Egyptian'] = true;
- t['Heather'] = true;
- t['Hercules'] = true;
- t['High Tower Text'] = true;
- t['Hiroshige'] = true;
- t['Hoefler Text'] = true;
- t['Humana Serif'] = true;
- t['Imprint'] = true;
- t['Ionic No. 5'] = true;
- t['Janson'] = true;
- t['Joanna'] = true;
- t['Korinna'] = true;
- t['Lexicon'] = true;
- t['Liberation Serif'] = true;
- t['Linux Libertine'] = true;
- t['Literaturnaya'] = true;
- t['Lucida'] = true;
- t['Lucida Bright'] = true;
- t['Melior'] = true;
- t['Memphis'] = true;
- t['Miller'] = true;
- t['Minion'] = true;
- t['Modern'] = true;
- t['Mona Lisa'] = true;
- t['Mrs Eaves'] = true;
- t['MS Serif'] = true;
- t['Museo Slab'] = true;
- t['New York'] = true;
- t['Nimbus Roman'] = true;
- t['NPS Rawlinson Roadway'] = true;
- t['Palatino'] = true;
- t['Perpetua'] = true;
- t['Plantin'] = true;
- t['Plantin Schoolbook'] = true;
- t['Playbill'] = true;
- t['Poor Richard'] = true;
- t['Rawlinson Roadway'] = true;
- t['Renault'] = true;
- t['Requiem'] = true;
- t['Rockwell'] = true;
- t['Roman'] = true;
- t['Rotis Serif'] = true;
- t['Sabon'] = true;
- t['Scala'] = true;
- t['Seagull'] = true;
- t['Sistina'] = true;
- t['Souvenir'] = true;
- t['STIX'] = true;
- t['Stone Informal'] = true;
- t['Stone Serif'] = true;
- t['Sylfaen'] = true;
- t['Times'] = true;
- t['Trajan'] = true;
- t['Trinité'] = true;
- t['Trump Mediaeval'] = true;
- t['Utopia'] = true;
- t['Vale Type'] = true;
- t['Bitstream Vera'] = true;
- t['Vera Serif'] = true;
- t['Versailles'] = true;
- t['Wanted'] = true;
- t['Weiss'] = true;
- t['Wide Latin'] = true;
- t['Windsor'] = true;
- t['XITS'] = true;
- });
- var getSymbolsFonts = getLookupTableFactory(function (t) {
- t['Dingbats'] = true;
- t['Symbol'] = true;
- t['ZapfDingbats'] = true;
- });
- // Glyph map for well-known standard fonts. Sometimes Ghostscript uses CID
- // fonts, but does not embed the CID to GID mapping. The mapping is incomplete
- // for all glyphs, but common for some set of the standard fonts.
- var getGlyphMapForStandardFonts = getLookupTableFactory(function (t) {
- t[2] = 10;
- t[3] = 32;
- t[4] = 33;
- t[5] = 34;
- t[6] = 35;
- t[7] = 36;
- t[8] = 37;
- t[9] = 38;
- t[10] = 39;
- t[11] = 40;
- t[12] = 41;
- t[13] = 42;
- t[14] = 43;
- t[15] = 44;
- t[16] = 45;
- t[17] = 46;
- t[18] = 47;
- t[19] = 48;
- t[20] = 49;
- t[21] = 50;
- t[22] = 51;
- t[23] = 52;
- t[24] = 53;
- t[25] = 54;
- t[26] = 55;
- t[27] = 56;
- t[28] = 57;
- t[29] = 58;
- t[30] = 894;
- t[31] = 60;
- t[32] = 61;
- t[33] = 62;
- t[34] = 63;
- t[35] = 64;
- t[36] = 65;
- t[37] = 66;
- t[38] = 67;
- t[39] = 68;
- t[40] = 69;
- t[41] = 70;
- t[42] = 71;
- t[43] = 72;
- t[44] = 73;
- t[45] = 74;
- t[46] = 75;
- t[47] = 76;
- t[48] = 77;
- t[49] = 78;
- t[50] = 79;
- t[51] = 80;
- t[52] = 81;
- t[53] = 82;
- t[54] = 83;
- t[55] = 84;
- t[56] = 85;
- t[57] = 86;
- t[58] = 87;
- t[59] = 88;
- t[60] = 89;
- t[61] = 90;
- t[62] = 91;
- t[63] = 92;
- t[64] = 93;
- t[65] = 94;
- t[66] = 95;
- t[67] = 96;
- t[68] = 97;
- t[69] = 98;
- t[70] = 99;
- t[71] = 100;
- t[72] = 101;
- t[73] = 102;
- t[74] = 103;
- t[75] = 104;
- t[76] = 105;
- t[77] = 106;
- t[78] = 107;
- t[79] = 108;
- t[80] = 109;
- t[81] = 110;
- t[82] = 111;
- t[83] = 112;
- t[84] = 113;
- t[85] = 114;
- t[86] = 115;
- t[87] = 116;
- t[88] = 117;
- t[89] = 118;
- t[90] = 119;
- t[91] = 120;
- t[92] = 121;
- t[93] = 122;
- t[94] = 123;
- t[95] = 124;
- t[96] = 125;
- t[97] = 126;
- t[98] = 196;
- t[99] = 197;
- t[100] = 199;
- t[101] = 201;
- t[102] = 209;
- t[103] = 214;
- t[104] = 220;
- t[105] = 225;
- t[106] = 224;
- t[107] = 226;
- t[108] = 228;
- t[109] = 227;
- t[110] = 229;
- t[111] = 231;
- t[112] = 233;
- t[113] = 232;
- t[114] = 234;
- t[115] = 235;
- t[116] = 237;
- t[117] = 236;
- t[118] = 238;
- t[119] = 239;
- t[120] = 241;
- t[121] = 243;
- t[122] = 242;
- t[123] = 244;
- t[124] = 246;
- t[125] = 245;
- t[126] = 250;
- t[127] = 249;
- t[128] = 251;
- t[129] = 252;
- t[130] = 8224;
- t[131] = 176;
- t[132] = 162;
- t[133] = 163;
- t[134] = 167;
- t[135] = 8226;
- t[136] = 182;
- t[137] = 223;
- t[138] = 174;
- t[139] = 169;
- t[140] = 8482;
- t[141] = 180;
- t[142] = 168;
- t[143] = 8800;
- t[144] = 198;
- t[145] = 216;
- t[146] = 8734;
- t[147] = 177;
- t[148] = 8804;
- t[149] = 8805;
- t[150] = 165;
- t[151] = 181;
- t[152] = 8706;
- t[153] = 8721;
- t[154] = 8719;
- t[156] = 8747;
- t[157] = 170;
- t[158] = 186;
- t[159] = 8486;
- t[160] = 230;
- t[161] = 248;
- t[162] = 191;
- t[163] = 161;
- t[164] = 172;
- t[165] = 8730;
- t[166] = 402;
- t[167] = 8776;
- t[168] = 8710;
- t[169] = 171;
- t[170] = 187;
- t[171] = 8230;
- t[210] = 218;
- t[223] = 711;
- t[224] = 321;
- t[225] = 322;
- t[227] = 353;
- t[229] = 382;
- t[234] = 253;
- t[252] = 263;
- t[253] = 268;
- t[254] = 269;
- t[258] = 258;
- t[260] = 260;
- t[261] = 261;
- t[265] = 280;
- t[266] = 281;
- t[268] = 283;
- t[269] = 313;
- t[275] = 323;
- t[276] = 324;
- t[278] = 328;
- t[284] = 345;
- t[285] = 346;
- t[286] = 347;
- t[292] = 367;
- t[295] = 377;
- t[296] = 378;
- t[298] = 380;
- t[305] = 963;
- t[306] = 964;
- t[307] = 966;
- t[308] = 8215;
- t[309] = 8252;
- t[310] = 8319;
- t[311] = 8359;
- t[312] = 8592;
- t[313] = 8593;
- t[337] = 9552;
- t[493] = 1039;
- t[494] = 1040;
- t[705] = 1524;
- t[706] = 8362;
- t[710] = 64288;
- t[711] = 64298;
- t[759] = 1617;
- t[761] = 1776;
- t[763] = 1778;
- t[775] = 1652;
- t[777] = 1764;
- t[778] = 1780;
- t[779] = 1781;
- t[780] = 1782;
- t[782] = 771;
- t[783] = 64726;
- t[786] = 8363;
- t[788] = 8532;
- t[790] = 768;
- t[791] = 769;
- t[792] = 768;
- t[795] = 803;
- t[797] = 64336;
- t[798] = 64337;
- t[799] = 64342;
- t[800] = 64343;
- t[801] = 64344;
- t[802] = 64345;
- t[803] = 64362;
- t[804] = 64363;
- t[805] = 64364;
- t[2424] = 7821;
- t[2425] = 7822;
- t[2426] = 7823;
- t[2427] = 7824;
- t[2428] = 7825;
- t[2429] = 7826;
- t[2430] = 7827;
- t[2433] = 7682;
- t[2678] = 8045;
- t[2679] = 8046;
- t[2830] = 1552;
- t[2838] = 686;
- t[2840] = 751;
- t[2842] = 753;
- t[2843] = 754;
- t[2844] = 755;
- t[2846] = 757;
- t[2856] = 767;
- t[2857] = 848;
- t[2858] = 849;
- t[2862] = 853;
- t[2863] = 854;
- t[2864] = 855;
- t[2865] = 861;
- t[2866] = 862;
- t[2906] = 7460;
- t[2908] = 7462;
- t[2909] = 7463;
- t[2910] = 7464;
- t[2912] = 7466;
- t[2913] = 7467;
- t[2914] = 7468;
- t[2916] = 7470;
- t[2917] = 7471;
- t[2918] = 7472;
- t[2920] = 7474;
- t[2921] = 7475;
- t[2922] = 7476;
- t[2924] = 7478;
- t[2925] = 7479;
- t[2926] = 7480;
- t[2928] = 7482;
- t[2929] = 7483;
- t[2930] = 7484;
- t[2932] = 7486;
- t[2933] = 7487;
- t[2934] = 7488;
- t[2936] = 7490;
- t[2937] = 7491;
- t[2938] = 7492;
- t[2940] = 7494;
- t[2941] = 7495;
- t[2942] = 7496;
- t[2944] = 7498;
- t[2946] = 7500;
- t[2948] = 7502;
- t[2950] = 7504;
- t[2951] = 7505;
- t[2952] = 7506;
- t[2954] = 7508;
- t[2955] = 7509;
- t[2956] = 7510;
- t[2958] = 7512;
- t[2959] = 7513;
- t[2960] = 7514;
- t[2962] = 7516;
- t[2963] = 7517;
- t[2964] = 7518;
- t[2966] = 7520;
- t[2967] = 7521;
- t[2968] = 7522;
- t[2970] = 7524;
- t[2971] = 7525;
- t[2972] = 7526;
- t[2974] = 7528;
- t[2975] = 7529;
- t[2976] = 7530;
- t[2978] = 1537;
- t[2979] = 1538;
- t[2980] = 1539;
- t[2982] = 1549;
- t[2983] = 1551;
- t[2984] = 1552;
- t[2986] = 1554;
- t[2987] = 1555;
- t[2988] = 1556;
- t[2990] = 1623;
- t[2991] = 1624;
- t[2995] = 1775;
- t[2999] = 1791;
- t[3002] = 64290;
- t[3003] = 64291;
- t[3004] = 64292;
- t[3006] = 64294;
- t[3007] = 64295;
- t[3008] = 64296;
- t[3011] = 1900;
- t[3014] = 8223;
- t[3015] = 8244;
- t[3017] = 7532;
- t[3018] = 7533;
- t[3019] = 7534;
- t[3075] = 7590;
- t[3076] = 7591;
- t[3079] = 7594;
- t[3080] = 7595;
- t[3083] = 7598;
- t[3084] = 7599;
- t[3087] = 7602;
- t[3088] = 7603;
- t[3091] = 7606;
- t[3092] = 7607;
- t[3095] = 7610;
- t[3096] = 7611;
- t[3099] = 7614;
- t[3100] = 7615;
- t[3103] = 7618;
- t[3104] = 7619;
- t[3107] = 8337;
- t[3108] = 8338;
- t[3116] = 1884;
- t[3119] = 1885;
- t[3120] = 1885;
- t[3123] = 1886;
- t[3124] = 1886;
- t[3127] = 1887;
- t[3128] = 1887;
- t[3131] = 1888;
- t[3132] = 1888;
- t[3135] = 1889;
- t[3136] = 1889;
- t[3139] = 1890;
- t[3140] = 1890;
- t[3143] = 1891;
- t[3144] = 1891;
- t[3147] = 1892;
- t[3148] = 1892;
- t[3153] = 580;
- t[3154] = 581;
- t[3157] = 584;
- t[3158] = 585;
- t[3161] = 588;
- t[3162] = 589;
- t[3165] = 891;
- t[3166] = 892;
- t[3169] = 1274;
- t[3170] = 1275;
- t[3173] = 1278;
- t[3174] = 1279;
- t[3181] = 7622;
- t[3182] = 7623;
- t[3282] = 11799;
- t[3316] = 578;
- t[3379] = 42785;
- t[3393] = 1159;
- t[3416] = 8377;
- });
- // The glyph map for ArialBlack differs slightly from the glyph map used for
- // other well-known standard fonts. Hence we use this (incomplete) CID to GID
- // mapping to adjust the glyph map for non-embedded ArialBlack fonts.
- var getSupplementalGlyphMapForArialBlack = getLookupTableFactory(function (t) {
- t[227] = 322;
- t[264] = 261;
- t[291] = 346;
- });
- exports.getStdFontMap = getStdFontMap;
- exports.getNonStdFontMap = getNonStdFontMap;
- exports.getSerifFonts = getSerifFonts;
- exports.getSymbolsFonts = getSymbolsFonts;
- exports.getGlyphMapForStandardFonts = getGlyphMapForStandardFonts;
- exports.getSupplementalGlyphMapForArialBlack = getSupplementalGlyphMapForArialBlack;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreUnicode = {}, root.pdfjsSharedUtil);
- }(this, function (exports, sharedUtil) {
- var getLookupTableFactory = sharedUtil.getLookupTableFactory;
- // Some characters, e.g. copyrightserif, are mapped to the private use area
- // and might not be displayed using standard fonts. Mapping/hacking well-known
- // chars to the similar equivalents in the normal characters range.
- var getSpecialPUASymbols = getLookupTableFactory(function (t) {
- t[63721] = 0x00A9;
- // copyrightsans (0xF8E9) => copyright
- t[63193] = 0x00A9;
- // copyrightserif (0xF6D9) => copyright
- t[63720] = 0x00AE;
- // registersans (0xF8E8) => registered
- t[63194] = 0x00AE;
- // registerserif (0xF6DA) => registered
- t[63722] = 0x2122;
- // trademarksans (0xF8EA) => trademark
- t[63195] = 0x2122;
- // trademarkserif (0xF6DB) => trademark
- t[63729] = 0x23A7;
- // bracelefttp (0xF8F1)
- t[63730] = 0x23A8;
- // braceleftmid (0xF8F2)
- t[63731] = 0x23A9;
- // braceleftbt (0xF8F3)
- t[63740] = 0x23AB;
- // bracerighttp (0xF8FC)
- t[63741] = 0x23AC;
- // bracerightmid (0xF8FD)
- t[63742] = 0x23AD;
- // bracerightbt (0xF8FE)
- t[63726] = 0x23A1;
- // bracketlefttp (0xF8EE)
- t[63727] = 0x23A2;
- // bracketleftex (0xF8EF)
- t[63728] = 0x23A3;
- // bracketleftbt (0xF8F0)
- t[63737] = 0x23A4;
- // bracketrighttp (0xF8F9)
- t[63738] = 0x23A5;
- // bracketrightex (0xF8FA)
- t[63739] = 0x23A6;
- // bracketrightbt (0xF8FB)
- t[63723] = 0x239B;
- // parenlefttp (0xF8EB)
- t[63724] = 0x239C;
- // parenleftex (0xF8EC)
- t[63725] = 0x239D;
- // parenleftbt (0xF8ED)
- t[63734] = 0x239E;
- // parenrighttp (0xF8F6)
- t[63735] = 0x239F;
- // parenrightex (0xF8F7)
- t[63736] = 0x23A0;
- });
- // parenrightbt (0xF8F8)
- function mapSpecialUnicodeValues(code) {
- if (code >= 0xFFF0 && code <= 0xFFFF) {
- // Specials unicode block.
- return 0;
- } else if (code >= 0xF600 && code <= 0xF8FF) {
- return getSpecialPUASymbols()[code] || code;
- }
- return code;
- }
- function getUnicodeForGlyph(name, glyphsUnicodeMap) {
- var unicode = glyphsUnicodeMap[name];
- if (unicode !== undefined) {
- return unicode;
- }
- if (!name) {
- return -1;
- }
- // Try to recover valid Unicode values from 'uniXXXX'/'uXXXX{XX}' glyphs.
- if (name[0] === 'u') {
- var nameLen = name.length, hexStr;
- if (nameLen === 7 && name[1] === 'n' && name[2] === 'i') {
- // 'uniXXXX'
- hexStr = name.substr(3);
- } else if (nameLen >= 5 && nameLen <= 7) {
- // 'uXXXX{XX}'
- hexStr = name.substr(1);
- } else {
- return -1;
- }
- // Check for upper-case hexadecimal characters, to avoid false positives.
- if (hexStr === hexStr.toUpperCase()) {
- unicode = parseInt(hexStr, 16);
- if (unicode >= 0) {
- return unicode;
- }
- }
- }
- return -1;
- }
- var UnicodeRanges = [
- {
- 'begin': 0x0000,
- 'end': 0x007F
- },
- // Basic Latin
- {
- 'begin': 0x0080,
- 'end': 0x00FF
- },
- // Latin-1 Supplement
- {
- 'begin': 0x0100,
- 'end': 0x017F
- },
- // Latin Extended-A
- {
- 'begin': 0x0180,
- 'end': 0x024F
- },
- // Latin Extended-B
- {
- 'begin': 0x0250,
- 'end': 0x02AF
- },
- // IPA Extensions
- {
- 'begin': 0x02B0,
- 'end': 0x02FF
- },
- // Spacing Modifier Letters
- {
- 'begin': 0x0300,
- 'end': 0x036F
- },
- // Combining Diacritical Marks
- {
- 'begin': 0x0370,
- 'end': 0x03FF
- },
- // Greek and Coptic
- {
- 'begin': 0x2C80,
- 'end': 0x2CFF
- },
- // Coptic
- {
- 'begin': 0x0400,
- 'end': 0x04FF
- },
- // Cyrillic
- {
- 'begin': 0x0530,
- 'end': 0x058F
- },
- // Armenian
- {
- 'begin': 0x0590,
- 'end': 0x05FF
- },
- // Hebrew
- {
- 'begin': 0xA500,
- 'end': 0xA63F
- },
- // Vai
- {
- 'begin': 0x0600,
- 'end': 0x06FF
- },
- // Arabic
- {
- 'begin': 0x07C0,
- 'end': 0x07FF
- },
- // NKo
- {
- 'begin': 0x0900,
- 'end': 0x097F
- },
- // Devanagari
- {
- 'begin': 0x0980,
- 'end': 0x09FF
- },
- // Bengali
- {
- 'begin': 0x0A00,
- 'end': 0x0A7F
- },
- // Gurmukhi
- {
- 'begin': 0x0A80,
- 'end': 0x0AFF
- },
- // Gujarati
- {
- 'begin': 0x0B00,
- 'end': 0x0B7F
- },
- // Oriya
- {
- 'begin': 0x0B80,
- 'end': 0x0BFF
- },
- // Tamil
- {
- 'begin': 0x0C00,
- 'end': 0x0C7F
- },
- // Telugu
- {
- 'begin': 0x0C80,
- 'end': 0x0CFF
- },
- // Kannada
- {
- 'begin': 0x0D00,
- 'end': 0x0D7F
- },
- // Malayalam
- {
- 'begin': 0x0E00,
- 'end': 0x0E7F
- },
- // Thai
- {
- 'begin': 0x0E80,
- 'end': 0x0EFF
- },
- // Lao
- {
- 'begin': 0x10A0,
- 'end': 0x10FF
- },
- // Georgian
- {
- 'begin': 0x1B00,
- 'end': 0x1B7F
- },
- // Balinese
- {
- 'begin': 0x1100,
- 'end': 0x11FF
- },
- // Hangul Jamo
- {
- 'begin': 0x1E00,
- 'end': 0x1EFF
- },
- // Latin Extended Additional
- {
- 'begin': 0x1F00,
- 'end': 0x1FFF
- },
- // Greek Extended
- {
- 'begin': 0x2000,
- 'end': 0x206F
- },
- // General Punctuation
- {
- 'begin': 0x2070,
- 'end': 0x209F
- },
- // Superscripts And Subscripts
- {
- 'begin': 0x20A0,
- 'end': 0x20CF
- },
- // Currency Symbol
- {
- 'begin': 0x20D0,
- 'end': 0x20FF
- },
- // Combining Diacritical Marks
- {
- 'begin': 0x2100,
- 'end': 0x214F
- },
- // Letterlike Symbols
- {
- 'begin': 0x2150,
- 'end': 0x218F
- },
- // Number Forms
- {
- 'begin': 0x2190,
- 'end': 0x21FF
- },
- // Arrows
- {
- 'begin': 0x2200,
- 'end': 0x22FF
- },
- // Mathematical Operators
- {
- 'begin': 0x2300,
- 'end': 0x23FF
- },
- // Miscellaneous Technical
- {
- 'begin': 0x2400,
- 'end': 0x243F
- },
- // Control Pictures
- {
- 'begin': 0x2440,
- 'end': 0x245F
- },
- // Optical Character Recognition
- {
- 'begin': 0x2460,
- 'end': 0x24FF
- },
- // Enclosed Alphanumerics
- {
- 'begin': 0x2500,
- 'end': 0x257F
- },
- // Box Drawing
- {
- 'begin': 0x2580,
- 'end': 0x259F
- },
- // Block Elements
- {
- 'begin': 0x25A0,
- 'end': 0x25FF
- },
- // Geometric Shapes
- {
- 'begin': 0x2600,
- 'end': 0x26FF
- },
- // Miscellaneous Symbols
- {
- 'begin': 0x2700,
- 'end': 0x27BF
- },
- // Dingbats
- {
- 'begin': 0x3000,
- 'end': 0x303F
- },
- // CJK Symbols And Punctuation
- {
- 'begin': 0x3040,
- 'end': 0x309F
- },
- // Hiragana
- {
- 'begin': 0x30A0,
- 'end': 0x30FF
- },
- // Katakana
- {
- 'begin': 0x3100,
- 'end': 0x312F
- },
- // Bopomofo
- {
- 'begin': 0x3130,
- 'end': 0x318F
- },
- // Hangul Compatibility Jamo
- {
- 'begin': 0xA840,
- 'end': 0xA87F
- },
- // Phags-pa
- {
- 'begin': 0x3200,
- 'end': 0x32FF
- },
- // Enclosed CJK Letters And Months
- {
- 'begin': 0x3300,
- 'end': 0x33FF
- },
- // CJK Compatibility
- {
- 'begin': 0xAC00,
- 'end': 0xD7AF
- },
- // Hangul Syllables
- {
- 'begin': 0xD800,
- 'end': 0xDFFF
- },
- // Non-Plane 0 *
- {
- 'begin': 0x10900,
- 'end': 0x1091F
- },
- // Phoenicia
- {
- 'begin': 0x4E00,
- 'end': 0x9FFF
- },
- // CJK Unified Ideographs
- {
- 'begin': 0xE000,
- 'end': 0xF8FF
- },
- // Private Use Area (plane 0)
- {
- 'begin': 0x31C0,
- 'end': 0x31EF
- },
- // CJK Strokes
- {
- 'begin': 0xFB00,
- 'end': 0xFB4F
- },
- // Alphabetic Presentation Forms
- {
- 'begin': 0xFB50,
- 'end': 0xFDFF
- },
- // Arabic Presentation Forms-A
- {
- 'begin': 0xFE20,
- 'end': 0xFE2F
- },
- // Combining Half Marks
- {
- 'begin': 0xFE10,
- 'end': 0xFE1F
- },
- // Vertical Forms
- {
- 'begin': 0xFE50,
- 'end': 0xFE6F
- },
- // Small Form Variants
- {
- 'begin': 0xFE70,
- 'end': 0xFEFF
- },
- // Arabic Presentation Forms-B
- {
- 'begin': 0xFF00,
- 'end': 0xFFEF
- },
- // Halfwidth And Fullwidth Forms
- {
- 'begin': 0xFFF0,
- 'end': 0xFFFF
- },
- // Specials
- {
- 'begin': 0x0F00,
- 'end': 0x0FFF
- },
- // Tibetan
- {
- 'begin': 0x0700,
- 'end': 0x074F
- },
- // Syriac
- {
- 'begin': 0x0780,
- 'end': 0x07BF
- },
- // Thaana
- {
- 'begin': 0x0D80,
- 'end': 0x0DFF
- },
- // Sinhala
- {
- 'begin': 0x1000,
- 'end': 0x109F
- },
- // Myanmar
- {
- 'begin': 0x1200,
- 'end': 0x137F
- },
- // Ethiopic
- {
- 'begin': 0x13A0,
- 'end': 0x13FF
- },
- // Cherokee
- {
- 'begin': 0x1400,
- 'end': 0x167F
- },
- // Unified Canadian Aboriginal Syllabics
- {
- 'begin': 0x1680,
- 'end': 0x169F
- },
- // Ogham
- {
- 'begin': 0x16A0,
- 'end': 0x16FF
- },
- // Runic
- {
- 'begin': 0x1780,
- 'end': 0x17FF
- },
- // Khmer
- {
- 'begin': 0x1800,
- 'end': 0x18AF
- },
- // Mongolian
- {
- 'begin': 0x2800,
- 'end': 0x28FF
- },
- // Braille Patterns
- {
- 'begin': 0xA000,
- 'end': 0xA48F
- },
- // Yi Syllables
- {
- 'begin': 0x1700,
- 'end': 0x171F
- },
- // Tagalog
- {
- 'begin': 0x10300,
- 'end': 0x1032F
- },
- // Old Italic
- {
- 'begin': 0x10330,
- 'end': 0x1034F
- },
- // Gothic
- {
- 'begin': 0x10400,
- 'end': 0x1044F
- },
- // Deseret
- {
- 'begin': 0x1D000,
- 'end': 0x1D0FF
- },
- // Byzantine Musical Symbols
- {
- 'begin': 0x1D400,
- 'end': 0x1D7FF
- },
- // Mathematical Alphanumeric Symbols
- {
- 'begin': 0xFF000,
- 'end': 0xFFFFD
- },
- // Private Use (plane 15)
- {
- 'begin': 0xFE00,
- 'end': 0xFE0F
- },
- // Variation Selectors
- {
- 'begin': 0xE0000,
- 'end': 0xE007F
- },
- // Tags
- {
- 'begin': 0x1900,
- 'end': 0x194F
- },
- // Limbu
- {
- 'begin': 0x1950,
- 'end': 0x197F
- },
- // Tai Le
- {
- 'begin': 0x1980,
- 'end': 0x19DF
- },
- // New Tai Lue
- {
- 'begin': 0x1A00,
- 'end': 0x1A1F
- },
- // Buginese
- {
- 'begin': 0x2C00,
- 'end': 0x2C5F
- },
- // Glagolitic
- {
- 'begin': 0x2D30,
- 'end': 0x2D7F
- },
- // Tifinagh
- {
- 'begin': 0x4DC0,
- 'end': 0x4DFF
- },
- // Yijing Hexagram Symbols
- {
- 'begin': 0xA800,
- 'end': 0xA82F
- },
- // Syloti Nagri
- {
- 'begin': 0x10000,
- 'end': 0x1007F
- },
- // Linear B Syllabary
- {
- 'begin': 0x10140,
- 'end': 0x1018F
- },
- // Ancient Greek Numbers
- {
- 'begin': 0x10380,
- 'end': 0x1039F
- },
- // Ugaritic
- {
- 'begin': 0x103A0,
- 'end': 0x103DF
- },
- // Old Persian
- {
- 'begin': 0x10450,
- 'end': 0x1047F
- },
- // Shavian
- {
- 'begin': 0x10480,
- 'end': 0x104AF
- },
- // Osmanya
- {
- 'begin': 0x10800,
- 'end': 0x1083F
- },
- // Cypriot Syllabary
- {
- 'begin': 0x10A00,
- 'end': 0x10A5F
- },
- // Kharoshthi
- {
- 'begin': 0x1D300,
- 'end': 0x1D35F
- },
- // Tai Xuan Jing Symbols
- {
- 'begin': 0x12000,
- 'end': 0x123FF
- },
- // Cuneiform
- {
- 'begin': 0x1D360,
- 'end': 0x1D37F
- },
- // Counting Rod Numerals
- {
- 'begin': 0x1B80,
- 'end': 0x1BBF
- },
- // Sundanese
- {
- 'begin': 0x1C00,
- 'end': 0x1C4F
- },
- // Lepcha
- {
- 'begin': 0x1C50,
- 'end': 0x1C7F
- },
- // Ol Chiki
- {
- 'begin': 0xA880,
- 'end': 0xA8DF
- },
- // Saurashtra
- {
- 'begin': 0xA900,
- 'end': 0xA92F
- },
- // Kayah Li
- {
- 'begin': 0xA930,
- 'end': 0xA95F
- },
- // Rejang
- {
- 'begin': 0xAA00,
- 'end': 0xAA5F
- },
- // Cham
- {
- 'begin': 0x10190,
- 'end': 0x101CF
- },
- // Ancient Symbols
- {
- 'begin': 0x101D0,
- 'end': 0x101FF
- },
- // Phaistos Disc
- {
- 'begin': 0x102A0,
- 'end': 0x102DF
- },
- // Carian
- {
- 'begin': 0x1F030,
- 'end': 0x1F09F
- }
- ];
- // Domino Tiles
- function getUnicodeRangeFor(value) {
- for (var i = 0, ii = UnicodeRanges.length; i < ii; i++) {
- var range = UnicodeRanges[i];
- if (value >= range.begin && value < range.end) {
- return i;
- }
- }
- return -1;
- }
- function isRTLRangeFor(value) {
- var range = UnicodeRanges[13];
- if (value >= range.begin && value < range.end) {
- return true;
- }
- range = UnicodeRanges[11];
- if (value >= range.begin && value < range.end) {
- return true;
- }
- return false;
- }
- // The normalization table is obtained by filtering the Unicode characters
- // database with <compat> entries.
- var getNormalizedUnicodes = getLookupTableFactory(function (t) {
- t['\u00A8'] = '\u0020\u0308';
- t['\u00AF'] = '\u0020\u0304';
- t['\u00B4'] = '\u0020\u0301';
- t['\u00B5'] = '\u03BC';
- t['\u00B8'] = '\u0020\u0327';
- t['\u0132'] = '\u0049\u004A';
- t['\u0133'] = '\u0069\u006A';
- t['\u013F'] = '\u004C\u00B7';
- t['\u0140'] = '\u006C\u00B7';
- t['\u0149'] = '\u02BC\u006E';
- t['\u017F'] = '\u0073';
- t['\u01C4'] = '\u0044\u017D';
- t['\u01C5'] = '\u0044\u017E';
- t['\u01C6'] = '\u0064\u017E';
- t['\u01C7'] = '\u004C\u004A';
- t['\u01C8'] = '\u004C\u006A';
- t['\u01C9'] = '\u006C\u006A';
- t['\u01CA'] = '\u004E\u004A';
- t['\u01CB'] = '\u004E\u006A';
- t['\u01CC'] = '\u006E\u006A';
- t['\u01F1'] = '\u0044\u005A';
- t['\u01F2'] = '\u0044\u007A';
- t['\u01F3'] = '\u0064\u007A';
- t['\u02D8'] = '\u0020\u0306';
- t['\u02D9'] = '\u0020\u0307';
- t['\u02DA'] = '\u0020\u030A';
- t['\u02DB'] = '\u0020\u0328';
- t['\u02DC'] = '\u0020\u0303';
- t['\u02DD'] = '\u0020\u030B';
- t['\u037A'] = '\u0020\u0345';
- t['\u0384'] = '\u0020\u0301';
- t['\u03D0'] = '\u03B2';
- t['\u03D1'] = '\u03B8';
- t['\u03D2'] = '\u03A5';
- t['\u03D5'] = '\u03C6';
- t['\u03D6'] = '\u03C0';
- t['\u03F0'] = '\u03BA';
- t['\u03F1'] = '\u03C1';
- t['\u03F2'] = '\u03C2';
- t['\u03F4'] = '\u0398';
- t['\u03F5'] = '\u03B5';
- t['\u03F9'] = '\u03A3';
- t['\u0587'] = '\u0565\u0582';
- t['\u0675'] = '\u0627\u0674';
- t['\u0676'] = '\u0648\u0674';
- t['\u0677'] = '\u06C7\u0674';
- t['\u0678'] = '\u064A\u0674';
- t['\u0E33'] = '\u0E4D\u0E32';
- t['\u0EB3'] = '\u0ECD\u0EB2';
- t['\u0EDC'] = '\u0EAB\u0E99';
- t['\u0EDD'] = '\u0EAB\u0EA1';
- t['\u0F77'] = '\u0FB2\u0F81';
- t['\u0F79'] = '\u0FB3\u0F81';
- t['\u1E9A'] = '\u0061\u02BE';
- t['\u1FBD'] = '\u0020\u0313';
- t['\u1FBF'] = '\u0020\u0313';
- t['\u1FC0'] = '\u0020\u0342';
- t['\u1FFE'] = '\u0020\u0314';
- t['\u2002'] = '\u0020';
- t['\u2003'] = '\u0020';
- t['\u2004'] = '\u0020';
- t['\u2005'] = '\u0020';
- t['\u2006'] = '\u0020';
- t['\u2008'] = '\u0020';
- t['\u2009'] = '\u0020';
- t['\u200A'] = '\u0020';
- t['\u2017'] = '\u0020\u0333';
- t['\u2024'] = '\u002E';
- t['\u2025'] = '\u002E\u002E';
- t['\u2026'] = '\u002E\u002E\u002E';
- t['\u2033'] = '\u2032\u2032';
- t['\u2034'] = '\u2032\u2032\u2032';
- t['\u2036'] = '\u2035\u2035';
- t['\u2037'] = '\u2035\u2035\u2035';
- t['\u203C'] = '\u0021\u0021';
- t['\u203E'] = '\u0020\u0305';
- t['\u2047'] = '\u003F\u003F';
- t['\u2048'] = '\u003F\u0021';
- t['\u2049'] = '\u0021\u003F';
- t['\u2057'] = '\u2032\u2032\u2032\u2032';
- t['\u205F'] = '\u0020';
- t['\u20A8'] = '\u0052\u0073';
- t['\u2100'] = '\u0061\u002F\u0063';
- t['\u2101'] = '\u0061\u002F\u0073';
- t['\u2103'] = '\u00B0\u0043';
- t['\u2105'] = '\u0063\u002F\u006F';
- t['\u2106'] = '\u0063\u002F\u0075';
- t['\u2107'] = '\u0190';
- t['\u2109'] = '\u00B0\u0046';
- t['\u2116'] = '\u004E\u006F';
- t['\u2121'] = '\u0054\u0045\u004C';
- t['\u2135'] = '\u05D0';
- t['\u2136'] = '\u05D1';
- t['\u2137'] = '\u05D2';
- t['\u2138'] = '\u05D3';
- t['\u213B'] = '\u0046\u0041\u0058';
- t['\u2160'] = '\u0049';
- t['\u2161'] = '\u0049\u0049';
- t['\u2162'] = '\u0049\u0049\u0049';
- t['\u2163'] = '\u0049\u0056';
- t['\u2164'] = '\u0056';
- t['\u2165'] = '\u0056\u0049';
- t['\u2166'] = '\u0056\u0049\u0049';
- t['\u2167'] = '\u0056\u0049\u0049\u0049';
- t['\u2168'] = '\u0049\u0058';
- t['\u2169'] = '\u0058';
- t['\u216A'] = '\u0058\u0049';
- t['\u216B'] = '\u0058\u0049\u0049';
- t['\u216C'] = '\u004C';
- t['\u216D'] = '\u0043';
- t['\u216E'] = '\u0044';
- t['\u216F'] = '\u004D';
- t['\u2170'] = '\u0069';
- t['\u2171'] = '\u0069\u0069';
- t['\u2172'] = '\u0069\u0069\u0069';
- t['\u2173'] = '\u0069\u0076';
- t['\u2174'] = '\u0076';
- t['\u2175'] = '\u0076\u0069';
- t['\u2176'] = '\u0076\u0069\u0069';
- t['\u2177'] = '\u0076\u0069\u0069\u0069';
- t['\u2178'] = '\u0069\u0078';
- t['\u2179'] = '\u0078';
- t['\u217A'] = '\u0078\u0069';
- t['\u217B'] = '\u0078\u0069\u0069';
- t['\u217C'] = '\u006C';
- t['\u217D'] = '\u0063';
- t['\u217E'] = '\u0064';
- t['\u217F'] = '\u006D';
- t['\u222C'] = '\u222B\u222B';
- t['\u222D'] = '\u222B\u222B\u222B';
- t['\u222F'] = '\u222E\u222E';
- t['\u2230'] = '\u222E\u222E\u222E';
- t['\u2474'] = '\u0028\u0031\u0029';
- t['\u2475'] = '\u0028\u0032\u0029';
- t['\u2476'] = '\u0028\u0033\u0029';
- t['\u2477'] = '\u0028\u0034\u0029';
- t['\u2478'] = '\u0028\u0035\u0029';
- t['\u2479'] = '\u0028\u0036\u0029';
- t['\u247A'] = '\u0028\u0037\u0029';
- t['\u247B'] = '\u0028\u0038\u0029';
- t['\u247C'] = '\u0028\u0039\u0029';
- t['\u247D'] = '\u0028\u0031\u0030\u0029';
- t['\u247E'] = '\u0028\u0031\u0031\u0029';
- t['\u247F'] = '\u0028\u0031\u0032\u0029';
- t['\u2480'] = '\u0028\u0031\u0033\u0029';
- t['\u2481'] = '\u0028\u0031\u0034\u0029';
- t['\u2482'] = '\u0028\u0031\u0035\u0029';
- t['\u2483'] = '\u0028\u0031\u0036\u0029';
- t['\u2484'] = '\u0028\u0031\u0037\u0029';
- t['\u2485'] = '\u0028\u0031\u0038\u0029';
- t['\u2486'] = '\u0028\u0031\u0039\u0029';
- t['\u2487'] = '\u0028\u0032\u0030\u0029';
- t['\u2488'] = '\u0031\u002E';
- t['\u2489'] = '\u0032\u002E';
- t['\u248A'] = '\u0033\u002E';
- t['\u248B'] = '\u0034\u002E';
- t['\u248C'] = '\u0035\u002E';
- t['\u248D'] = '\u0036\u002E';
- t['\u248E'] = '\u0037\u002E';
- t['\u248F'] = '\u0038\u002E';
- t['\u2490'] = '\u0039\u002E';
- t['\u2491'] = '\u0031\u0030\u002E';
- t['\u2492'] = '\u0031\u0031\u002E';
- t['\u2493'] = '\u0031\u0032\u002E';
- t['\u2494'] = '\u0031\u0033\u002E';
- t['\u2495'] = '\u0031\u0034\u002E';
- t['\u2496'] = '\u0031\u0035\u002E';
- t['\u2497'] = '\u0031\u0036\u002E';
- t['\u2498'] = '\u0031\u0037\u002E';
- t['\u2499'] = '\u0031\u0038\u002E';
- t['\u249A'] = '\u0031\u0039\u002E';
- t['\u249B'] = '\u0032\u0030\u002E';
- t['\u249C'] = '\u0028\u0061\u0029';
- t['\u249D'] = '\u0028\u0062\u0029';
- t['\u249E'] = '\u0028\u0063\u0029';
- t['\u249F'] = '\u0028\u0064\u0029';
- t['\u24A0'] = '\u0028\u0065\u0029';
- t['\u24A1'] = '\u0028\u0066\u0029';
- t['\u24A2'] = '\u0028\u0067\u0029';
- t['\u24A3'] = '\u0028\u0068\u0029';
- t['\u24A4'] = '\u0028\u0069\u0029';
- t['\u24A5'] = '\u0028\u006A\u0029';
- t['\u24A6'] = '\u0028\u006B\u0029';
- t['\u24A7'] = '\u0028\u006C\u0029';
- t['\u24A8'] = '\u0028\u006D\u0029';
- t['\u24A9'] = '\u0028\u006E\u0029';
- t['\u24AA'] = '\u0028\u006F\u0029';
- t['\u24AB'] = '\u0028\u0070\u0029';
- t['\u24AC'] = '\u0028\u0071\u0029';
- t['\u24AD'] = '\u0028\u0072\u0029';
- t['\u24AE'] = '\u0028\u0073\u0029';
- t['\u24AF'] = '\u0028\u0074\u0029';
- t['\u24B0'] = '\u0028\u0075\u0029';
- t['\u24B1'] = '\u0028\u0076\u0029';
- t['\u24B2'] = '\u0028\u0077\u0029';
- t['\u24B3'] = '\u0028\u0078\u0029';
- t['\u24B4'] = '\u0028\u0079\u0029';
- t['\u24B5'] = '\u0028\u007A\u0029';
- t['\u2A0C'] = '\u222B\u222B\u222B\u222B';
- t['\u2A74'] = '\u003A\u003A\u003D';
- t['\u2A75'] = '\u003D\u003D';
- t['\u2A76'] = '\u003D\u003D\u003D';
- t['\u2E9F'] = '\u6BCD';
- t['\u2EF3'] = '\u9F9F';
- t['\u2F00'] = '\u4E00';
- t['\u2F01'] = '\u4E28';
- t['\u2F02'] = '\u4E36';
- t['\u2F03'] = '\u4E3F';
- t['\u2F04'] = '\u4E59';
- t['\u2F05'] = '\u4E85';
- t['\u2F06'] = '\u4E8C';
- t['\u2F07'] = '\u4EA0';
- t['\u2F08'] = '\u4EBA';
- t['\u2F09'] = '\u513F';
- t['\u2F0A'] = '\u5165';
- t['\u2F0B'] = '\u516B';
- t['\u2F0C'] = '\u5182';
- t['\u2F0D'] = '\u5196';
- t['\u2F0E'] = '\u51AB';
- t['\u2F0F'] = '\u51E0';
- t['\u2F10'] = '\u51F5';
- t['\u2F11'] = '\u5200';
- t['\u2F12'] = '\u529B';
- t['\u2F13'] = '\u52F9';
- t['\u2F14'] = '\u5315';
- t['\u2F15'] = '\u531A';
- t['\u2F16'] = '\u5338';
- t['\u2F17'] = '\u5341';
- t['\u2F18'] = '\u535C';
- t['\u2F19'] = '\u5369';
- t['\u2F1A'] = '\u5382';
- t['\u2F1B'] = '\u53B6';
- t['\u2F1C'] = '\u53C8';
- t['\u2F1D'] = '\u53E3';
- t['\u2F1E'] = '\u56D7';
- t['\u2F1F'] = '\u571F';
- t['\u2F20'] = '\u58EB';
- t['\u2F21'] = '\u5902';
- t['\u2F22'] = '\u590A';
- t['\u2F23'] = '\u5915';
- t['\u2F24'] = '\u5927';
- t['\u2F25'] = '\u5973';
- t['\u2F26'] = '\u5B50';
- t['\u2F27'] = '\u5B80';
- t['\u2F28'] = '\u5BF8';
- t['\u2F29'] = '\u5C0F';
- t['\u2F2A'] = '\u5C22';
- t['\u2F2B'] = '\u5C38';
- t['\u2F2C'] = '\u5C6E';
- t['\u2F2D'] = '\u5C71';
- t['\u2F2E'] = '\u5DDB';
- t['\u2F2F'] = '\u5DE5';
- t['\u2F30'] = '\u5DF1';
- t['\u2F31'] = '\u5DFE';
- t['\u2F32'] = '\u5E72';
- t['\u2F33'] = '\u5E7A';
- t['\u2F34'] = '\u5E7F';
- t['\u2F35'] = '\u5EF4';
- t['\u2F36'] = '\u5EFE';
- t['\u2F37'] = '\u5F0B';
- t['\u2F38'] = '\u5F13';
- t['\u2F39'] = '\u5F50';
- t['\u2F3A'] = '\u5F61';
- t['\u2F3B'] = '\u5F73';
- t['\u2F3C'] = '\u5FC3';
- t['\u2F3D'] = '\u6208';
- t['\u2F3E'] = '\u6236';
- t['\u2F3F'] = '\u624B';
- t['\u2F40'] = '\u652F';
- t['\u2F41'] = '\u6534';
- t['\u2F42'] = '\u6587';
- t['\u2F43'] = '\u6597';
- t['\u2F44'] = '\u65A4';
- t['\u2F45'] = '\u65B9';
- t['\u2F46'] = '\u65E0';
- t['\u2F47'] = '\u65E5';
- t['\u2F48'] = '\u66F0';
- t['\u2F49'] = '\u6708';
- t['\u2F4A'] = '\u6728';
- t['\u2F4B'] = '\u6B20';
- t['\u2F4C'] = '\u6B62';
- t['\u2F4D'] = '\u6B79';
- t['\u2F4E'] = '\u6BB3';
- t['\u2F4F'] = '\u6BCB';
- t['\u2F50'] = '\u6BD4';
- t['\u2F51'] = '\u6BDB';
- t['\u2F52'] = '\u6C0F';
- t['\u2F53'] = '\u6C14';
- t['\u2F54'] = '\u6C34';
- t['\u2F55'] = '\u706B';
- t['\u2F56'] = '\u722A';
- t['\u2F57'] = '\u7236';
- t['\u2F58'] = '\u723B';
- t['\u2F59'] = '\u723F';
- t['\u2F5A'] = '\u7247';
- t['\u2F5B'] = '\u7259';
- t['\u2F5C'] = '\u725B';
- t['\u2F5D'] = '\u72AC';
- t['\u2F5E'] = '\u7384';
- t['\u2F5F'] = '\u7389';
- t['\u2F60'] = '\u74DC';
- t['\u2F61'] = '\u74E6';
- t['\u2F62'] = '\u7518';
- t['\u2F63'] = '\u751F';
- t['\u2F64'] = '\u7528';
- t['\u2F65'] = '\u7530';
- t['\u2F66'] = '\u758B';
- t['\u2F67'] = '\u7592';
- t['\u2F68'] = '\u7676';
- t['\u2F69'] = '\u767D';
- t['\u2F6A'] = '\u76AE';
- t['\u2F6B'] = '\u76BF';
- t['\u2F6C'] = '\u76EE';
- t['\u2F6D'] = '\u77DB';
- t['\u2F6E'] = '\u77E2';
- t['\u2F6F'] = '\u77F3';
- t['\u2F70'] = '\u793A';
- t['\u2F71'] = '\u79B8';
- t['\u2F72'] = '\u79BE';
- t['\u2F73'] = '\u7A74';
- t['\u2F74'] = '\u7ACB';
- t['\u2F75'] = '\u7AF9';
- t['\u2F76'] = '\u7C73';
- t['\u2F77'] = '\u7CF8';
- t['\u2F78'] = '\u7F36';
- t['\u2F79'] = '\u7F51';
- t['\u2F7A'] = '\u7F8A';
- t['\u2F7B'] = '\u7FBD';
- t['\u2F7C'] = '\u8001';
- t['\u2F7D'] = '\u800C';
- t['\u2F7E'] = '\u8012';
- t['\u2F7F'] = '\u8033';
- t['\u2F80'] = '\u807F';
- t['\u2F81'] = '\u8089';
- t['\u2F82'] = '\u81E3';
- t['\u2F83'] = '\u81EA';
- t['\u2F84'] = '\u81F3';
- t['\u2F85'] = '\u81FC';
- t['\u2F86'] = '\u820C';
- t['\u2F87'] = '\u821B';
- t['\u2F88'] = '\u821F';
- t['\u2F89'] = '\u826E';
- t['\u2F8A'] = '\u8272';
- t['\u2F8B'] = '\u8278';
- t['\u2F8C'] = '\u864D';
- t['\u2F8D'] = '\u866B';
- t['\u2F8E'] = '\u8840';
- t['\u2F8F'] = '\u884C';
- t['\u2F90'] = '\u8863';
- t['\u2F91'] = '\u897E';
- t['\u2F92'] = '\u898B';
- t['\u2F93'] = '\u89D2';
- t['\u2F94'] = '\u8A00';
- t['\u2F95'] = '\u8C37';
- t['\u2F96'] = '\u8C46';
- t['\u2F97'] = '\u8C55';
- t['\u2F98'] = '\u8C78';
- t['\u2F99'] = '\u8C9D';
- t['\u2F9A'] = '\u8D64';
- t['\u2F9B'] = '\u8D70';
- t['\u2F9C'] = '\u8DB3';
- t['\u2F9D'] = '\u8EAB';
- t['\u2F9E'] = '\u8ECA';
- t['\u2F9F'] = '\u8F9B';
- t['\u2FA0'] = '\u8FB0';
- t['\u2FA1'] = '\u8FB5';
- t['\u2FA2'] = '\u9091';
- t['\u2FA3'] = '\u9149';
- t['\u2FA4'] = '\u91C6';
- t['\u2FA5'] = '\u91CC';
- t['\u2FA6'] = '\u91D1';
- t['\u2FA7'] = '\u9577';
- t['\u2FA8'] = '\u9580';
- t['\u2FA9'] = '\u961C';
- t['\u2FAA'] = '\u96B6';
- t['\u2FAB'] = '\u96B9';
- t['\u2FAC'] = '\u96E8';
- t['\u2FAD'] = '\u9751';
- t['\u2FAE'] = '\u975E';
- t['\u2FAF'] = '\u9762';
- t['\u2FB0'] = '\u9769';
- t['\u2FB1'] = '\u97CB';
- t['\u2FB2'] = '\u97ED';
- t['\u2FB3'] = '\u97F3';
- t['\u2FB4'] = '\u9801';
- t['\u2FB5'] = '\u98A8';
- t['\u2FB6'] = '\u98DB';
- t['\u2FB7'] = '\u98DF';
- t['\u2FB8'] = '\u9996';
- t['\u2FB9'] = '\u9999';
- t['\u2FBA'] = '\u99AC';
- t['\u2FBB'] = '\u9AA8';
- t['\u2FBC'] = '\u9AD8';
- t['\u2FBD'] = '\u9ADF';
- t['\u2FBE'] = '\u9B25';
- t['\u2FBF'] = '\u9B2F';
- t['\u2FC0'] = '\u9B32';
- t['\u2FC1'] = '\u9B3C';
- t['\u2FC2'] = '\u9B5A';
- t['\u2FC3'] = '\u9CE5';
- t['\u2FC4'] = '\u9E75';
- t['\u2FC5'] = '\u9E7F';
- t['\u2FC6'] = '\u9EA5';
- t['\u2FC7'] = '\u9EBB';
- t['\u2FC8'] = '\u9EC3';
- t['\u2FC9'] = '\u9ECD';
- t['\u2FCA'] = '\u9ED1';
- t['\u2FCB'] = '\u9EF9';
- t['\u2FCC'] = '\u9EFD';
- t['\u2FCD'] = '\u9F0E';
- t['\u2FCE'] = '\u9F13';
- t['\u2FCF'] = '\u9F20';
- t['\u2FD0'] = '\u9F3B';
- t['\u2FD1'] = '\u9F4A';
- t['\u2FD2'] = '\u9F52';
- t['\u2FD3'] = '\u9F8D';
- t['\u2FD4'] = '\u9F9C';
- t['\u2FD5'] = '\u9FA0';
- t['\u3036'] = '\u3012';
- t['\u3038'] = '\u5341';
- t['\u3039'] = '\u5344';
- t['\u303A'] = '\u5345';
- t['\u309B'] = '\u0020\u3099';
- t['\u309C'] = '\u0020\u309A';
- t['\u3131'] = '\u1100';
- t['\u3132'] = '\u1101';
- t['\u3133'] = '\u11AA';
- t['\u3134'] = '\u1102';
- t['\u3135'] = '\u11AC';
- t['\u3136'] = '\u11AD';
- t['\u3137'] = '\u1103';
- t['\u3138'] = '\u1104';
- t['\u3139'] = '\u1105';
- t['\u313A'] = '\u11B0';
- t['\u313B'] = '\u11B1';
- t['\u313C'] = '\u11B2';
- t['\u313D'] = '\u11B3';
- t['\u313E'] = '\u11B4';
- t['\u313F'] = '\u11B5';
- t['\u3140'] = '\u111A';
- t['\u3141'] = '\u1106';
- t['\u3142'] = '\u1107';
- t['\u3143'] = '\u1108';
- t['\u3144'] = '\u1121';
- t['\u3145'] = '\u1109';
- t['\u3146'] = '\u110A';
- t['\u3147'] = '\u110B';
- t['\u3148'] = '\u110C';
- t['\u3149'] = '\u110D';
- t['\u314A'] = '\u110E';
- t['\u314B'] = '\u110F';
- t['\u314C'] = '\u1110';
- t['\u314D'] = '\u1111';
- t['\u314E'] = '\u1112';
- t['\u314F'] = '\u1161';
- t['\u3150'] = '\u1162';
- t['\u3151'] = '\u1163';
- t['\u3152'] = '\u1164';
- t['\u3153'] = '\u1165';
- t['\u3154'] = '\u1166';
- t['\u3155'] = '\u1167';
- t['\u3156'] = '\u1168';
- t['\u3157'] = '\u1169';
- t['\u3158'] = '\u116A';
- t['\u3159'] = '\u116B';
- t['\u315A'] = '\u116C';
- t['\u315B'] = '\u116D';
- t['\u315C'] = '\u116E';
- t['\u315D'] = '\u116F';
- t['\u315E'] = '\u1170';
- t['\u315F'] = '\u1171';
- t['\u3160'] = '\u1172';
- t['\u3161'] = '\u1173';
- t['\u3162'] = '\u1174';
- t['\u3163'] = '\u1175';
- t['\u3164'] = '\u1160';
- t['\u3165'] = '\u1114';
- t['\u3166'] = '\u1115';
- t['\u3167'] = '\u11C7';
- t['\u3168'] = '\u11C8';
- t['\u3169'] = '\u11CC';
- t['\u316A'] = '\u11CE';
- t['\u316B'] = '\u11D3';
- t['\u316C'] = '\u11D7';
- t['\u316D'] = '\u11D9';
- t['\u316E'] = '\u111C';
- t['\u316F'] = '\u11DD';
- t['\u3170'] = '\u11DF';
- t['\u3171'] = '\u111D';
- t['\u3172'] = '\u111E';
- t['\u3173'] = '\u1120';
- t['\u3174'] = '\u1122';
- t['\u3175'] = '\u1123';
- t['\u3176'] = '\u1127';
- t['\u3177'] = '\u1129';
- t['\u3178'] = '\u112B';
- t['\u3179'] = '\u112C';
- t['\u317A'] = '\u112D';
- t['\u317B'] = '\u112E';
- t['\u317C'] = '\u112F';
- t['\u317D'] = '\u1132';
- t['\u317E'] = '\u1136';
- t['\u317F'] = '\u1140';
- t['\u3180'] = '\u1147';
- t['\u3181'] = '\u114C';
- t['\u3182'] = '\u11F1';
- t['\u3183'] = '\u11F2';
- t['\u3184'] = '\u1157';
- t['\u3185'] = '\u1158';
- t['\u3186'] = '\u1159';
- t['\u3187'] = '\u1184';
- t['\u3188'] = '\u1185';
- t['\u3189'] = '\u1188';
- t['\u318A'] = '\u1191';
- t['\u318B'] = '\u1192';
- t['\u318C'] = '\u1194';
- t['\u318D'] = '\u119E';
- t['\u318E'] = '\u11A1';
- t['\u3200'] = '\u0028\u1100\u0029';
- t['\u3201'] = '\u0028\u1102\u0029';
- t['\u3202'] = '\u0028\u1103\u0029';
- t['\u3203'] = '\u0028\u1105\u0029';
- t['\u3204'] = '\u0028\u1106\u0029';
- t['\u3205'] = '\u0028\u1107\u0029';
- t['\u3206'] = '\u0028\u1109\u0029';
- t['\u3207'] = '\u0028\u110B\u0029';
- t['\u3208'] = '\u0028\u110C\u0029';
- t['\u3209'] = '\u0028\u110E\u0029';
- t['\u320A'] = '\u0028\u110F\u0029';
- t['\u320B'] = '\u0028\u1110\u0029';
- t['\u320C'] = '\u0028\u1111\u0029';
- t['\u320D'] = '\u0028\u1112\u0029';
- t['\u320E'] = '\u0028\u1100\u1161\u0029';
- t['\u320F'] = '\u0028\u1102\u1161\u0029';
- t['\u3210'] = '\u0028\u1103\u1161\u0029';
- t['\u3211'] = '\u0028\u1105\u1161\u0029';
- t['\u3212'] = '\u0028\u1106\u1161\u0029';
- t['\u3213'] = '\u0028\u1107\u1161\u0029';
- t['\u3214'] = '\u0028\u1109\u1161\u0029';
- t['\u3215'] = '\u0028\u110B\u1161\u0029';
- t['\u3216'] = '\u0028\u110C\u1161\u0029';
- t['\u3217'] = '\u0028\u110E\u1161\u0029';
- t['\u3218'] = '\u0028\u110F\u1161\u0029';
- t['\u3219'] = '\u0028\u1110\u1161\u0029';
- t['\u321A'] = '\u0028\u1111\u1161\u0029';
- t['\u321B'] = '\u0028\u1112\u1161\u0029';
- t['\u321C'] = '\u0028\u110C\u116E\u0029';
- t['\u321D'] = '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029';
- t['\u321E'] = '\u0028\u110B\u1169\u1112\u116E\u0029';
- t['\u3220'] = '\u0028\u4E00\u0029';
- t['\u3221'] = '\u0028\u4E8C\u0029';
- t['\u3222'] = '\u0028\u4E09\u0029';
- t['\u3223'] = '\u0028\u56DB\u0029';
- t['\u3224'] = '\u0028\u4E94\u0029';
- t['\u3225'] = '\u0028\u516D\u0029';
- t['\u3226'] = '\u0028\u4E03\u0029';
- t['\u3227'] = '\u0028\u516B\u0029';
- t['\u3228'] = '\u0028\u4E5D\u0029';
- t['\u3229'] = '\u0028\u5341\u0029';
- t['\u322A'] = '\u0028\u6708\u0029';
- t['\u322B'] = '\u0028\u706B\u0029';
- t['\u322C'] = '\u0028\u6C34\u0029';
- t['\u322D'] = '\u0028\u6728\u0029';
- t['\u322E'] = '\u0028\u91D1\u0029';
- t['\u322F'] = '\u0028\u571F\u0029';
- t['\u3230'] = '\u0028\u65E5\u0029';
- t['\u3231'] = '\u0028\u682A\u0029';
- t['\u3232'] = '\u0028\u6709\u0029';
- t['\u3233'] = '\u0028\u793E\u0029';
- t['\u3234'] = '\u0028\u540D\u0029';
- t['\u3235'] = '\u0028\u7279\u0029';
- t['\u3236'] = '\u0028\u8CA1\u0029';
- t['\u3237'] = '\u0028\u795D\u0029';
- t['\u3238'] = '\u0028\u52B4\u0029';
- t['\u3239'] = '\u0028\u4EE3\u0029';
- t['\u323A'] = '\u0028\u547C\u0029';
- t['\u323B'] = '\u0028\u5B66\u0029';
- t['\u323C'] = '\u0028\u76E3\u0029';
- t['\u323D'] = '\u0028\u4F01\u0029';
- t['\u323E'] = '\u0028\u8CC7\u0029';
- t['\u323F'] = '\u0028\u5354\u0029';
- t['\u3240'] = '\u0028\u796D\u0029';
- t['\u3241'] = '\u0028\u4F11\u0029';
- t['\u3242'] = '\u0028\u81EA\u0029';
- t['\u3243'] = '\u0028\u81F3\u0029';
- t['\u32C0'] = '\u0031\u6708';
- t['\u32C1'] = '\u0032\u6708';
- t['\u32C2'] = '\u0033\u6708';
- t['\u32C3'] = '\u0034\u6708';
- t['\u32C4'] = '\u0035\u6708';
- t['\u32C5'] = '\u0036\u6708';
- t['\u32C6'] = '\u0037\u6708';
- t['\u32C7'] = '\u0038\u6708';
- t['\u32C8'] = '\u0039\u6708';
- t['\u32C9'] = '\u0031\u0030\u6708';
- t['\u32CA'] = '\u0031\u0031\u6708';
- t['\u32CB'] = '\u0031\u0032\u6708';
- t['\u3358'] = '\u0030\u70B9';
- t['\u3359'] = '\u0031\u70B9';
- t['\u335A'] = '\u0032\u70B9';
- t['\u335B'] = '\u0033\u70B9';
- t['\u335C'] = '\u0034\u70B9';
- t['\u335D'] = '\u0035\u70B9';
- t['\u335E'] = '\u0036\u70B9';
- t['\u335F'] = '\u0037\u70B9';
- t['\u3360'] = '\u0038\u70B9';
- t['\u3361'] = '\u0039\u70B9';
- t['\u3362'] = '\u0031\u0030\u70B9';
- t['\u3363'] = '\u0031\u0031\u70B9';
- t['\u3364'] = '\u0031\u0032\u70B9';
- t['\u3365'] = '\u0031\u0033\u70B9';
- t['\u3366'] = '\u0031\u0034\u70B9';
- t['\u3367'] = '\u0031\u0035\u70B9';
- t['\u3368'] = '\u0031\u0036\u70B9';
- t['\u3369'] = '\u0031\u0037\u70B9';
- t['\u336A'] = '\u0031\u0038\u70B9';
- t['\u336B'] = '\u0031\u0039\u70B9';
- t['\u336C'] = '\u0032\u0030\u70B9';
- t['\u336D'] = '\u0032\u0031\u70B9';
- t['\u336E'] = '\u0032\u0032\u70B9';
- t['\u336F'] = '\u0032\u0033\u70B9';
- t['\u3370'] = '\u0032\u0034\u70B9';
- t['\u33E0'] = '\u0031\u65E5';
- t['\u33E1'] = '\u0032\u65E5';
- t['\u33E2'] = '\u0033\u65E5';
- t['\u33E3'] = '\u0034\u65E5';
- t['\u33E4'] = '\u0035\u65E5';
- t['\u33E5'] = '\u0036\u65E5';
- t['\u33E6'] = '\u0037\u65E5';
- t['\u33E7'] = '\u0038\u65E5';
- t['\u33E8'] = '\u0039\u65E5';
- t['\u33E9'] = '\u0031\u0030\u65E5';
- t['\u33EA'] = '\u0031\u0031\u65E5';
- t['\u33EB'] = '\u0031\u0032\u65E5';
- t['\u33EC'] = '\u0031\u0033\u65E5';
- t['\u33ED'] = '\u0031\u0034\u65E5';
- t['\u33EE'] = '\u0031\u0035\u65E5';
- t['\u33EF'] = '\u0031\u0036\u65E5';
- t['\u33F0'] = '\u0031\u0037\u65E5';
- t['\u33F1'] = '\u0031\u0038\u65E5';
- t['\u33F2'] = '\u0031\u0039\u65E5';
- t['\u33F3'] = '\u0032\u0030\u65E5';
- t['\u33F4'] = '\u0032\u0031\u65E5';
- t['\u33F5'] = '\u0032\u0032\u65E5';
- t['\u33F6'] = '\u0032\u0033\u65E5';
- t['\u33F7'] = '\u0032\u0034\u65E5';
- t['\u33F8'] = '\u0032\u0035\u65E5';
- t['\u33F9'] = '\u0032\u0036\u65E5';
- t['\u33FA'] = '\u0032\u0037\u65E5';
- t['\u33FB'] = '\u0032\u0038\u65E5';
- t['\u33FC'] = '\u0032\u0039\u65E5';
- t['\u33FD'] = '\u0033\u0030\u65E5';
- t['\u33FE'] = '\u0033\u0031\u65E5';
- t['\uFB00'] = '\u0066\u0066';
- t['\uFB01'] = '\u0066\u0069';
- t['\uFB02'] = '\u0066\u006C';
- t['\uFB03'] = '\u0066\u0066\u0069';
- t['\uFB04'] = '\u0066\u0066\u006C';
- t['\uFB05'] = '\u017F\u0074';
- t['\uFB06'] = '\u0073\u0074';
- t['\uFB13'] = '\u0574\u0576';
- t['\uFB14'] = '\u0574\u0565';
- t['\uFB15'] = '\u0574\u056B';
- t['\uFB16'] = '\u057E\u0576';
- t['\uFB17'] = '\u0574\u056D';
- t['\uFB4F'] = '\u05D0\u05DC';
- t['\uFB50'] = '\u0671';
- t['\uFB51'] = '\u0671';
- t['\uFB52'] = '\u067B';
- t['\uFB53'] = '\u067B';
- t['\uFB54'] = '\u067B';
- t['\uFB55'] = '\u067B';
- t['\uFB56'] = '\u067E';
- t['\uFB57'] = '\u067E';
- t['\uFB58'] = '\u067E';
- t['\uFB59'] = '\u067E';
- t['\uFB5A'] = '\u0680';
- t['\uFB5B'] = '\u0680';
- t['\uFB5C'] = '\u0680';
- t['\uFB5D'] = '\u0680';
- t['\uFB5E'] = '\u067A';
- t['\uFB5F'] = '\u067A';
- t['\uFB60'] = '\u067A';
- t['\uFB61'] = '\u067A';
- t['\uFB62'] = '\u067F';
- t['\uFB63'] = '\u067F';
- t['\uFB64'] = '\u067F';
- t['\uFB65'] = '\u067F';
- t['\uFB66'] = '\u0679';
- t['\uFB67'] = '\u0679';
- t['\uFB68'] = '\u0679';
- t['\uFB69'] = '\u0679';
- t['\uFB6A'] = '\u06A4';
- t['\uFB6B'] = '\u06A4';
- t['\uFB6C'] = '\u06A4';
- t['\uFB6D'] = '\u06A4';
- t['\uFB6E'] = '\u06A6';
- t['\uFB6F'] = '\u06A6';
- t['\uFB70'] = '\u06A6';
- t['\uFB71'] = '\u06A6';
- t['\uFB72'] = '\u0684';
- t['\uFB73'] = '\u0684';
- t['\uFB74'] = '\u0684';
- t['\uFB75'] = '\u0684';
- t['\uFB76'] = '\u0683';
- t['\uFB77'] = '\u0683';
- t['\uFB78'] = '\u0683';
- t['\uFB79'] = '\u0683';
- t['\uFB7A'] = '\u0686';
- t['\uFB7B'] = '\u0686';
- t['\uFB7C'] = '\u0686';
- t['\uFB7D'] = '\u0686';
- t['\uFB7E'] = '\u0687';
- t['\uFB7F'] = '\u0687';
- t['\uFB80'] = '\u0687';
- t['\uFB81'] = '\u0687';
- t['\uFB82'] = '\u068D';
- t['\uFB83'] = '\u068D';
- t['\uFB84'] = '\u068C';
- t['\uFB85'] = '\u068C';
- t['\uFB86'] = '\u068E';
- t['\uFB87'] = '\u068E';
- t['\uFB88'] = '\u0688';
- t['\uFB89'] = '\u0688';
- t['\uFB8A'] = '\u0698';
- t['\uFB8B'] = '\u0698';
- t['\uFB8C'] = '\u0691';
- t['\uFB8D'] = '\u0691';
- t['\uFB8E'] = '\u06A9';
- t['\uFB8F'] = '\u06A9';
- t['\uFB90'] = '\u06A9';
- t['\uFB91'] = '\u06A9';
- t['\uFB92'] = '\u06AF';
- t['\uFB93'] = '\u06AF';
- t['\uFB94'] = '\u06AF';
- t['\uFB95'] = '\u06AF';
- t['\uFB96'] = '\u06B3';
- t['\uFB97'] = '\u06B3';
- t['\uFB98'] = '\u06B3';
- t['\uFB99'] = '\u06B3';
- t['\uFB9A'] = '\u06B1';
- t['\uFB9B'] = '\u06B1';
- t['\uFB9C'] = '\u06B1';
- t['\uFB9D'] = '\u06B1';
- t['\uFB9E'] = '\u06BA';
- t['\uFB9F'] = '\u06BA';
- t['\uFBA0'] = '\u06BB';
- t['\uFBA1'] = '\u06BB';
- t['\uFBA2'] = '\u06BB';
- t['\uFBA3'] = '\u06BB';
- t['\uFBA4'] = '\u06C0';
- t['\uFBA5'] = '\u06C0';
- t['\uFBA6'] = '\u06C1';
- t['\uFBA7'] = '\u06C1';
- t['\uFBA8'] = '\u06C1';
- t['\uFBA9'] = '\u06C1';
- t['\uFBAA'] = '\u06BE';
- t['\uFBAB'] = '\u06BE';
- t['\uFBAC'] = '\u06BE';
- t['\uFBAD'] = '\u06BE';
- t['\uFBAE'] = '\u06D2';
- t['\uFBAF'] = '\u06D2';
- t['\uFBB0'] = '\u06D3';
- t['\uFBB1'] = '\u06D3';
- t['\uFBD3'] = '\u06AD';
- t['\uFBD4'] = '\u06AD';
- t['\uFBD5'] = '\u06AD';
- t['\uFBD6'] = '\u06AD';
- t['\uFBD7'] = '\u06C7';
- t['\uFBD8'] = '\u06C7';
- t['\uFBD9'] = '\u06C6';
- t['\uFBDA'] = '\u06C6';
- t['\uFBDB'] = '\u06C8';
- t['\uFBDC'] = '\u06C8';
- t['\uFBDD'] = '\u0677';
- t['\uFBDE'] = '\u06CB';
- t['\uFBDF'] = '\u06CB';
- t['\uFBE0'] = '\u06C5';
- t['\uFBE1'] = '\u06C5';
- t['\uFBE2'] = '\u06C9';
- t['\uFBE3'] = '\u06C9';
- t['\uFBE4'] = '\u06D0';
- t['\uFBE5'] = '\u06D0';
- t['\uFBE6'] = '\u06D0';
- t['\uFBE7'] = '\u06D0';
- t['\uFBE8'] = '\u0649';
- t['\uFBE9'] = '\u0649';
- t['\uFBEA'] = '\u0626\u0627';
- t['\uFBEB'] = '\u0626\u0627';
- t['\uFBEC'] = '\u0626\u06D5';
- t['\uFBED'] = '\u0626\u06D5';
- t['\uFBEE'] = '\u0626\u0648';
- t['\uFBEF'] = '\u0626\u0648';
- t['\uFBF0'] = '\u0626\u06C7';
- t['\uFBF1'] = '\u0626\u06C7';
- t['\uFBF2'] = '\u0626\u06C6';
- t['\uFBF3'] = '\u0626\u06C6';
- t['\uFBF4'] = '\u0626\u06C8';
- t['\uFBF5'] = '\u0626\u06C8';
- t['\uFBF6'] = '\u0626\u06D0';
- t['\uFBF7'] = '\u0626\u06D0';
- t['\uFBF8'] = '\u0626\u06D0';
- t['\uFBF9'] = '\u0626\u0649';
- t['\uFBFA'] = '\u0626\u0649';
- t['\uFBFB'] = '\u0626\u0649';
- t['\uFBFC'] = '\u06CC';
- t['\uFBFD'] = '\u06CC';
- t['\uFBFE'] = '\u06CC';
- t['\uFBFF'] = '\u06CC';
- t['\uFC00'] = '\u0626\u062C';
- t['\uFC01'] = '\u0626\u062D';
- t['\uFC02'] = '\u0626\u0645';
- t['\uFC03'] = '\u0626\u0649';
- t['\uFC04'] = '\u0626\u064A';
- t['\uFC05'] = '\u0628\u062C';
- t['\uFC06'] = '\u0628\u062D';
- t['\uFC07'] = '\u0628\u062E';
- t['\uFC08'] = '\u0628\u0645';
- t['\uFC09'] = '\u0628\u0649';
- t['\uFC0A'] = '\u0628\u064A';
- t['\uFC0B'] = '\u062A\u062C';
- t['\uFC0C'] = '\u062A\u062D';
- t['\uFC0D'] = '\u062A\u062E';
- t['\uFC0E'] = '\u062A\u0645';
- t['\uFC0F'] = '\u062A\u0649';
- t['\uFC10'] = '\u062A\u064A';
- t['\uFC11'] = '\u062B\u062C';
- t['\uFC12'] = '\u062B\u0645';
- t['\uFC13'] = '\u062B\u0649';
- t['\uFC14'] = '\u062B\u064A';
- t['\uFC15'] = '\u062C\u062D';
- t['\uFC16'] = '\u062C\u0645';
- t['\uFC17'] = '\u062D\u062C';
- t['\uFC18'] = '\u062D\u0645';
- t['\uFC19'] = '\u062E\u062C';
- t['\uFC1A'] = '\u062E\u062D';
- t['\uFC1B'] = '\u062E\u0645';
- t['\uFC1C'] = '\u0633\u062C';
- t['\uFC1D'] = '\u0633\u062D';
- t['\uFC1E'] = '\u0633\u062E';
- t['\uFC1F'] = '\u0633\u0645';
- t['\uFC20'] = '\u0635\u062D';
- t['\uFC21'] = '\u0635\u0645';
- t['\uFC22'] = '\u0636\u062C';
- t['\uFC23'] = '\u0636\u062D';
- t['\uFC24'] = '\u0636\u062E';
- t['\uFC25'] = '\u0636\u0645';
- t['\uFC26'] = '\u0637\u062D';
- t['\uFC27'] = '\u0637\u0645';
- t['\uFC28'] = '\u0638\u0645';
- t['\uFC29'] = '\u0639\u062C';
- t['\uFC2A'] = '\u0639\u0645';
- t['\uFC2B'] = '\u063A\u062C';
- t['\uFC2C'] = '\u063A\u0645';
- t['\uFC2D'] = '\u0641\u062C';
- t['\uFC2E'] = '\u0641\u062D';
- t['\uFC2F'] = '\u0641\u062E';
- t['\uFC30'] = '\u0641\u0645';
- t['\uFC31'] = '\u0641\u0649';
- t['\uFC32'] = '\u0641\u064A';
- t['\uFC33'] = '\u0642\u062D';
- t['\uFC34'] = '\u0642\u0645';
- t['\uFC35'] = '\u0642\u0649';
- t['\uFC36'] = '\u0642\u064A';
- t['\uFC37'] = '\u0643\u0627';
- t['\uFC38'] = '\u0643\u062C';
- t['\uFC39'] = '\u0643\u062D';
- t['\uFC3A'] = '\u0643\u062E';
- t['\uFC3B'] = '\u0643\u0644';
- t['\uFC3C'] = '\u0643\u0645';
- t['\uFC3D'] = '\u0643\u0649';
- t['\uFC3E'] = '\u0643\u064A';
- t['\uFC3F'] = '\u0644\u062C';
- t['\uFC40'] = '\u0644\u062D';
- t['\uFC41'] = '\u0644\u062E';
- t['\uFC42'] = '\u0644\u0645';
- t['\uFC43'] = '\u0644\u0649';
- t['\uFC44'] = '\u0644\u064A';
- t['\uFC45'] = '\u0645\u062C';
- t['\uFC46'] = '\u0645\u062D';
- t['\uFC47'] = '\u0645\u062E';
- t['\uFC48'] = '\u0645\u0645';
- t['\uFC49'] = '\u0645\u0649';
- t['\uFC4A'] = '\u0645\u064A';
- t['\uFC4B'] = '\u0646\u062C';
- t['\uFC4C'] = '\u0646\u062D';
- t['\uFC4D'] = '\u0646\u062E';
- t['\uFC4E'] = '\u0646\u0645';
- t['\uFC4F'] = '\u0646\u0649';
- t['\uFC50'] = '\u0646\u064A';
- t['\uFC51'] = '\u0647\u062C';
- t['\uFC52'] = '\u0647\u0645';
- t['\uFC53'] = '\u0647\u0649';
- t['\uFC54'] = '\u0647\u064A';
- t['\uFC55'] = '\u064A\u062C';
- t['\uFC56'] = '\u064A\u062D';
- t['\uFC57'] = '\u064A\u062E';
- t['\uFC58'] = '\u064A\u0645';
- t['\uFC59'] = '\u064A\u0649';
- t['\uFC5A'] = '\u064A\u064A';
- t['\uFC5B'] = '\u0630\u0670';
- t['\uFC5C'] = '\u0631\u0670';
- t['\uFC5D'] = '\u0649\u0670';
- t['\uFC5E'] = '\u0020\u064C\u0651';
- t['\uFC5F'] = '\u0020\u064D\u0651';
- t['\uFC60'] = '\u0020\u064E\u0651';
- t['\uFC61'] = '\u0020\u064F\u0651';
- t['\uFC62'] = '\u0020\u0650\u0651';
- t['\uFC63'] = '\u0020\u0651\u0670';
- t['\uFC64'] = '\u0626\u0631';
- t['\uFC65'] = '\u0626\u0632';
- t['\uFC66'] = '\u0626\u0645';
- t['\uFC67'] = '\u0626\u0646';
- t['\uFC68'] = '\u0626\u0649';
- t['\uFC69'] = '\u0626\u064A';
- t['\uFC6A'] = '\u0628\u0631';
- t['\uFC6B'] = '\u0628\u0632';
- t['\uFC6C'] = '\u0628\u0645';
- t['\uFC6D'] = '\u0628\u0646';
- t['\uFC6E'] = '\u0628\u0649';
- t['\uFC6F'] = '\u0628\u064A';
- t['\uFC70'] = '\u062A\u0631';
- t['\uFC71'] = '\u062A\u0632';
- t['\uFC72'] = '\u062A\u0645';
- t['\uFC73'] = '\u062A\u0646';
- t['\uFC74'] = '\u062A\u0649';
- t['\uFC75'] = '\u062A\u064A';
- t['\uFC76'] = '\u062B\u0631';
- t['\uFC77'] = '\u062B\u0632';
- t['\uFC78'] = '\u062B\u0645';
- t['\uFC79'] = '\u062B\u0646';
- t['\uFC7A'] = '\u062B\u0649';
- t['\uFC7B'] = '\u062B\u064A';
- t['\uFC7C'] = '\u0641\u0649';
- t['\uFC7D'] = '\u0641\u064A';
- t['\uFC7E'] = '\u0642\u0649';
- t['\uFC7F'] = '\u0642\u064A';
- t['\uFC80'] = '\u0643\u0627';
- t['\uFC81'] = '\u0643\u0644';
- t['\uFC82'] = '\u0643\u0645';
- t['\uFC83'] = '\u0643\u0649';
- t['\uFC84'] = '\u0643\u064A';
- t['\uFC85'] = '\u0644\u0645';
- t['\uFC86'] = '\u0644\u0649';
- t['\uFC87'] = '\u0644\u064A';
- t['\uFC88'] = '\u0645\u0627';
- t['\uFC89'] = '\u0645\u0645';
- t['\uFC8A'] = '\u0646\u0631';
- t['\uFC8B'] = '\u0646\u0632';
- t['\uFC8C'] = '\u0646\u0645';
- t['\uFC8D'] = '\u0646\u0646';
- t['\uFC8E'] = '\u0646\u0649';
- t['\uFC8F'] = '\u0646\u064A';
- t['\uFC90'] = '\u0649\u0670';
- t['\uFC91'] = '\u064A\u0631';
- t['\uFC92'] = '\u064A\u0632';
- t['\uFC93'] = '\u064A\u0645';
- t['\uFC94'] = '\u064A\u0646';
- t['\uFC95'] = '\u064A\u0649';
- t['\uFC96'] = '\u064A\u064A';
- t['\uFC97'] = '\u0626\u062C';
- t['\uFC98'] = '\u0626\u062D';
- t['\uFC99'] = '\u0626\u062E';
- t['\uFC9A'] = '\u0626\u0645';
- t['\uFC9B'] = '\u0626\u0647';
- t['\uFC9C'] = '\u0628\u062C';
- t['\uFC9D'] = '\u0628\u062D';
- t['\uFC9E'] = '\u0628\u062E';
- t['\uFC9F'] = '\u0628\u0645';
- t['\uFCA0'] = '\u0628\u0647';
- t['\uFCA1'] = '\u062A\u062C';
- t['\uFCA2'] = '\u062A\u062D';
- t['\uFCA3'] = '\u062A\u062E';
- t['\uFCA4'] = '\u062A\u0645';
- t['\uFCA5'] = '\u062A\u0647';
- t['\uFCA6'] = '\u062B\u0645';
- t['\uFCA7'] = '\u062C\u062D';
- t['\uFCA8'] = '\u062C\u0645';
- t['\uFCA9'] = '\u062D\u062C';
- t['\uFCAA'] = '\u062D\u0645';
- t['\uFCAB'] = '\u062E\u062C';
- t['\uFCAC'] = '\u062E\u0645';
- t['\uFCAD'] = '\u0633\u062C';
- t['\uFCAE'] = '\u0633\u062D';
- t['\uFCAF'] = '\u0633\u062E';
- t['\uFCB0'] = '\u0633\u0645';
- t['\uFCB1'] = '\u0635\u062D';
- t['\uFCB2'] = '\u0635\u062E';
- t['\uFCB3'] = '\u0635\u0645';
- t['\uFCB4'] = '\u0636\u062C';
- t['\uFCB5'] = '\u0636\u062D';
- t['\uFCB6'] = '\u0636\u062E';
- t['\uFCB7'] = '\u0636\u0645';
- t['\uFCB8'] = '\u0637\u062D';
- t['\uFCB9'] = '\u0638\u0645';
- t['\uFCBA'] = '\u0639\u062C';
- t['\uFCBB'] = '\u0639\u0645';
- t['\uFCBC'] = '\u063A\u062C';
- t['\uFCBD'] = '\u063A\u0645';
- t['\uFCBE'] = '\u0641\u062C';
- t['\uFCBF'] = '\u0641\u062D';
- t['\uFCC0'] = '\u0641\u062E';
- t['\uFCC1'] = '\u0641\u0645';
- t['\uFCC2'] = '\u0642\u062D';
- t['\uFCC3'] = '\u0642\u0645';
- t['\uFCC4'] = '\u0643\u062C';
- t['\uFCC5'] = '\u0643\u062D';
- t['\uFCC6'] = '\u0643\u062E';
- t['\uFCC7'] = '\u0643\u0644';
- t['\uFCC8'] = '\u0643\u0645';
- t['\uFCC9'] = '\u0644\u062C';
- t['\uFCCA'] = '\u0644\u062D';
- t['\uFCCB'] = '\u0644\u062E';
- t['\uFCCC'] = '\u0644\u0645';
- t['\uFCCD'] = '\u0644\u0647';
- t['\uFCCE'] = '\u0645\u062C';
- t['\uFCCF'] = '\u0645\u062D';
- t['\uFCD0'] = '\u0645\u062E';
- t['\uFCD1'] = '\u0645\u0645';
- t['\uFCD2'] = '\u0646\u062C';
- t['\uFCD3'] = '\u0646\u062D';
- t['\uFCD4'] = '\u0646\u062E';
- t['\uFCD5'] = '\u0646\u0645';
- t['\uFCD6'] = '\u0646\u0647';
- t['\uFCD7'] = '\u0647\u062C';
- t['\uFCD8'] = '\u0647\u0645';
- t['\uFCD9'] = '\u0647\u0670';
- t['\uFCDA'] = '\u064A\u062C';
- t['\uFCDB'] = '\u064A\u062D';
- t['\uFCDC'] = '\u064A\u062E';
- t['\uFCDD'] = '\u064A\u0645';
- t['\uFCDE'] = '\u064A\u0647';
- t['\uFCDF'] = '\u0626\u0645';
- t['\uFCE0'] = '\u0626\u0647';
- t['\uFCE1'] = '\u0628\u0645';
- t['\uFCE2'] = '\u0628\u0647';
- t['\uFCE3'] = '\u062A\u0645';
- t['\uFCE4'] = '\u062A\u0647';
- t['\uFCE5'] = '\u062B\u0645';
- t['\uFCE6'] = '\u062B\u0647';
- t['\uFCE7'] = '\u0633\u0645';
- t['\uFCE8'] = '\u0633\u0647';
- t['\uFCE9'] = '\u0634\u0645';
- t['\uFCEA'] = '\u0634\u0647';
- t['\uFCEB'] = '\u0643\u0644';
- t['\uFCEC'] = '\u0643\u0645';
- t['\uFCED'] = '\u0644\u0645';
- t['\uFCEE'] = '\u0646\u0645';
- t['\uFCEF'] = '\u0646\u0647';
- t['\uFCF0'] = '\u064A\u0645';
- t['\uFCF1'] = '\u064A\u0647';
- t['\uFCF2'] = '\u0640\u064E\u0651';
- t['\uFCF3'] = '\u0640\u064F\u0651';
- t['\uFCF4'] = '\u0640\u0650\u0651';
- t['\uFCF5'] = '\u0637\u0649';
- t['\uFCF6'] = '\u0637\u064A';
- t['\uFCF7'] = '\u0639\u0649';
- t['\uFCF8'] = '\u0639\u064A';
- t['\uFCF9'] = '\u063A\u0649';
- t['\uFCFA'] = '\u063A\u064A';
- t['\uFCFB'] = '\u0633\u0649';
- t['\uFCFC'] = '\u0633\u064A';
- t['\uFCFD'] = '\u0634\u0649';
- t['\uFCFE'] = '\u0634\u064A';
- t['\uFCFF'] = '\u062D\u0649';
- t['\uFD00'] = '\u062D\u064A';
- t['\uFD01'] = '\u062C\u0649';
- t['\uFD02'] = '\u062C\u064A';
- t['\uFD03'] = '\u062E\u0649';
- t['\uFD04'] = '\u062E\u064A';
- t['\uFD05'] = '\u0635\u0649';
- t['\uFD06'] = '\u0635\u064A';
- t['\uFD07'] = '\u0636\u0649';
- t['\uFD08'] = '\u0636\u064A';
- t['\uFD09'] = '\u0634\u062C';
- t['\uFD0A'] = '\u0634\u062D';
- t['\uFD0B'] = '\u0634\u062E';
- t['\uFD0C'] = '\u0634\u0645';
- t['\uFD0D'] = '\u0634\u0631';
- t['\uFD0E'] = '\u0633\u0631';
- t['\uFD0F'] = '\u0635\u0631';
- t['\uFD10'] = '\u0636\u0631';
- t['\uFD11'] = '\u0637\u0649';
- t['\uFD12'] = '\u0637\u064A';
- t['\uFD13'] = '\u0639\u0649';
- t['\uFD14'] = '\u0639\u064A';
- t['\uFD15'] = '\u063A\u0649';
- t['\uFD16'] = '\u063A\u064A';
- t['\uFD17'] = '\u0633\u0649';
- t['\uFD18'] = '\u0633\u064A';
- t['\uFD19'] = '\u0634\u0649';
- t['\uFD1A'] = '\u0634\u064A';
- t['\uFD1B'] = '\u062D\u0649';
- t['\uFD1C'] = '\u062D\u064A';
- t['\uFD1D'] = '\u062C\u0649';
- t['\uFD1E'] = '\u062C\u064A';
- t['\uFD1F'] = '\u062E\u0649';
- t['\uFD20'] = '\u062E\u064A';
- t['\uFD21'] = '\u0635\u0649';
- t['\uFD22'] = '\u0635\u064A';
- t['\uFD23'] = '\u0636\u0649';
- t['\uFD24'] = '\u0636\u064A';
- t['\uFD25'] = '\u0634\u062C';
- t['\uFD26'] = '\u0634\u062D';
- t['\uFD27'] = '\u0634\u062E';
- t['\uFD28'] = '\u0634\u0645';
- t['\uFD29'] = '\u0634\u0631';
- t['\uFD2A'] = '\u0633\u0631';
- t['\uFD2B'] = '\u0635\u0631';
- t['\uFD2C'] = '\u0636\u0631';
- t['\uFD2D'] = '\u0634\u062C';
- t['\uFD2E'] = '\u0634\u062D';
- t['\uFD2F'] = '\u0634\u062E';
- t['\uFD30'] = '\u0634\u0645';
- t['\uFD31'] = '\u0633\u0647';
- t['\uFD32'] = '\u0634\u0647';
- t['\uFD33'] = '\u0637\u0645';
- t['\uFD34'] = '\u0633\u062C';
- t['\uFD35'] = '\u0633\u062D';
- t['\uFD36'] = '\u0633\u062E';
- t['\uFD37'] = '\u0634\u062C';
- t['\uFD38'] = '\u0634\u062D';
- t['\uFD39'] = '\u0634\u062E';
- t['\uFD3A'] = '\u0637\u0645';
- t['\uFD3B'] = '\u0638\u0645';
- t['\uFD3C'] = '\u0627\u064B';
- t['\uFD3D'] = '\u0627\u064B';
- t['\uFD50'] = '\u062A\u062C\u0645';
- t['\uFD51'] = '\u062A\u062D\u062C';
- t['\uFD52'] = '\u062A\u062D\u062C';
- t['\uFD53'] = '\u062A\u062D\u0645';
- t['\uFD54'] = '\u062A\u062E\u0645';
- t['\uFD55'] = '\u062A\u0645\u062C';
- t['\uFD56'] = '\u062A\u0645\u062D';
- t['\uFD57'] = '\u062A\u0645\u062E';
- t['\uFD58'] = '\u062C\u0645\u062D';
- t['\uFD59'] = '\u062C\u0645\u062D';
- t['\uFD5A'] = '\u062D\u0645\u064A';
- t['\uFD5B'] = '\u062D\u0645\u0649';
- t['\uFD5C'] = '\u0633\u062D\u062C';
- t['\uFD5D'] = '\u0633\u062C\u062D';
- t['\uFD5E'] = '\u0633\u062C\u0649';
- t['\uFD5F'] = '\u0633\u0645\u062D';
- t['\uFD60'] = '\u0633\u0645\u062D';
- t['\uFD61'] = '\u0633\u0645\u062C';
- t['\uFD62'] = '\u0633\u0645\u0645';
- t['\uFD63'] = '\u0633\u0645\u0645';
- t['\uFD64'] = '\u0635\u062D\u062D';
- t['\uFD65'] = '\u0635\u062D\u062D';
- t['\uFD66'] = '\u0635\u0645\u0645';
- t['\uFD67'] = '\u0634\u062D\u0645';
- t['\uFD68'] = '\u0634\u062D\u0645';
- t['\uFD69'] = '\u0634\u062C\u064A';
- t['\uFD6A'] = '\u0634\u0645\u062E';
- t['\uFD6B'] = '\u0634\u0645\u062E';
- t['\uFD6C'] = '\u0634\u0645\u0645';
- t['\uFD6D'] = '\u0634\u0645\u0645';
- t['\uFD6E'] = '\u0636\u062D\u0649';
- t['\uFD6F'] = '\u0636\u062E\u0645';
- t['\uFD70'] = '\u0636\u062E\u0645';
- t['\uFD71'] = '\u0637\u0645\u062D';
- t['\uFD72'] = '\u0637\u0645\u062D';
- t['\uFD73'] = '\u0637\u0645\u0645';
- t['\uFD74'] = '\u0637\u0645\u064A';
- t['\uFD75'] = '\u0639\u062C\u0645';
- t['\uFD76'] = '\u0639\u0645\u0645';
- t['\uFD77'] = '\u0639\u0645\u0645';
- t['\uFD78'] = '\u0639\u0645\u0649';
- t['\uFD79'] = '\u063A\u0645\u0645';
- t['\uFD7A'] = '\u063A\u0645\u064A';
- t['\uFD7B'] = '\u063A\u0645\u0649';
- t['\uFD7C'] = '\u0641\u062E\u0645';
- t['\uFD7D'] = '\u0641\u062E\u0645';
- t['\uFD7E'] = '\u0642\u0645\u062D';
- t['\uFD7F'] = '\u0642\u0645\u0645';
- t['\uFD80'] = '\u0644\u062D\u0645';
- t['\uFD81'] = '\u0644\u062D\u064A';
- t['\uFD82'] = '\u0644\u062D\u0649';
- t['\uFD83'] = '\u0644\u062C\u062C';
- t['\uFD84'] = '\u0644\u062C\u062C';
- t['\uFD85'] = '\u0644\u062E\u0645';
- t['\uFD86'] = '\u0644\u062E\u0645';
- t['\uFD87'] = '\u0644\u0645\u062D';
- t['\uFD88'] = '\u0644\u0645\u062D';
- t['\uFD89'] = '\u0645\u062D\u062C';
- t['\uFD8A'] = '\u0645\u062D\u0645';
- t['\uFD8B'] = '\u0645\u062D\u064A';
- t['\uFD8C'] = '\u0645\u062C\u062D';
- t['\uFD8D'] = '\u0645\u062C\u0645';
- t['\uFD8E'] = '\u0645\u062E\u062C';
- t['\uFD8F'] = '\u0645\u062E\u0645';
- t['\uFD92'] = '\u0645\u062C\u062E';
- t['\uFD93'] = '\u0647\u0645\u062C';
- t['\uFD94'] = '\u0647\u0645\u0645';
- t['\uFD95'] = '\u0646\u062D\u0645';
- t['\uFD96'] = '\u0646\u062D\u0649';
- t['\uFD97'] = '\u0646\u062C\u0645';
- t['\uFD98'] = '\u0646\u062C\u0645';
- t['\uFD99'] = '\u0646\u062C\u0649';
- t['\uFD9A'] = '\u0646\u0645\u064A';
- t['\uFD9B'] = '\u0646\u0645\u0649';
- t['\uFD9C'] = '\u064A\u0645\u0645';
- t['\uFD9D'] = '\u064A\u0645\u0645';
- t['\uFD9E'] = '\u0628\u062E\u064A';
- t['\uFD9F'] = '\u062A\u062C\u064A';
- t['\uFDA0'] = '\u062A\u062C\u0649';
- t['\uFDA1'] = '\u062A\u062E\u064A';
- t['\uFDA2'] = '\u062A\u062E\u0649';
- t['\uFDA3'] = '\u062A\u0645\u064A';
- t['\uFDA4'] = '\u062A\u0645\u0649';
- t['\uFDA5'] = '\u062C\u0645\u064A';
- t['\uFDA6'] = '\u062C\u062D\u0649';
- t['\uFDA7'] = '\u062C\u0645\u0649';
- t['\uFDA8'] = '\u0633\u062E\u0649';
- t['\uFDA9'] = '\u0635\u062D\u064A';
- t['\uFDAA'] = '\u0634\u062D\u064A';
- t['\uFDAB'] = '\u0636\u062D\u064A';
- t['\uFDAC'] = '\u0644\u062C\u064A';
- t['\uFDAD'] = '\u0644\u0645\u064A';
- t['\uFDAE'] = '\u064A\u062D\u064A';
- t['\uFDAF'] = '\u064A\u062C\u064A';
- t['\uFDB0'] = '\u064A\u0645\u064A';
- t['\uFDB1'] = '\u0645\u0645\u064A';
- t['\uFDB2'] = '\u0642\u0645\u064A';
- t['\uFDB3'] = '\u0646\u062D\u064A';
- t['\uFDB4'] = '\u0642\u0645\u062D';
- t['\uFDB5'] = '\u0644\u062D\u0645';
- t['\uFDB6'] = '\u0639\u0645\u064A';
- t['\uFDB7'] = '\u0643\u0645\u064A';
- t['\uFDB8'] = '\u0646\u062C\u062D';
- t['\uFDB9'] = '\u0645\u062E\u064A';
- t['\uFDBA'] = '\u0644\u062C\u0645';
- t['\uFDBB'] = '\u0643\u0645\u0645';
- t['\uFDBC'] = '\u0644\u062C\u0645';
- t['\uFDBD'] = '\u0646\u062C\u062D';
- t['\uFDBE'] = '\u062C\u062D\u064A';
- t['\uFDBF'] = '\u062D\u062C\u064A';
- t['\uFDC0'] = '\u0645\u062C\u064A';
- t['\uFDC1'] = '\u0641\u0645\u064A';
- t['\uFDC2'] = '\u0628\u062D\u064A';
- t['\uFDC3'] = '\u0643\u0645\u0645';
- t['\uFDC4'] = '\u0639\u062C\u0645';
- t['\uFDC5'] = '\u0635\u0645\u0645';
- t['\uFDC6'] = '\u0633\u062E\u064A';
- t['\uFDC7'] = '\u0646\u062C\u064A';
- t['\uFE49'] = '\u203E';
- t['\uFE4A'] = '\u203E';
- t['\uFE4B'] = '\u203E';
- t['\uFE4C'] = '\u203E';
- t['\uFE4D'] = '\u005F';
- t['\uFE4E'] = '\u005F';
- t['\uFE4F'] = '\u005F';
- t['\uFE80'] = '\u0621';
- t['\uFE81'] = '\u0622';
- t['\uFE82'] = '\u0622';
- t['\uFE83'] = '\u0623';
- t['\uFE84'] = '\u0623';
- t['\uFE85'] = '\u0624';
- t['\uFE86'] = '\u0624';
- t['\uFE87'] = '\u0625';
- t['\uFE88'] = '\u0625';
- t['\uFE89'] = '\u0626';
- t['\uFE8A'] = '\u0626';
- t['\uFE8B'] = '\u0626';
- t['\uFE8C'] = '\u0626';
- t['\uFE8D'] = '\u0627';
- t['\uFE8E'] = '\u0627';
- t['\uFE8F'] = '\u0628';
- t['\uFE90'] = '\u0628';
- t['\uFE91'] = '\u0628';
- t['\uFE92'] = '\u0628';
- t['\uFE93'] = '\u0629';
- t['\uFE94'] = '\u0629';
- t['\uFE95'] = '\u062A';
- t['\uFE96'] = '\u062A';
- t['\uFE97'] = '\u062A';
- t['\uFE98'] = '\u062A';
- t['\uFE99'] = '\u062B';
- t['\uFE9A'] = '\u062B';
- t['\uFE9B'] = '\u062B';
- t['\uFE9C'] = '\u062B';
- t['\uFE9D'] = '\u062C';
- t['\uFE9E'] = '\u062C';
- t['\uFE9F'] = '\u062C';
- t['\uFEA0'] = '\u062C';
- t['\uFEA1'] = '\u062D';
- t['\uFEA2'] = '\u062D';
- t['\uFEA3'] = '\u062D';
- t['\uFEA4'] = '\u062D';
- t['\uFEA5'] = '\u062E';
- t['\uFEA6'] = '\u062E';
- t['\uFEA7'] = '\u062E';
- t['\uFEA8'] = '\u062E';
- t['\uFEA9'] = '\u062F';
- t['\uFEAA'] = '\u062F';
- t['\uFEAB'] = '\u0630';
- t['\uFEAC'] = '\u0630';
- t['\uFEAD'] = '\u0631';
- t['\uFEAE'] = '\u0631';
- t['\uFEAF'] = '\u0632';
- t['\uFEB0'] = '\u0632';
- t['\uFEB1'] = '\u0633';
- t['\uFEB2'] = '\u0633';
- t['\uFEB3'] = '\u0633';
- t['\uFEB4'] = '\u0633';
- t['\uFEB5'] = '\u0634';
- t['\uFEB6'] = '\u0634';
- t['\uFEB7'] = '\u0634';
- t['\uFEB8'] = '\u0634';
- t['\uFEB9'] = '\u0635';
- t['\uFEBA'] = '\u0635';
- t['\uFEBB'] = '\u0635';
- t['\uFEBC'] = '\u0635';
- t['\uFEBD'] = '\u0636';
- t['\uFEBE'] = '\u0636';
- t['\uFEBF'] = '\u0636';
- t['\uFEC0'] = '\u0636';
- t['\uFEC1'] = '\u0637';
- t['\uFEC2'] = '\u0637';
- t['\uFEC3'] = '\u0637';
- t['\uFEC4'] = '\u0637';
- t['\uFEC5'] = '\u0638';
- t['\uFEC6'] = '\u0638';
- t['\uFEC7'] = '\u0638';
- t['\uFEC8'] = '\u0638';
- t['\uFEC9'] = '\u0639';
- t['\uFECA'] = '\u0639';
- t['\uFECB'] = '\u0639';
- t['\uFECC'] = '\u0639';
- t['\uFECD'] = '\u063A';
- t['\uFECE'] = '\u063A';
- t['\uFECF'] = '\u063A';
- t['\uFED0'] = '\u063A';
- t['\uFED1'] = '\u0641';
- t['\uFED2'] = '\u0641';
- t['\uFED3'] = '\u0641';
- t['\uFED4'] = '\u0641';
- t['\uFED5'] = '\u0642';
- t['\uFED6'] = '\u0642';
- t['\uFED7'] = '\u0642';
- t['\uFED8'] = '\u0642';
- t['\uFED9'] = '\u0643';
- t['\uFEDA'] = '\u0643';
- t['\uFEDB'] = '\u0643';
- t['\uFEDC'] = '\u0643';
- t['\uFEDD'] = '\u0644';
- t['\uFEDE'] = '\u0644';
- t['\uFEDF'] = '\u0644';
- t['\uFEE0'] = '\u0644';
- t['\uFEE1'] = '\u0645';
- t['\uFEE2'] = '\u0645';
- t['\uFEE3'] = '\u0645';
- t['\uFEE4'] = '\u0645';
- t['\uFEE5'] = '\u0646';
- t['\uFEE6'] = '\u0646';
- t['\uFEE7'] = '\u0646';
- t['\uFEE8'] = '\u0646';
- t['\uFEE9'] = '\u0647';
- t['\uFEEA'] = '\u0647';
- t['\uFEEB'] = '\u0647';
- t['\uFEEC'] = '\u0647';
- t['\uFEED'] = '\u0648';
- t['\uFEEE'] = '\u0648';
- t['\uFEEF'] = '\u0649';
- t['\uFEF0'] = '\u0649';
- t['\uFEF1'] = '\u064A';
- t['\uFEF2'] = '\u064A';
- t['\uFEF3'] = '\u064A';
- t['\uFEF4'] = '\u064A';
- t['\uFEF5'] = '\u0644\u0622';
- t['\uFEF6'] = '\u0644\u0622';
- t['\uFEF7'] = '\u0644\u0623';
- t['\uFEF8'] = '\u0644\u0623';
- t['\uFEF9'] = '\u0644\u0625';
- t['\uFEFA'] = '\u0644\u0625';
- t['\uFEFB'] = '\u0644\u0627';
- t['\uFEFC'] = '\u0644\u0627';
- });
- function reverseIfRtl(chars) {
- var charsLength = chars.length;
- //reverse an arabic ligature
- if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) {
- return chars;
- }
- var s = '';
- for (var ii = charsLength - 1; ii >= 0; ii--) {
- s += chars[ii];
- }
- return s;
- }
- exports.mapSpecialUnicodeValues = mapSpecialUnicodeValues;
- exports.reverseIfRtl = reverseIfRtl;
- exports.getUnicodeRangeFor = getUnicodeRangeFor;
- exports.getNormalizedUnicodes = getNormalizedUnicodes;
- exports.getUnicodeForGlyph = getUnicodeForGlyph;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreStream = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreJbig2, root.pdfjsCoreJpg, root.pdfjsCoreJpx);
- }(this, function (exports, sharedUtil, corePrimitives, coreJbig2, coreJpg, coreJpx) {
- var Util = sharedUtil.Util;
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var isInt = sharedUtil.isInt;
- var isArray = sharedUtil.isArray;
- var createObjectURL = sharedUtil.createObjectURL;
- var shadow = sharedUtil.shadow;
- var warn = sharedUtil.warn;
- var isSpace = sharedUtil.isSpace;
- var Dict = corePrimitives.Dict;
- var isDict = corePrimitives.isDict;
- var isStream = corePrimitives.isStream;
- var Jbig2Image = coreJbig2.Jbig2Image;
- var JpegImage = coreJpg.JpegImage;
- var JpxImage = coreJpx.JpxImage;
- var Stream = function StreamClosure() {
- function Stream(arrayBuffer, start, length, dict) {
- this.bytes = arrayBuffer instanceof Uint8Array ? arrayBuffer : new Uint8Array(arrayBuffer);
- this.start = start || 0;
- this.pos = this.start;
- this.end = start + length || this.bytes.length;
- this.dict = dict;
- }
- // required methods for a stream. if a particular stream does not
- // implement these, an error should be thrown
- Stream.prototype = {
- get length() {
- return this.end - this.start;
- },
- get isEmpty() {
- return this.length === 0;
- },
- getByte: function Stream_getByte() {
- if (this.pos >= this.end) {
- return -1;
- }
- return this.bytes[this.pos++];
- },
- getUint16: function Stream_getUint16() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- if (b0 === -1 || b1 === -1) {
- return -1;
- }
- return (b0 << 8) + b1;
- },
- getInt32: function Stream_getInt32() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- var b2 = this.getByte();
- var b3 = this.getByte();
- return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
- },
- // returns subarray of original buffer
- // should only be read
- getBytes: function Stream_getBytes(length) {
- var bytes = this.bytes;
- var pos = this.pos;
- var strEnd = this.end;
- if (!length) {
- return bytes.subarray(pos, strEnd);
- }
- var end = pos + length;
- if (end > strEnd) {
- end = strEnd;
- }
- this.pos = end;
- return bytes.subarray(pos, end);
- },
- peekByte: function Stream_peekByte() {
- var peekedByte = this.getByte();
- this.pos--;
- return peekedByte;
- },
- peekBytes: function Stream_peekBytes(length) {
- var bytes = this.getBytes(length);
- this.pos -= bytes.length;
- return bytes;
- },
- skip: function Stream_skip(n) {
- if (!n) {
- n = 1;
- }
- this.pos += n;
- },
- reset: function Stream_reset() {
- this.pos = this.start;
- },
- moveStart: function Stream_moveStart() {
- this.start = this.pos;
- },
- makeSubStream: function Stream_makeSubStream(start, length, dict) {
- return new Stream(this.bytes.buffer, start, length, dict);
- },
- isStream: true
- };
- return Stream;
- }();
- var StringStream = function StringStreamClosure() {
- function StringStream(str) {
- var length = str.length;
- var bytes = new Uint8Array(length);
- for (var n = 0; n < length; ++n) {
- bytes[n] = str.charCodeAt(n);
- }
- Stream.call(this, bytes);
- }
- StringStream.prototype = Stream.prototype;
- return StringStream;
- }();
- // super class for the decoding streams
- var DecodeStream = function DecodeStreamClosure() {
- // Lots of DecodeStreams are created whose buffers are never used. For these
- // we share a single empty buffer. This is (a) space-efficient and (b) avoids
- // having special cases that would be required if we used |null| for an empty
- // buffer.
- var emptyBuffer = new Uint8Array(0);
- function DecodeStream(maybeMinBufferLength) {
- this.pos = 0;
- this.bufferLength = 0;
- this.eof = false;
- this.buffer = emptyBuffer;
- this.minBufferLength = 512;
- if (maybeMinBufferLength) {
- // Compute the first power of two that is as big as maybeMinBufferLength.
- while (this.minBufferLength < maybeMinBufferLength) {
- this.minBufferLength *= 2;
- }
- }
- }
- DecodeStream.prototype = {
- get isEmpty() {
- while (!this.eof && this.bufferLength === 0) {
- this.readBlock();
- }
- return this.bufferLength === 0;
- },
- ensureBuffer: function DecodeStream_ensureBuffer(requested) {
- var buffer = this.buffer;
- if (requested <= buffer.byteLength) {
- return buffer;
- }
- var size = this.minBufferLength;
- while (size < requested) {
- size *= 2;
- }
- var buffer2 = new Uint8Array(size);
- buffer2.set(buffer);
- return this.buffer = buffer2;
- },
- getByte: function DecodeStream_getByte() {
- var pos = this.pos;
- while (this.bufferLength <= pos) {
- if (this.eof) {
- return -1;
- }
- this.readBlock();
- }
- return this.buffer[this.pos++];
- },
- getUint16: function DecodeStream_getUint16() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- if (b0 === -1 || b1 === -1) {
- return -1;
- }
- return (b0 << 8) + b1;
- },
- getInt32: function DecodeStream_getInt32() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- var b2 = this.getByte();
- var b3 = this.getByte();
- return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
- },
- getBytes: function DecodeStream_getBytes(length) {
- var end, pos = this.pos;
- if (length) {
- this.ensureBuffer(pos + length);
- end = pos + length;
- while (!this.eof && this.bufferLength < end) {
- this.readBlock();
- }
- var bufEnd = this.bufferLength;
- if (end > bufEnd) {
- end = bufEnd;
- }
- } else {
- while (!this.eof) {
- this.readBlock();
- }
- end = this.bufferLength;
- }
- this.pos = end;
- return this.buffer.subarray(pos, end);
- },
- peekByte: function DecodeStream_peekByte() {
- var peekedByte = this.getByte();
- this.pos--;
- return peekedByte;
- },
- peekBytes: function DecodeStream_peekBytes(length) {
- var bytes = this.getBytes(length);
- this.pos -= bytes.length;
- return bytes;
- },
- makeSubStream: function DecodeStream_makeSubStream(start, length, dict) {
- var end = start + length;
- while (this.bufferLength <= end && !this.eof) {
- this.readBlock();
- }
- return new Stream(this.buffer, start, length, dict);
- },
- skip: function DecodeStream_skip(n) {
- if (!n) {
- n = 1;
- }
- this.pos += n;
- },
- reset: function DecodeStream_reset() {
- this.pos = 0;
- },
- getBaseStreams: function DecodeStream_getBaseStreams() {
- if (this.str && this.str.getBaseStreams) {
- return this.str.getBaseStreams();
- }
- return [];
- }
- };
- return DecodeStream;
- }();
- var StreamsSequenceStream = function StreamsSequenceStreamClosure() {
- function StreamsSequenceStream(streams) {
- this.streams = streams;
- DecodeStream.call(this, /* maybeLength = */
- null);
- }
- StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
- StreamsSequenceStream.prototype.readBlock = function streamSequenceStreamReadBlock() {
- var streams = this.streams;
- if (streams.length === 0) {
- this.eof = true;
- return;
- }
- var stream = streams.shift();
- var chunk = stream.getBytes();
- var bufferLength = this.bufferLength;
- var newLength = bufferLength + chunk.length;
- var buffer = this.ensureBuffer(newLength);
- buffer.set(chunk, bufferLength);
- this.bufferLength = newLength;
- };
- StreamsSequenceStream.prototype.getBaseStreams = function StreamsSequenceStream_getBaseStreams() {
- var baseStreams = [];
- for (var i = 0, ii = this.streams.length; i < ii; i++) {
- var stream = this.streams[i];
- if (stream.getBaseStreams) {
- Util.appendToArray(baseStreams, stream.getBaseStreams());
- }
- }
- return baseStreams;
- };
- return StreamsSequenceStream;
- }();
- var FlateStream = function FlateStreamClosure() {
- var codeLenCodeMap = new Int32Array([
- 16,
- 17,
- 18,
- 0,
- 8,
- 7,
- 9,
- 6,
- 10,
- 5,
- 11,
- 4,
- 12,
- 3,
- 13,
- 2,
- 14,
- 1,
- 15
- ]);
- var lengthDecode = new Int32Array([
- 0x00003,
- 0x00004,
- 0x00005,
- 0x00006,
- 0x00007,
- 0x00008,
- 0x00009,
- 0x0000a,
- 0x1000b,
- 0x1000d,
- 0x1000f,
- 0x10011,
- 0x20013,
- 0x20017,
- 0x2001b,
- 0x2001f,
- 0x30023,
- 0x3002b,
- 0x30033,
- 0x3003b,
- 0x40043,
- 0x40053,
- 0x40063,
- 0x40073,
- 0x50083,
- 0x500a3,
- 0x500c3,
- 0x500e3,
- 0x00102,
- 0x00102,
- 0x00102
- ]);
- var distDecode = new Int32Array([
- 0x00001,
- 0x00002,
- 0x00003,
- 0x00004,
- 0x10005,
- 0x10007,
- 0x20009,
- 0x2000d,
- 0x30011,
- 0x30019,
- 0x40021,
- 0x40031,
- 0x50041,
- 0x50061,
- 0x60081,
- 0x600c1,
- 0x70101,
- 0x70181,
- 0x80201,
- 0x80301,
- 0x90401,
- 0x90601,
- 0xa0801,
- 0xa0c01,
- 0xb1001,
- 0xb1801,
- 0xc2001,
- 0xc3001,
- 0xd4001,
- 0xd6001
- ]);
- var fixedLitCodeTab = [
- new Int32Array([
- 0x70100,
- 0x80050,
- 0x80010,
- 0x80118,
- 0x70110,
- 0x80070,
- 0x80030,
- 0x900c0,
- 0x70108,
- 0x80060,
- 0x80020,
- 0x900a0,
- 0x80000,
- 0x80080,
- 0x80040,
- 0x900e0,
- 0x70104,
- 0x80058,
- 0x80018,
- 0x90090,
- 0x70114,
- 0x80078,
- 0x80038,
- 0x900d0,
- 0x7010c,
- 0x80068,
- 0x80028,
- 0x900b0,
- 0x80008,
- 0x80088,
- 0x80048,
- 0x900f0,
- 0x70102,
- 0x80054,
- 0x80014,
- 0x8011c,
- 0x70112,
- 0x80074,
- 0x80034,
- 0x900c8,
- 0x7010a,
- 0x80064,
- 0x80024,
- 0x900a8,
- 0x80004,
- 0x80084,
- 0x80044,
- 0x900e8,
- 0x70106,
- 0x8005c,
- 0x8001c,
- 0x90098,
- 0x70116,
- 0x8007c,
- 0x8003c,
- 0x900d8,
- 0x7010e,
- 0x8006c,
- 0x8002c,
- 0x900b8,
- 0x8000c,
- 0x8008c,
- 0x8004c,
- 0x900f8,
- 0x70101,
- 0x80052,
- 0x80012,
- 0x8011a,
- 0x70111,
- 0x80072,
- 0x80032,
- 0x900c4,
- 0x70109,
- 0x80062,
- 0x80022,
- 0x900a4,
- 0x80002,
- 0x80082,
- 0x80042,
- 0x900e4,
- 0x70105,
- 0x8005a,
- 0x8001a,
- 0x90094,
- 0x70115,
- 0x8007a,
- 0x8003a,
- 0x900d4,
- 0x7010d,
- 0x8006a,
- 0x8002a,
- 0x900b4,
- 0x8000a,
- 0x8008a,
- 0x8004a,
- 0x900f4,
- 0x70103,
- 0x80056,
- 0x80016,
- 0x8011e,
- 0x70113,
- 0x80076,
- 0x80036,
- 0x900cc,
- 0x7010b,
- 0x80066,
- 0x80026,
- 0x900ac,
- 0x80006,
- 0x80086,
- 0x80046,
- 0x900ec,
- 0x70107,
- 0x8005e,
- 0x8001e,
- 0x9009c,
- 0x70117,
- 0x8007e,
- 0x8003e,
- 0x900dc,
- 0x7010f,
- 0x8006e,
- 0x8002e,
- 0x900bc,
- 0x8000e,
- 0x8008e,
- 0x8004e,
- 0x900fc,
- 0x70100,
- 0x80051,
- 0x80011,
- 0x80119,
- 0x70110,
- 0x80071,
- 0x80031,
- 0x900c2,
- 0x70108,
- 0x80061,
- 0x80021,
- 0x900a2,
- 0x80001,
- 0x80081,
- 0x80041,
- 0x900e2,
- 0x70104,
- 0x80059,
- 0x80019,
- 0x90092,
- 0x70114,
- 0x80079,
- 0x80039,
- 0x900d2,
- 0x7010c,
- 0x80069,
- 0x80029,
- 0x900b2,
- 0x80009,
- 0x80089,
- 0x80049,
- 0x900f2,
- 0x70102,
- 0x80055,
- 0x80015,
- 0x8011d,
- 0x70112,
- 0x80075,
- 0x80035,
- 0x900ca,
- 0x7010a,
- 0x80065,
- 0x80025,
- 0x900aa,
- 0x80005,
- 0x80085,
- 0x80045,
- 0x900ea,
- 0x70106,
- 0x8005d,
- 0x8001d,
- 0x9009a,
- 0x70116,
- 0x8007d,
- 0x8003d,
- 0x900da,
- 0x7010e,
- 0x8006d,
- 0x8002d,
- 0x900ba,
- 0x8000d,
- 0x8008d,
- 0x8004d,
- 0x900fa,
- 0x70101,
- 0x80053,
- 0x80013,
- 0x8011b,
- 0x70111,
- 0x80073,
- 0x80033,
- 0x900c6,
- 0x70109,
- 0x80063,
- 0x80023,
- 0x900a6,
- 0x80003,
- 0x80083,
- 0x80043,
- 0x900e6,
- 0x70105,
- 0x8005b,
- 0x8001b,
- 0x90096,
- 0x70115,
- 0x8007b,
- 0x8003b,
- 0x900d6,
- 0x7010d,
- 0x8006b,
- 0x8002b,
- 0x900b6,
- 0x8000b,
- 0x8008b,
- 0x8004b,
- 0x900f6,
- 0x70103,
- 0x80057,
- 0x80017,
- 0x8011f,
- 0x70113,
- 0x80077,
- 0x80037,
- 0x900ce,
- 0x7010b,
- 0x80067,
- 0x80027,
- 0x900ae,
- 0x80007,
- 0x80087,
- 0x80047,
- 0x900ee,
- 0x70107,
- 0x8005f,
- 0x8001f,
- 0x9009e,
- 0x70117,
- 0x8007f,
- 0x8003f,
- 0x900de,
- 0x7010f,
- 0x8006f,
- 0x8002f,
- 0x900be,
- 0x8000f,
- 0x8008f,
- 0x8004f,
- 0x900fe,
- 0x70100,
- 0x80050,
- 0x80010,
- 0x80118,
- 0x70110,
- 0x80070,
- 0x80030,
- 0x900c1,
- 0x70108,
- 0x80060,
- 0x80020,
- 0x900a1,
- 0x80000,
- 0x80080,
- 0x80040,
- 0x900e1,
- 0x70104,
- 0x80058,
- 0x80018,
- 0x90091,
- 0x70114,
- 0x80078,
- 0x80038,
- 0x900d1,
- 0x7010c,
- 0x80068,
- 0x80028,
- 0x900b1,
- 0x80008,
- 0x80088,
- 0x80048,
- 0x900f1,
- 0x70102,
- 0x80054,
- 0x80014,
- 0x8011c,
- 0x70112,
- 0x80074,
- 0x80034,
- 0x900c9,
- 0x7010a,
- 0x80064,
- 0x80024,
- 0x900a9,
- 0x80004,
- 0x80084,
- 0x80044,
- 0x900e9,
- 0x70106,
- 0x8005c,
- 0x8001c,
- 0x90099,
- 0x70116,
- 0x8007c,
- 0x8003c,
- 0x900d9,
- 0x7010e,
- 0x8006c,
- 0x8002c,
- 0x900b9,
- 0x8000c,
- 0x8008c,
- 0x8004c,
- 0x900f9,
- 0x70101,
- 0x80052,
- 0x80012,
- 0x8011a,
- 0x70111,
- 0x80072,
- 0x80032,
- 0x900c5,
- 0x70109,
- 0x80062,
- 0x80022,
- 0x900a5,
- 0x80002,
- 0x80082,
- 0x80042,
- 0x900e5,
- 0x70105,
- 0x8005a,
- 0x8001a,
- 0x90095,
- 0x70115,
- 0x8007a,
- 0x8003a,
- 0x900d5,
- 0x7010d,
- 0x8006a,
- 0x8002a,
- 0x900b5,
- 0x8000a,
- 0x8008a,
- 0x8004a,
- 0x900f5,
- 0x70103,
- 0x80056,
- 0x80016,
- 0x8011e,
- 0x70113,
- 0x80076,
- 0x80036,
- 0x900cd,
- 0x7010b,
- 0x80066,
- 0x80026,
- 0x900ad,
- 0x80006,
- 0x80086,
- 0x80046,
- 0x900ed,
- 0x70107,
- 0x8005e,
- 0x8001e,
- 0x9009d,
- 0x70117,
- 0x8007e,
- 0x8003e,
- 0x900dd,
- 0x7010f,
- 0x8006e,
- 0x8002e,
- 0x900bd,
- 0x8000e,
- 0x8008e,
- 0x8004e,
- 0x900fd,
- 0x70100,
- 0x80051,
- 0x80011,
- 0x80119,
- 0x70110,
- 0x80071,
- 0x80031,
- 0x900c3,
- 0x70108,
- 0x80061,
- 0x80021,
- 0x900a3,
- 0x80001,
- 0x80081,
- 0x80041,
- 0x900e3,
- 0x70104,
- 0x80059,
- 0x80019,
- 0x90093,
- 0x70114,
- 0x80079,
- 0x80039,
- 0x900d3,
- 0x7010c,
- 0x80069,
- 0x80029,
- 0x900b3,
- 0x80009,
- 0x80089,
- 0x80049,
- 0x900f3,
- 0x70102,
- 0x80055,
- 0x80015,
- 0x8011d,
- 0x70112,
- 0x80075,
- 0x80035,
- 0x900cb,
- 0x7010a,
- 0x80065,
- 0x80025,
- 0x900ab,
- 0x80005,
- 0x80085,
- 0x80045,
- 0x900eb,
- 0x70106,
- 0x8005d,
- 0x8001d,
- 0x9009b,
- 0x70116,
- 0x8007d,
- 0x8003d,
- 0x900db,
- 0x7010e,
- 0x8006d,
- 0x8002d,
- 0x900bb,
- 0x8000d,
- 0x8008d,
- 0x8004d,
- 0x900fb,
- 0x70101,
- 0x80053,
- 0x80013,
- 0x8011b,
- 0x70111,
- 0x80073,
- 0x80033,
- 0x900c7,
- 0x70109,
- 0x80063,
- 0x80023,
- 0x900a7,
- 0x80003,
- 0x80083,
- 0x80043,
- 0x900e7,
- 0x70105,
- 0x8005b,
- 0x8001b,
- 0x90097,
- 0x70115,
- 0x8007b,
- 0x8003b,
- 0x900d7,
- 0x7010d,
- 0x8006b,
- 0x8002b,
- 0x900b7,
- 0x8000b,
- 0x8008b,
- 0x8004b,
- 0x900f7,
- 0x70103,
- 0x80057,
- 0x80017,
- 0x8011f,
- 0x70113,
- 0x80077,
- 0x80037,
- 0x900cf,
- 0x7010b,
- 0x80067,
- 0x80027,
- 0x900af,
- 0x80007,
- 0x80087,
- 0x80047,
- 0x900ef,
- 0x70107,
- 0x8005f,
- 0x8001f,
- 0x9009f,
- 0x70117,
- 0x8007f,
- 0x8003f,
- 0x900df,
- 0x7010f,
- 0x8006f,
- 0x8002f,
- 0x900bf,
- 0x8000f,
- 0x8008f,
- 0x8004f,
- 0x900ff
- ]),
- 9
- ];
- var fixedDistCodeTab = [
- new Int32Array([
- 0x50000,
- 0x50010,
- 0x50008,
- 0x50018,
- 0x50004,
- 0x50014,
- 0x5000c,
- 0x5001c,
- 0x50002,
- 0x50012,
- 0x5000a,
- 0x5001a,
- 0x50006,
- 0x50016,
- 0x5000e,
- 0x00000,
- 0x50001,
- 0x50011,
- 0x50009,
- 0x50019,
- 0x50005,
- 0x50015,
- 0x5000d,
- 0x5001d,
- 0x50003,
- 0x50013,
- 0x5000b,
- 0x5001b,
- 0x50007,
- 0x50017,
- 0x5000f,
- 0x00000
- ]),
- 5
- ];
- function FlateStream(str, maybeLength) {
- this.str = str;
- this.dict = str.dict;
- var cmf = str.getByte();
- var flg = str.getByte();
- if (cmf === -1 || flg === -1) {
- error('Invalid header in flate stream: ' + cmf + ', ' + flg);
- }
- if ((cmf & 0x0f) !== 0x08) {
- error('Unknown compression method in flate stream: ' + cmf + ', ' + flg);
- }
- if (((cmf << 8) + flg) % 31 !== 0) {
- error('Bad FCHECK in flate stream: ' + cmf + ', ' + flg);
- }
- if (flg & 0x20) {
- error('FDICT bit set in flate stream: ' + cmf + ', ' + flg);
- }
- this.codeSize = 0;
- this.codeBuf = 0;
- DecodeStream.call(this, maybeLength);
- }
- FlateStream.prototype = Object.create(DecodeStream.prototype);
- FlateStream.prototype.getBits = function FlateStream_getBits(bits) {
- var str = this.str;
- var codeSize = this.codeSize;
- var codeBuf = this.codeBuf;
- var b;
- while (codeSize < bits) {
- if ((b = str.getByte()) === -1) {
- error('Bad encoding in flate stream');
- }
- codeBuf |= b << codeSize;
- codeSize += 8;
- }
- b = codeBuf & (1 << bits) - 1;
- this.codeBuf = codeBuf >> bits;
- this.codeSize = codeSize -= bits;
- return b;
- };
- FlateStream.prototype.getCode = function FlateStream_getCode(table) {
- var str = this.str;
- var codes = table[0];
- var maxLen = table[1];
- var codeSize = this.codeSize;
- var codeBuf = this.codeBuf;
- var b;
- while (codeSize < maxLen) {
- if ((b = str.getByte()) === -1) {
- // premature end of stream. code might however still be valid.
- // codeSize < codeLen check below guards against incomplete codeVal.
- break;
- }
- codeBuf |= b << codeSize;
- codeSize += 8;
- }
- var code = codes[codeBuf & (1 << maxLen) - 1];
- var codeLen = code >> 16;
- var codeVal = code & 0xffff;
- if (codeLen < 1 || codeSize < codeLen) {
- error('Bad encoding in flate stream');
- }
- this.codeBuf = codeBuf >> codeLen;
- this.codeSize = codeSize - codeLen;
- return codeVal;
- };
- FlateStream.prototype.generateHuffmanTable = function flateStreamGenerateHuffmanTable(lengths) {
- var n = lengths.length;
- // find max code length
- var maxLen = 0;
- var i;
- for (i = 0; i < n; ++i) {
- if (lengths[i] > maxLen) {
- maxLen = lengths[i];
- }
- }
- // build the table
- var size = 1 << maxLen;
- var codes = new Int32Array(size);
- for (var len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) {
- for (var val = 0; val < n; ++val) {
- if (lengths[val] === len) {
- // bit-reverse the code
- var code2 = 0;
- var t = code;
- for (i = 0; i < len; ++i) {
- code2 = code2 << 1 | t & 1;
- t >>= 1;
- }
- // fill the table entries
- for (i = code2; i < size; i += skip) {
- codes[i] = len << 16 | val;
- }
- ++code;
- }
- }
- }
- return [
- codes,
- maxLen
- ];
- };
- FlateStream.prototype.readBlock = function FlateStream_readBlock() {
- var buffer, len;
- var str = this.str;
- // read block header
- var hdr = this.getBits(3);
- if (hdr & 1) {
- this.eof = true;
- }
- hdr >>= 1;
- if (hdr === 0) {
- // uncompressed block
- var b;
- if ((b = str.getByte()) === -1) {
- error('Bad block header in flate stream');
- }
- var blockLen = b;
- if ((b = str.getByte()) === -1) {
- error('Bad block header in flate stream');
- }
- blockLen |= b << 8;
- if ((b = str.getByte()) === -1) {
- error('Bad block header in flate stream');
- }
- var check = b;
- if ((b = str.getByte()) === -1) {
- error('Bad block header in flate stream');
- }
- check |= b << 8;
- if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) {
- // Ignoring error for bad "empty" block (see issue 1277)
- error('Bad uncompressed block length in flate stream');
- }
- this.codeBuf = 0;
- this.codeSize = 0;
- var bufferLength = this.bufferLength;
- buffer = this.ensureBuffer(bufferLength + blockLen);
- var end = bufferLength + blockLen;
- this.bufferLength = end;
- if (blockLen === 0) {
- if (str.peekByte() === -1) {
- this.eof = true;
- }
- } else {
- for (var n = bufferLength; n < end; ++n) {
- if ((b = str.getByte()) === -1) {
- this.eof = true;
- break;
- }
- buffer[n] = b;
- }
- }
- return;
- }
- var litCodeTable;
- var distCodeTable;
- if (hdr === 1) {
- // compressed block, fixed codes
- litCodeTable = fixedLitCodeTab;
- distCodeTable = fixedDistCodeTab;
- } else if (hdr === 2) {
- // compressed block, dynamic codes
- var numLitCodes = this.getBits(5) + 257;
- var numDistCodes = this.getBits(5) + 1;
- var numCodeLenCodes = this.getBits(4) + 4;
- // build the code lengths code table
- var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length);
- var i;
- for (i = 0; i < numCodeLenCodes; ++i) {
- codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3);
- }
- var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);
- // build the literal and distance code tables
- len = 0;
- i = 0;
- var codes = numLitCodes + numDistCodes;
- var codeLengths = new Uint8Array(codes);
- var bitsLength, bitsOffset, what;
- while (i < codes) {
- var code = this.getCode(codeLenCodeTab);
- if (code === 16) {
- bitsLength = 2;
- bitsOffset = 3;
- what = len;
- } else if (code === 17) {
- bitsLength = 3;
- bitsOffset = 3;
- what = len = 0;
- } else if (code === 18) {
- bitsLength = 7;
- bitsOffset = 11;
- what = len = 0;
- } else {
- codeLengths[i++] = len = code;
- continue;
- }
- var repeatLength = this.getBits(bitsLength) + bitsOffset;
- while (repeatLength-- > 0) {
- codeLengths[i++] = what;
- }
- }
- litCodeTable = this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes));
- distCodeTable = this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes));
- } else {
- error('Unknown block type in flate stream');
- }
- buffer = this.buffer;
- var limit = buffer ? buffer.length : 0;
- var pos = this.bufferLength;
- while (true) {
- var code1 = this.getCode(litCodeTable);
- if (code1 < 256) {
- if (pos + 1 >= limit) {
- buffer = this.ensureBuffer(pos + 1);
- limit = buffer.length;
- }
- buffer[pos++] = code1;
- continue;
- }
- if (code1 === 256) {
- this.bufferLength = pos;
- return;
- }
- code1 -= 257;
- code1 = lengthDecode[code1];
- var code2 = code1 >> 16;
- if (code2 > 0) {
- code2 = this.getBits(code2);
- }
- len = (code1 & 0xffff) + code2;
- code1 = this.getCode(distCodeTable);
- code1 = distDecode[code1];
- code2 = code1 >> 16;
- if (code2 > 0) {
- code2 = this.getBits(code2);
- }
- var dist = (code1 & 0xffff) + code2;
- if (pos + len >= limit) {
- buffer = this.ensureBuffer(pos + len);
- limit = buffer.length;
- }
- for (var k = 0; k < len; ++k, ++pos) {
- buffer[pos] = buffer[pos - dist];
- }
- }
- };
- return FlateStream;
- }();
- var PredictorStream = function PredictorStreamClosure() {
- function PredictorStream(str, maybeLength, params) {
- if (!isDict(params)) {
- return str;
- }
- // no prediction
- var predictor = this.predictor = params.get('Predictor') || 1;
- if (predictor <= 1) {
- return str;
- }
- // no prediction
- if (predictor !== 2 && (predictor < 10 || predictor > 15)) {
- error('Unsupported predictor: ' + predictor);
- }
- if (predictor === 2) {
- this.readBlock = this.readBlockTiff;
- } else {
- this.readBlock = this.readBlockPng;
- }
- this.str = str;
- this.dict = str.dict;
- var colors = this.colors = params.get('Colors') || 1;
- var bits = this.bits = params.get('BitsPerComponent') || 8;
- var columns = this.columns = params.get('Columns') || 1;
- this.pixBytes = colors * bits + 7 >> 3;
- this.rowBytes = columns * colors * bits + 7 >> 3;
- DecodeStream.call(this, maybeLength);
- return this;
- }
- PredictorStream.prototype = Object.create(DecodeStream.prototype);
- PredictorStream.prototype.readBlockTiff = function predictorStreamReadBlockTiff() {
- var rowBytes = this.rowBytes;
- var bufferLength = this.bufferLength;
- var buffer = this.ensureBuffer(bufferLength + rowBytes);
- var bits = this.bits;
- var colors = this.colors;
- var rawBytes = this.str.getBytes(rowBytes);
- this.eof = !rawBytes.length;
- if (this.eof) {
- return;
- }
- var inbuf = 0, outbuf = 0;
- var inbits = 0, outbits = 0;
- var pos = bufferLength;
- var i;
- if (bits === 1) {
- for (i = 0; i < rowBytes; ++i) {
- var c = rawBytes[i];
- inbuf = inbuf << 8 | c;
- // bitwise addition is exclusive or
- // first shift inbuf and then add
- buffer[pos++] = (c ^ inbuf >> colors) & 0xFF;
- // truncate inbuf (assumes colors < 16)
- inbuf &= 0xFFFF;
- }
- } else if (bits === 8) {
- for (i = 0; i < colors; ++i) {
- buffer[pos++] = rawBytes[i];
- }
- for (; i < rowBytes; ++i) {
- buffer[pos] = buffer[pos - colors] + rawBytes[i];
- pos++;
- }
- } else {
- var compArray = new Uint8Array(colors + 1);
- var bitMask = (1 << bits) - 1;
- var j = 0, k = bufferLength;
- var columns = this.columns;
- for (i = 0; i < columns; ++i) {
- for (var kk = 0; kk < colors; ++kk) {
- if (inbits < bits) {
- inbuf = inbuf << 8 | rawBytes[j++] & 0xFF;
- inbits += 8;
- }
- compArray[kk] = compArray[kk] + (inbuf >> inbits - bits) & bitMask;
- inbits -= bits;
- outbuf = outbuf << bits | compArray[kk];
- outbits += bits;
- if (outbits >= 8) {
- buffer[k++] = outbuf >> outbits - 8 & 0xFF;
- outbits -= 8;
- }
- }
- }
- if (outbits > 0) {
- buffer[k++] = (outbuf << 8 - outbits) + (inbuf & (1 << 8 - outbits) - 1);
- }
- }
- this.bufferLength += rowBytes;
- };
- PredictorStream.prototype.readBlockPng = function predictorStreamReadBlockPng() {
- var rowBytes = this.rowBytes;
- var pixBytes = this.pixBytes;
- var predictor = this.str.getByte();
- var rawBytes = this.str.getBytes(rowBytes);
- this.eof = !rawBytes.length;
- if (this.eof) {
- return;
- }
- var bufferLength = this.bufferLength;
- var buffer = this.ensureBuffer(bufferLength + rowBytes);
- var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
- if (prevRow.length === 0) {
- prevRow = new Uint8Array(rowBytes);
- }
- var i, j = bufferLength, up, c;
- switch (predictor) {
- case 0:
- for (i = 0; i < rowBytes; ++i) {
- buffer[j++] = rawBytes[i];
- }
- break;
- case 1:
- for (i = 0; i < pixBytes; ++i) {
- buffer[j++] = rawBytes[i];
- }
- for (; i < rowBytes; ++i) {
- buffer[j] = buffer[j - pixBytes] + rawBytes[i] & 0xFF;
- j++;
- }
- break;
- case 2:
- for (i = 0; i < rowBytes; ++i) {
- buffer[j++] = prevRow[i] + rawBytes[i] & 0xFF;
- }
- break;
- case 3:
- for (i = 0; i < pixBytes; ++i) {
- buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
- }
- for (; i < rowBytes; ++i) {
- buffer[j] = (prevRow[i] + buffer[j - pixBytes] >> 1) + rawBytes[i] & 0xFF;
- j++;
- }
- break;
- case 4:
- // we need to save the up left pixels values. the simplest way
- // is to create a new buffer
- for (i = 0; i < pixBytes; ++i) {
- up = prevRow[i];
- c = rawBytes[i];
- buffer[j++] = up + c;
- }
- for (; i < rowBytes; ++i) {
- up = prevRow[i];
- var upLeft = prevRow[i - pixBytes];
- var left = buffer[j - pixBytes];
- var p = left + up - upLeft;
- var pa = p - left;
- if (pa < 0) {
- pa = -pa;
- }
- var pb = p - up;
- if (pb < 0) {
- pb = -pb;
- }
- var pc = p - upLeft;
- if (pc < 0) {
- pc = -pc;
- }
- c = rawBytes[i];
- if (pa <= pb && pa <= pc) {
- buffer[j++] = left + c;
- } else if (pb <= pc) {
- buffer[j++] = up + c;
- } else {
- buffer[j++] = upLeft + c;
- }
- }
- break;
- default:
- error('Unsupported predictor: ' + predictor);
- }
- this.bufferLength += rowBytes;
- };
- return PredictorStream;
- }();
- /**
- * Depending on the type of JPEG a JpegStream is handled in different ways. For
- * JPEG's that are supported natively such as DeviceGray and DeviceRGB the image
- * data is stored and then loaded by the browser. For unsupported JPEG's we use
- * a library to decode these images and the stream behaves like all the other
- * DecodeStreams.
- */
- var JpegStream = function JpegStreamClosure() {
- function JpegStream(stream, maybeLength, dict, params) {
- // Some images may contain 'junk' before the SOI (start-of-image) marker.
- // Note: this seems to mainly affect inline images.
- var ch;
- while ((ch = stream.getByte()) !== -1) {
- if (ch === 0xFF) {
- // Find the first byte of the SOI marker (0xFFD8).
- stream.skip(-1);
- // Reset the stream position to the SOI.
- break;
- }
- }
- this.stream = stream;
- this.maybeLength = maybeLength;
- this.dict = dict;
- this.params = params;
- DecodeStream.call(this, maybeLength);
- }
- JpegStream.prototype = Object.create(DecodeStream.prototype);
- Object.defineProperty(JpegStream.prototype, 'bytes', {
- get: function JpegStream_bytes() {
- // If this.maybeLength is null, we'll get the entire stream.
- return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
- },
- configurable: true
- });
- JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) {
- if (this.bufferLength) {
- return;
- }
- var jpegImage = new JpegImage();
- // Checking if values need to be transformed before conversion.
- var decodeArr = this.dict.getArray('Decode', 'D');
- if (this.forceRGB && isArray(decodeArr)) {
- var bitsPerComponent = this.dict.get('BitsPerComponent') || 8;
- var decodeArrLength = decodeArr.length;
- var transform = new Int32Array(decodeArrLength);
- var transformNeeded = false;
- var maxValue = (1 << bitsPerComponent) - 1;
- for (var i = 0; i < decodeArrLength; i += 2) {
- transform[i] = (decodeArr[i + 1] - decodeArr[i]) * 256 | 0;
- transform[i + 1] = decodeArr[i] * maxValue | 0;
- if (transform[i] !== 256 || transform[i + 1] !== 0) {
- transformNeeded = true;
- }
- }
- if (transformNeeded) {
- jpegImage.decodeTransform = transform;
- }
- }
- // Fetching the 'ColorTransform' entry, if it exists.
- if (isDict(this.params)) {
- var colorTransform = this.params.get('ColorTransform');
- if (isInt(colorTransform)) {
- jpegImage.colorTransform = colorTransform;
- }
- }
- jpegImage.parse(this.bytes);
- var data = jpegImage.getData(this.drawWidth, this.drawHeight, this.forceRGB);
- this.buffer = data;
- this.bufferLength = data.length;
- this.eof = true;
- };
- JpegStream.prototype.getBytes = function JpegStream_getBytes(length) {
- this.ensureBuffer();
- return this.buffer;
- };
- JpegStream.prototype.getIR = function JpegStream_getIR(forceDataSchema) {
- return createObjectURL(this.bytes, 'image/jpeg', forceDataSchema);
- };
- return JpegStream;
- }();
- /**
- * For JPEG 2000's we use a library to decode these images and
- * the stream behaves like all the other DecodeStreams.
- */
- var JpxStream = function JpxStreamClosure() {
- function JpxStream(stream, maybeLength, dict, params) {
- this.stream = stream;
- this.maybeLength = maybeLength;
- this.dict = dict;
- this.params = params;
- DecodeStream.call(this, maybeLength);
- }
- JpxStream.prototype = Object.create(DecodeStream.prototype);
- Object.defineProperty(JpxStream.prototype, 'bytes', {
- get: function JpxStream_bytes() {
- // If this.maybeLength is null, we'll get the entire stream.
- return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
- },
- configurable: true
- });
- JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) {
- if (this.bufferLength) {
- return;
- }
- var jpxImage = new JpxImage();
- jpxImage.parse(this.bytes);
- var width = jpxImage.width;
- var height = jpxImage.height;
- var componentsCount = jpxImage.componentsCount;
- var tileCount = jpxImage.tiles.length;
- if (tileCount === 1) {
- this.buffer = jpxImage.tiles[0].items;
- } else {
- var data = new Uint8Array(width * height * componentsCount);
- for (var k = 0; k < tileCount; k++) {
- var tileComponents = jpxImage.tiles[k];
- var tileWidth = tileComponents.width;
- var tileHeight = tileComponents.height;
- var tileLeft = tileComponents.left;
- var tileTop = tileComponents.top;
- var src = tileComponents.items;
- var srcPosition = 0;
- var dataPosition = (width * tileTop + tileLeft) * componentsCount;
- var imgRowSize = width * componentsCount;
- var tileRowSize = tileWidth * componentsCount;
- for (var j = 0; j < tileHeight; j++) {
- var rowBytes = src.subarray(srcPosition, srcPosition + tileRowSize);
- data.set(rowBytes, dataPosition);
- srcPosition += tileRowSize;
- dataPosition += imgRowSize;
- }
- }
- this.buffer = data;
- }
- this.bufferLength = this.buffer.length;
- this.eof = true;
- };
- return JpxStream;
- }();
- /**
- * For JBIG2's we use a library to decode these images and
- * the stream behaves like all the other DecodeStreams.
- */
- var Jbig2Stream = function Jbig2StreamClosure() {
- function Jbig2Stream(stream, maybeLength, dict, params) {
- this.stream = stream;
- this.maybeLength = maybeLength;
- this.dict = dict;
- this.params = params;
- DecodeStream.call(this, maybeLength);
- }
- Jbig2Stream.prototype = Object.create(DecodeStream.prototype);
- Object.defineProperty(Jbig2Stream.prototype, 'bytes', {
- get: function Jbig2Stream_bytes() {
- // If this.maybeLength is null, we'll get the entire stream.
- return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
- },
- configurable: true
- });
- Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) {
- if (this.bufferLength) {
- return;
- }
- var jbig2Image = new Jbig2Image();
- var chunks = [];
- if (isDict(this.params)) {
- var globalsStream = this.params.get('JBIG2Globals');
- if (isStream(globalsStream)) {
- var globals = globalsStream.getBytes();
- chunks.push({
- data: globals,
- start: 0,
- end: globals.length
- });
- }
- }
- chunks.push({
- data: this.bytes,
- start: 0,
- end: this.bytes.length
- });
- var data = jbig2Image.parseChunks(chunks);
- var dataLength = data.length;
- // JBIG2 had black as 1 and white as 0, inverting the colors
- for (var i = 0; i < dataLength; i++) {
- data[i] ^= 0xFF;
- }
- this.buffer = data;
- this.bufferLength = dataLength;
- this.eof = true;
- };
- return Jbig2Stream;
- }();
- var DecryptStream = function DecryptStreamClosure() {
- function DecryptStream(str, maybeLength, decrypt) {
- this.str = str;
- this.dict = str.dict;
- this.decrypt = decrypt;
- this.nextChunk = null;
- this.initialized = false;
- DecodeStream.call(this, maybeLength);
- }
- var chunkSize = 512;
- DecryptStream.prototype = Object.create(DecodeStream.prototype);
- DecryptStream.prototype.readBlock = function DecryptStream_readBlock() {
- var chunk;
- if (this.initialized) {
- chunk = this.nextChunk;
- } else {
- chunk = this.str.getBytes(chunkSize);
- this.initialized = true;
- }
- if (!chunk || chunk.length === 0) {
- this.eof = true;
- return;
- }
- this.nextChunk = this.str.getBytes(chunkSize);
- var hasMoreData = this.nextChunk && this.nextChunk.length > 0;
- var decrypt = this.decrypt;
- chunk = decrypt(chunk, !hasMoreData);
- var bufferLength = this.bufferLength;
- var i, n = chunk.length;
- var buffer = this.ensureBuffer(bufferLength + n);
- for (i = 0; i < n; i++) {
- buffer[bufferLength++] = chunk[i];
- }
- this.bufferLength = bufferLength;
- };
- return DecryptStream;
- }();
- var Ascii85Stream = function Ascii85StreamClosure() {
- function Ascii85Stream(str, maybeLength) {
- this.str = str;
- this.dict = str.dict;
- this.input = new Uint8Array(5);
- // Most streams increase in size when decoded, but Ascii85 streams
- // typically shrink by ~20%.
- if (maybeLength) {
- maybeLength = 0.8 * maybeLength;
- }
- DecodeStream.call(this, maybeLength);
- }
- Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
- Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() {
- var TILDA_CHAR = 0x7E;
- // '~'
- var Z_LOWER_CHAR = 0x7A;
- // 'z'
- var EOF = -1;
- var str = this.str;
- var c = str.getByte();
- while (isSpace(c)) {
- c = str.getByte();
- }
- if (c === EOF || c === TILDA_CHAR) {
- this.eof = true;
- return;
- }
- var bufferLength = this.bufferLength, buffer;
- var i;
- // special code for z
- if (c === Z_LOWER_CHAR) {
- buffer = this.ensureBuffer(bufferLength + 4);
- for (i = 0; i < 4; ++i) {
- buffer[bufferLength + i] = 0;
- }
- this.bufferLength += 4;
- } else {
- var input = this.input;
- input[0] = c;
- for (i = 1; i < 5; ++i) {
- c = str.getByte();
- while (isSpace(c)) {
- c = str.getByte();
- }
- input[i] = c;
- if (c === EOF || c === TILDA_CHAR) {
- break;
- }
- }
- buffer = this.ensureBuffer(bufferLength + i - 1);
- this.bufferLength += i - 1;
- // partial ending;
- if (i < 5) {
- for (; i < 5; ++i) {
- input[i] = 0x21 + 84;
- }
- this.eof = true;
- }
- var t = 0;
- for (i = 0; i < 5; ++i) {
- t = t * 85 + (input[i] - 0x21);
- }
- for (i = 3; i >= 0; --i) {
- buffer[bufferLength + i] = t & 0xFF;
- t >>= 8;
- }
- }
- };
- return Ascii85Stream;
- }();
- var AsciiHexStream = function AsciiHexStreamClosure() {
- function AsciiHexStream(str, maybeLength) {
- this.str = str;
- this.dict = str.dict;
- this.firstDigit = -1;
- // Most streams increase in size when decoded, but AsciiHex streams shrink
- // by 50%.
- if (maybeLength) {
- maybeLength = 0.5 * maybeLength;
- }
- DecodeStream.call(this, maybeLength);
- }
- AsciiHexStream.prototype = Object.create(DecodeStream.prototype);
- AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() {
- var UPSTREAM_BLOCK_SIZE = 8000;
- var bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE);
- if (!bytes.length) {
- this.eof = true;
- return;
- }
- var maxDecodeLength = bytes.length + 1 >> 1;
- var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength);
- var bufferLength = this.bufferLength;
- var firstDigit = this.firstDigit;
- for (var i = 0, ii = bytes.length; i < ii; i++) {
- var ch = bytes[i], digit;
- if (ch >= 0x30 && ch <= 0x39) {
- // '0'-'9'
- digit = ch & 0x0F;
- } else if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) {
- // 'A'-'Z', 'a'-'z'
- digit = (ch & 0x0F) + 9;
- } else if (ch === 0x3E) {
- // '>'
- this.eof = true;
- break;
- } else {
- // probably whitespace
- continue;
- }
- // ignoring
- if (firstDigit < 0) {
- firstDigit = digit;
- } else {
- buffer[bufferLength++] = firstDigit << 4 | digit;
- firstDigit = -1;
- }
- }
- if (firstDigit >= 0 && this.eof) {
- // incomplete byte
- buffer[bufferLength++] = firstDigit << 4;
- firstDigit = -1;
- }
- this.firstDigit = firstDigit;
- this.bufferLength = bufferLength;
- };
- return AsciiHexStream;
- }();
- var RunLengthStream = function RunLengthStreamClosure() {
- function RunLengthStream(str, maybeLength) {
- this.str = str;
- this.dict = str.dict;
- DecodeStream.call(this, maybeLength);
- }
- RunLengthStream.prototype = Object.create(DecodeStream.prototype);
- RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() {
- // The repeatHeader has following format. The first byte defines type of run
- // and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes
- // (in addition to the second byte from the header), n = 129 through 255 -
- // duplicate the second byte from the header (257 - n) times, n = 128 - end.
- var repeatHeader = this.str.getBytes(2);
- if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) {
- this.eof = true;
- return;
- }
- var buffer;
- var bufferLength = this.bufferLength;
- var n = repeatHeader[0];
- if (n < 128) {
- // copy n bytes
- buffer = this.ensureBuffer(bufferLength + n + 1);
- buffer[bufferLength++] = repeatHeader[1];
- if (n > 0) {
- var source = this.str.getBytes(n);
- buffer.set(source, bufferLength);
- bufferLength += n;
- }
- } else {
- n = 257 - n;
- var b = repeatHeader[1];
- buffer = this.ensureBuffer(bufferLength + n + 1);
- for (var i = 0; i < n; i++) {
- buffer[bufferLength++] = b;
- }
- }
- this.bufferLength = bufferLength;
- };
- return RunLengthStream;
- }();
- var CCITTFaxStream = function CCITTFaxStreamClosure() {
- var ccittEOL = -2;
- var ccittEOF = -1;
- var twoDimPass = 0;
- var twoDimHoriz = 1;
- var twoDimVert0 = 2;
- var twoDimVertR1 = 3;
- var twoDimVertL1 = 4;
- var twoDimVertR2 = 5;
- var twoDimVertL2 = 6;
- var twoDimVertR3 = 7;
- var twoDimVertL3 = 8;
- var twoDimTable = [
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 000000x
- [
- 7,
- twoDimVertL3
- ],
- // 0000010
- [
- 7,
- twoDimVertR3
- ],
- // 0000011
- [
- 6,
- twoDimVertL2
- ],
- [
- 6,
- twoDimVertL2
- ],
- // 000010x
- [
- 6,
- twoDimVertR2
- ],
- [
- 6,
- twoDimVertR2
- ],
- // 000011x
- [
- 4,
- twoDimPass
- ],
- [
- 4,
- twoDimPass
- ],
- // 0001xxx
- [
- 4,
- twoDimPass
- ],
- [
- 4,
- twoDimPass
- ],
- [
- 4,
- twoDimPass
- ],
- [
- 4,
- twoDimPass
- ],
- [
- 4,
- twoDimPass
- ],
- [
- 4,
- twoDimPass
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- // 001xxxx
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimHoriz
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- // 010xxxx
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertL1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- // 011xxxx
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 3,
- twoDimVertR1
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- // 1xxxxxx
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ],
- [
- 1,
- twoDimVert0
- ]
- ];
- var whiteTable1 = [
- [
- -1,
- -1
- ],
- // 00000
- [
- 12,
- ccittEOL
- ],
- // 00001
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 0001x
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 001xx
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 010xx
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 011xx
- [
- 11,
- 1792
- ],
- [
- 11,
- 1792
- ],
- // 1000x
- [
- 12,
- 1984
- ],
- // 10010
- [
- 12,
- 2048
- ],
- // 10011
- [
- 12,
- 2112
- ],
- // 10100
- [
- 12,
- 2176
- ],
- // 10101
- [
- 12,
- 2240
- ],
- // 10110
- [
- 12,
- 2304
- ],
- // 10111
- [
- 11,
- 1856
- ],
- [
- 11,
- 1856
- ],
- // 1100x
- [
- 11,
- 1920
- ],
- [
- 11,
- 1920
- ],
- // 1101x
- [
- 12,
- 2368
- ],
- // 11100
- [
- 12,
- 2432
- ],
- // 11101
- [
- 12,
- 2496
- ],
- // 11110
- [
- 12,
- 2560
- ]
- ];
- // 11111
- var whiteTable2 = [
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 0000000xx
- [
- 8,
- 29
- ],
- [
- 8,
- 29
- ],
- // 00000010x
- [
- 8,
- 30
- ],
- [
- 8,
- 30
- ],
- // 00000011x
- [
- 8,
- 45
- ],
- [
- 8,
- 45
- ],
- // 00000100x
- [
- 8,
- 46
- ],
- [
- 8,
- 46
- ],
- // 00000101x
- [
- 7,
- 22
- ],
- [
- 7,
- 22
- ],
- [
- 7,
- 22
- ],
- [
- 7,
- 22
- ],
- // 0000011xx
- [
- 7,
- 23
- ],
- [
- 7,
- 23
- ],
- [
- 7,
- 23
- ],
- [
- 7,
- 23
- ],
- // 0000100xx
- [
- 8,
- 47
- ],
- [
- 8,
- 47
- ],
- // 00001010x
- [
- 8,
- 48
- ],
- [
- 8,
- 48
- ],
- // 00001011x
- [
- 6,
- 13
- ],
- [
- 6,
- 13
- ],
- [
- 6,
- 13
- ],
- [
- 6,
- 13
- ],
- // 000011xxx
- [
- 6,
- 13
- ],
- [
- 6,
- 13
- ],
- [
- 6,
- 13
- ],
- [
- 6,
- 13
- ],
- [
- 7,
- 20
- ],
- [
- 7,
- 20
- ],
- [
- 7,
- 20
- ],
- [
- 7,
- 20
- ],
- // 0001000xx
- [
- 8,
- 33
- ],
- [
- 8,
- 33
- ],
- // 00010010x
- [
- 8,
- 34
- ],
- [
- 8,
- 34
- ],
- // 00010011x
- [
- 8,
- 35
- ],
- [
- 8,
- 35
- ],
- // 00010100x
- [
- 8,
- 36
- ],
- [
- 8,
- 36
- ],
- // 00010101x
- [
- 8,
- 37
- ],
- [
- 8,
- 37
- ],
- // 00010110x
- [
- 8,
- 38
- ],
- [
- 8,
- 38
- ],
- // 00010111x
- [
- 7,
- 19
- ],
- [
- 7,
- 19
- ],
- [
- 7,
- 19
- ],
- [
- 7,
- 19
- ],
- // 0001100xx
- [
- 8,
- 31
- ],
- [
- 8,
- 31
- ],
- // 00011010x
- [
- 8,
- 32
- ],
- [
- 8,
- 32
- ],
- // 00011011x
- [
- 6,
- 1
- ],
- [
- 6,
- 1
- ],
- [
- 6,
- 1
- ],
- [
- 6,
- 1
- ],
- // 000111xxx
- [
- 6,
- 1
- ],
- [
- 6,
- 1
- ],
- [
- 6,
- 1
- ],
- [
- 6,
- 1
- ],
- [
- 6,
- 12
- ],
- [
- 6,
- 12
- ],
- [
- 6,
- 12
- ],
- [
- 6,
- 12
- ],
- // 001000xxx
- [
- 6,
- 12
- ],
- [
- 6,
- 12
- ],
- [
- 6,
- 12
- ],
- [
- 6,
- 12
- ],
- [
- 8,
- 53
- ],
- [
- 8,
- 53
- ],
- // 00100100x
- [
- 8,
- 54
- ],
- [
- 8,
- 54
- ],
- // 00100101x
- [
- 7,
- 26
- ],
- [
- 7,
- 26
- ],
- [
- 7,
- 26
- ],
- [
- 7,
- 26
- ],
- // 0010011xx
- [
- 8,
- 39
- ],
- [
- 8,
- 39
- ],
- // 00101000x
- [
- 8,
- 40
- ],
- [
- 8,
- 40
- ],
- // 00101001x
- [
- 8,
- 41
- ],
- [
- 8,
- 41
- ],
- // 00101010x
- [
- 8,
- 42
- ],
- [
- 8,
- 42
- ],
- // 00101011x
- [
- 8,
- 43
- ],
- [
- 8,
- 43
- ],
- // 00101100x
- [
- 8,
- 44
- ],
- [
- 8,
- 44
- ],
- // 00101101x
- [
- 7,
- 21
- ],
- [
- 7,
- 21
- ],
- [
- 7,
- 21
- ],
- [
- 7,
- 21
- ],
- // 0010111xx
- [
- 7,
- 28
- ],
- [
- 7,
- 28
- ],
- [
- 7,
- 28
- ],
- [
- 7,
- 28
- ],
- // 0011000xx
- [
- 8,
- 61
- ],
- [
- 8,
- 61
- ],
- // 00110010x
- [
- 8,
- 62
- ],
- [
- 8,
- 62
- ],
- // 00110011x
- [
- 8,
- 63
- ],
- [
- 8,
- 63
- ],
- // 00110100x
- [
- 8,
- 0
- ],
- [
- 8,
- 0
- ],
- // 00110101x
- [
- 8,
- 320
- ],
- [
- 8,
- 320
- ],
- // 00110110x
- [
- 8,
- 384
- ],
- [
- 8,
- 384
- ],
- // 00110111x
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- // 00111xxxx
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 10
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- // 01000xxxx
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 5,
- 11
- ],
- [
- 7,
- 27
- ],
- [
- 7,
- 27
- ],
- [
- 7,
- 27
- ],
- [
- 7,
- 27
- ],
- // 0100100xx
- [
- 8,
- 59
- ],
- [
- 8,
- 59
- ],
- // 01001010x
- [
- 8,
- 60
- ],
- [
- 8,
- 60
- ],
- // 01001011x
- [
- 9,
- 1472
- ],
- // 010011000
- [
- 9,
- 1536
- ],
- // 010011001
- [
- 9,
- 1600
- ],
- // 010011010
- [
- 9,
- 1728
- ],
- // 010011011
- [
- 7,
- 18
- ],
- [
- 7,
- 18
- ],
- [
- 7,
- 18
- ],
- [
- 7,
- 18
- ],
- // 0100111xx
- [
- 7,
- 24
- ],
- [
- 7,
- 24
- ],
- [
- 7,
- 24
- ],
- [
- 7,
- 24
- ],
- // 0101000xx
- [
- 8,
- 49
- ],
- [
- 8,
- 49
- ],
- // 01010010x
- [
- 8,
- 50
- ],
- [
- 8,
- 50
- ],
- // 01010011x
- [
- 8,
- 51
- ],
- [
- 8,
- 51
- ],
- // 01010100x
- [
- 8,
- 52
- ],
- [
- 8,
- 52
- ],
- // 01010101x
- [
- 7,
- 25
- ],
- [
- 7,
- 25
- ],
- [
- 7,
- 25
- ],
- [
- 7,
- 25
- ],
- // 0101011xx
- [
- 8,
- 55
- ],
- [
- 8,
- 55
- ],
- // 01011000x
- [
- 8,
- 56
- ],
- [
- 8,
- 56
- ],
- // 01011001x
- [
- 8,
- 57
- ],
- [
- 8,
- 57
- ],
- // 01011010x
- [
- 8,
- 58
- ],
- [
- 8,
- 58
- ],
- // 01011011x
- [
- 6,
- 192
- ],
- [
- 6,
- 192
- ],
- [
- 6,
- 192
- ],
- [
- 6,
- 192
- ],
- // 010111xxx
- [
- 6,
- 192
- ],
- [
- 6,
- 192
- ],
- [
- 6,
- 192
- ],
- [
- 6,
- 192
- ],
- [
- 6,
- 1664
- ],
- [
- 6,
- 1664
- ],
- [
- 6,
- 1664
- ],
- [
- 6,
- 1664
- ],
- // 011000xxx
- [
- 6,
- 1664
- ],
- [
- 6,
- 1664
- ],
- [
- 6,
- 1664
- ],
- [
- 6,
- 1664
- ],
- [
- 8,
- 448
- ],
- [
- 8,
- 448
- ],
- // 01100100x
- [
- 8,
- 512
- ],
- [
- 8,
- 512
- ],
- // 01100101x
- [
- 9,
- 704
- ],
- // 011001100
- [
- 9,
- 768
- ],
- // 011001101
- [
- 8,
- 640
- ],
- [
- 8,
- 640
- ],
- // 01100111x
- [
- 8,
- 576
- ],
- [
- 8,
- 576
- ],
- // 01101000x
- [
- 9,
- 832
- ],
- // 011010010
- [
- 9,
- 896
- ],
- // 011010011
- [
- 9,
- 960
- ],
- // 011010100
- [
- 9,
- 1024
- ],
- // 011010101
- [
- 9,
- 1088
- ],
- // 011010110
- [
- 9,
- 1152
- ],
- // 011010111
- [
- 9,
- 1216
- ],
- // 011011000
- [
- 9,
- 1280
- ],
- // 011011001
- [
- 9,
- 1344
- ],
- // 011011010
- [
- 9,
- 1408
- ],
- // 011011011
- [
- 7,
- 256
- ],
- [
- 7,
- 256
- ],
- [
- 7,
- 256
- ],
- [
- 7,
- 256
- ],
- // 0110111xx
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- // 0111xxxxx
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 2
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- // 1000xxxxx
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 4,
- 3
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- // 10010xxxx
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 128
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- // 10011xxxx
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 8
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- // 10100xxxx
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 5,
- 9
- ],
- [
- 6,
- 16
- ],
- [
- 6,
- 16
- ],
- [
- 6,
- 16
- ],
- [
- 6,
- 16
- ],
- // 101010xxx
- [
- 6,
- 16
- ],
- [
- 6,
- 16
- ],
- [
- 6,
- 16
- ],
- [
- 6,
- 16
- ],
- [
- 6,
- 17
- ],
- [
- 6,
- 17
- ],
- [
- 6,
- 17
- ],
- [
- 6,
- 17
- ],
- // 101011xxx
- [
- 6,
- 17
- ],
- [
- 6,
- 17
- ],
- [
- 6,
- 17
- ],
- [
- 6,
- 17
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- // 1011xxxxx
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 4
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- // 1100xxxxx
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 6,
- 14
- ],
- [
- 6,
- 14
- ],
- [
- 6,
- 14
- ],
- [
- 6,
- 14
- ],
- // 110100xxx
- [
- 6,
- 14
- ],
- [
- 6,
- 14
- ],
- [
- 6,
- 14
- ],
- [
- 6,
- 14
- ],
- [
- 6,
- 15
- ],
- [
- 6,
- 15
- ],
- [
- 6,
- 15
- ],
- [
- 6,
- 15
- ],
- // 110101xxx
- [
- 6,
- 15
- ],
- [
- 6,
- 15
- ],
- [
- 6,
- 15
- ],
- [
- 6,
- 15
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- // 11011xxxx
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 5,
- 64
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- // 1110xxxxx
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- // 1111xxxxx
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ],
- [
- 4,
- 7
- ]
- ];
- var blackTable1 = [
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 000000000000x
- [
- 12,
- ccittEOL
- ],
- [
- 12,
- ccittEOL
- ],
- // 000000000001x
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 00000000001xx
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 00000000010xx
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 00000000011xx
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 00000000100xx
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 00000000101xx
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 00000000110xx
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 00000000111xx
- [
- 11,
- 1792
- ],
- [
- 11,
- 1792
- ],
- [
- 11,
- 1792
- ],
- [
- 11,
- 1792
- ],
- // 00000001000xx
- [
- 12,
- 1984
- ],
- [
- 12,
- 1984
- ],
- // 000000010010x
- [
- 12,
- 2048
- ],
- [
- 12,
- 2048
- ],
- // 000000010011x
- [
- 12,
- 2112
- ],
- [
- 12,
- 2112
- ],
- // 000000010100x
- [
- 12,
- 2176
- ],
- [
- 12,
- 2176
- ],
- // 000000010101x
- [
- 12,
- 2240
- ],
- [
- 12,
- 2240
- ],
- // 000000010110x
- [
- 12,
- 2304
- ],
- [
- 12,
- 2304
- ],
- // 000000010111x
- [
- 11,
- 1856
- ],
- [
- 11,
- 1856
- ],
- [
- 11,
- 1856
- ],
- [
- 11,
- 1856
- ],
- // 00000001100xx
- [
- 11,
- 1920
- ],
- [
- 11,
- 1920
- ],
- [
- 11,
- 1920
- ],
- [
- 11,
- 1920
- ],
- // 00000001101xx
- [
- 12,
- 2368
- ],
- [
- 12,
- 2368
- ],
- // 000000011100x
- [
- 12,
- 2432
- ],
- [
- 12,
- 2432
- ],
- // 000000011101x
- [
- 12,
- 2496
- ],
- [
- 12,
- 2496
- ],
- // 000000011110x
- [
- 12,
- 2560
- ],
- [
- 12,
- 2560
- ],
- // 000000011111x
- [
- 10,
- 18
- ],
- [
- 10,
- 18
- ],
- [
- 10,
- 18
- ],
- [
- 10,
- 18
- ],
- // 0000001000xxx
- [
- 10,
- 18
- ],
- [
- 10,
- 18
- ],
- [
- 10,
- 18
- ],
- [
- 10,
- 18
- ],
- [
- 12,
- 52
- ],
- [
- 12,
- 52
- ],
- // 000000100100x
- [
- 13,
- 640
- ],
- // 0000001001010
- [
- 13,
- 704
- ],
- // 0000001001011
- [
- 13,
- 768
- ],
- // 0000001001100
- [
- 13,
- 832
- ],
- // 0000001001101
- [
- 12,
- 55
- ],
- [
- 12,
- 55
- ],
- // 000000100111x
- [
- 12,
- 56
- ],
- [
- 12,
- 56
- ],
- // 000000101000x
- [
- 13,
- 1280
- ],
- // 0000001010010
- [
- 13,
- 1344
- ],
- // 0000001010011
- [
- 13,
- 1408
- ],
- // 0000001010100
- [
- 13,
- 1472
- ],
- // 0000001010101
- [
- 12,
- 59
- ],
- [
- 12,
- 59
- ],
- // 000000101011x
- [
- 12,
- 60
- ],
- [
- 12,
- 60
- ],
- // 000000101100x
- [
- 13,
- 1536
- ],
- // 0000001011010
- [
- 13,
- 1600
- ],
- // 0000001011011
- [
- 11,
- 24
- ],
- [
- 11,
- 24
- ],
- [
- 11,
- 24
- ],
- [
- 11,
- 24
- ],
- // 00000010111xx
- [
- 11,
- 25
- ],
- [
- 11,
- 25
- ],
- [
- 11,
- 25
- ],
- [
- 11,
- 25
- ],
- // 00000011000xx
- [
- 13,
- 1664
- ],
- // 0000001100100
- [
- 13,
- 1728
- ],
- // 0000001100101
- [
- 12,
- 320
- ],
- [
- 12,
- 320
- ],
- // 000000110011x
- [
- 12,
- 384
- ],
- [
- 12,
- 384
- ],
- // 000000110100x
- [
- 12,
- 448
- ],
- [
- 12,
- 448
- ],
- // 000000110101x
- [
- 13,
- 512
- ],
- // 0000001101100
- [
- 13,
- 576
- ],
- // 0000001101101
- [
- 12,
- 53
- ],
- [
- 12,
- 53
- ],
- // 000000110111x
- [
- 12,
- 54
- ],
- [
- 12,
- 54
- ],
- // 000000111000x
- [
- 13,
- 896
- ],
- // 0000001110010
- [
- 13,
- 960
- ],
- // 0000001110011
- [
- 13,
- 1024
- ],
- // 0000001110100
- [
- 13,
- 1088
- ],
- // 0000001110101
- [
- 13,
- 1152
- ],
- // 0000001110110
- [
- 13,
- 1216
- ],
- // 0000001110111
- [
- 10,
- 64
- ],
- [
- 10,
- 64
- ],
- [
- 10,
- 64
- ],
- [
- 10,
- 64
- ],
- // 0000001111xxx
- [
- 10,
- 64
- ],
- [
- 10,
- 64
- ],
- [
- 10,
- 64
- ],
- [
- 10,
- 64
- ]
- ];
- var blackTable2 = [
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- // 00000100xxxx
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 8,
- 13
- ],
- [
- 11,
- 23
- ],
- [
- 11,
- 23
- ],
- // 00000101000x
- [
- 12,
- 50
- ],
- // 000001010010
- [
- 12,
- 51
- ],
- // 000001010011
- [
- 12,
- 44
- ],
- // 000001010100
- [
- 12,
- 45
- ],
- // 000001010101
- [
- 12,
- 46
- ],
- // 000001010110
- [
- 12,
- 47
- ],
- // 000001010111
- [
- 12,
- 57
- ],
- // 000001011000
- [
- 12,
- 58
- ],
- // 000001011001
- [
- 12,
- 61
- ],
- // 000001011010
- [
- 12,
- 256
- ],
- // 000001011011
- [
- 10,
- 16
- ],
- [
- 10,
- 16
- ],
- [
- 10,
- 16
- ],
- [
- 10,
- 16
- ],
- // 0000010111xx
- [
- 10,
- 17
- ],
- [
- 10,
- 17
- ],
- [
- 10,
- 17
- ],
- [
- 10,
- 17
- ],
- // 0000011000xx
- [
- 12,
- 48
- ],
- // 000001100100
- [
- 12,
- 49
- ],
- // 000001100101
- [
- 12,
- 62
- ],
- // 000001100110
- [
- 12,
- 63
- ],
- // 000001100111
- [
- 12,
- 30
- ],
- // 000001101000
- [
- 12,
- 31
- ],
- // 000001101001
- [
- 12,
- 32
- ],
- // 000001101010
- [
- 12,
- 33
- ],
- // 000001101011
- [
- 12,
- 40
- ],
- // 000001101100
- [
- 12,
- 41
- ],
- // 000001101101
- [
- 11,
- 22
- ],
- [
- 11,
- 22
- ],
- // 00000110111x
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- // 00000111xxxx
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 8,
- 14
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- // 0000100xxxxx
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 10
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- // 0000101xxxxx
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 7,
- 11
- ],
- [
- 9,
- 15
- ],
- [
- 9,
- 15
- ],
- [
- 9,
- 15
- ],
- [
- 9,
- 15
- ],
- // 000011000xxx
- [
- 9,
- 15
- ],
- [
- 9,
- 15
- ],
- [
- 9,
- 15
- ],
- [
- 9,
- 15
- ],
- [
- 12,
- 128
- ],
- // 000011001000
- [
- 12,
- 192
- ],
- // 000011001001
- [
- 12,
- 26
- ],
- // 000011001010
- [
- 12,
- 27
- ],
- // 000011001011
- [
- 12,
- 28
- ],
- // 000011001100
- [
- 12,
- 29
- ],
- // 000011001101
- [
- 11,
- 19
- ],
- [
- 11,
- 19
- ],
- // 00001100111x
- [
- 11,
- 20
- ],
- [
- 11,
- 20
- ],
- // 00001101000x
- [
- 12,
- 34
- ],
- // 000011010010
- [
- 12,
- 35
- ],
- // 000011010011
- [
- 12,
- 36
- ],
- // 000011010100
- [
- 12,
- 37
- ],
- // 000011010101
- [
- 12,
- 38
- ],
- // 000011010110
- [
- 12,
- 39
- ],
- // 000011010111
- [
- 11,
- 21
- ],
- [
- 11,
- 21
- ],
- // 00001101100x
- [
- 12,
- 42
- ],
- // 000011011010
- [
- 12,
- 43
- ],
- // 000011011011
- [
- 10,
- 0
- ],
- [
- 10,
- 0
- ],
- [
- 10,
- 0
- ],
- [
- 10,
- 0
- ],
- // 0000110111xx
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- // 0000111xxxxx
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ],
- [
- 7,
- 12
- ]
- ];
- var blackTable3 = [
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- [
- -1,
- -1
- ],
- // 0000xx
- [
- 6,
- 9
- ],
- // 000100
- [
- 6,
- 8
- ],
- // 000101
- [
- 5,
- 7
- ],
- [
- 5,
- 7
- ],
- // 00011x
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- [
- 4,
- 6
- ],
- // 0010xx
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- [
- 4,
- 5
- ],
- // 0011xx
- [
- 3,
- 1
- ],
- [
- 3,
- 1
- ],
- [
- 3,
- 1
- ],
- [
- 3,
- 1
- ],
- // 010xxx
- [
- 3,
- 1
- ],
- [
- 3,
- 1
- ],
- [
- 3,
- 1
- ],
- [
- 3,
- 1
- ],
- [
- 3,
- 4
- ],
- [
- 3,
- 4
- ],
- [
- 3,
- 4
- ],
- [
- 3,
- 4
- ],
- // 011xxx
- [
- 3,
- 4
- ],
- [
- 3,
- 4
- ],
- [
- 3,
- 4
- ],
- [
- 3,
- 4
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- // 10xxxx
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 3
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- // 11xxxx
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ],
- [
- 2,
- 2
- ]
- ];
- function CCITTFaxStream(str, maybeLength, params) {
- this.str = str;
- this.dict = str.dict;
- params = params || Dict.empty;
- this.encoding = params.get('K') || 0;
- this.eoline = params.get('EndOfLine') || false;
- this.byteAlign = params.get('EncodedByteAlign') || false;
- this.columns = params.get('Columns') || 1728;
- this.rows = params.get('Rows') || 0;
- var eoblock = params.get('EndOfBlock');
- if (eoblock === null || eoblock === undefined) {
- eoblock = true;
- }
- this.eoblock = eoblock;
- this.black = params.get('BlackIs1') || false;
- this.codingLine = new Uint32Array(this.columns + 1);
- this.refLine = new Uint32Array(this.columns + 2);
- this.codingLine[0] = this.columns;
- this.codingPos = 0;
- this.row = 0;
- this.nextLine2D = this.encoding < 0;
- this.inputBits = 0;
- this.inputBuf = 0;
- this.outputBits = 0;
- var code1;
- while ((code1 = this.lookBits(12)) === 0) {
- this.eatBits(1);
- }
- if (code1 === 1) {
- this.eatBits(12);
- }
- if (this.encoding > 0) {
- this.nextLine2D = !this.lookBits(1);
- this.eatBits(1);
- }
- DecodeStream.call(this, maybeLength);
- }
- CCITTFaxStream.prototype = Object.create(DecodeStream.prototype);
- CCITTFaxStream.prototype.readBlock = function CCITTFaxStream_readBlock() {
- while (!this.eof) {
- var c = this.lookChar();
- this.ensureBuffer(this.bufferLength + 1);
- this.buffer[this.bufferLength++] = c;
- }
- };
- CCITTFaxStream.prototype.addPixels = function ccittFaxStreamAddPixels(a1, blackPixels) {
- var codingLine = this.codingLine;
- var codingPos = this.codingPos;
- if (a1 > codingLine[codingPos]) {
- if (a1 > this.columns) {
- info('row is wrong length');
- this.err = true;
- a1 = this.columns;
- }
- if (codingPos & 1 ^ blackPixels) {
- ++codingPos;
- }
- codingLine[codingPos] = a1;
- }
- this.codingPos = codingPos;
- };
- CCITTFaxStream.prototype.addPixelsNeg = function ccittFaxStreamAddPixelsNeg(a1, blackPixels) {
- var codingLine = this.codingLine;
- var codingPos = this.codingPos;
- if (a1 > codingLine[codingPos]) {
- if (a1 > this.columns) {
- info('row is wrong length');
- this.err = true;
- a1 = this.columns;
- }
- if (codingPos & 1 ^ blackPixels) {
- ++codingPos;
- }
- codingLine[codingPos] = a1;
- } else if (a1 < codingLine[codingPos]) {
- if (a1 < 0) {
- info('invalid code');
- this.err = true;
- a1 = 0;
- }
- while (codingPos > 0 && a1 < codingLine[codingPos - 1]) {
- --codingPos;
- }
- codingLine[codingPos] = a1;
- }
- this.codingPos = codingPos;
- };
- CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() {
- var refLine = this.refLine;
- var codingLine = this.codingLine;
- var columns = this.columns;
- var refPos, blackPixels, bits, i;
- if (this.outputBits === 0) {
- if (this.eof) {
- return null;
- }
- this.err = false;
- var code1, code2, code3;
- if (this.nextLine2D) {
- for (i = 0; codingLine[i] < columns; ++i) {
- refLine[i] = codingLine[i];
- }
- refLine[i++] = columns;
- refLine[i] = columns;
- codingLine[0] = 0;
- this.codingPos = 0;
- refPos = 0;
- blackPixels = 0;
- while (codingLine[this.codingPos] < columns) {
- code1 = this.getTwoDimCode();
- switch (code1) {
- case twoDimPass:
- this.addPixels(refLine[refPos + 1], blackPixels);
- if (refLine[refPos + 1] < columns) {
- refPos += 2;
- }
- break;
- case twoDimHoriz:
- code1 = code2 = 0;
- if (blackPixels) {
- do {
- code1 += code3 = this.getBlackCode();
- } while (code3 >= 64);
- do {
- code2 += code3 = this.getWhiteCode();
- } while (code3 >= 64);
- } else {
- do {
- code1 += code3 = this.getWhiteCode();
- } while (code3 >= 64);
- do {
- code2 += code3 = this.getBlackCode();
- } while (code3 >= 64);
- }
- this.addPixels(codingLine[this.codingPos] + code1, blackPixels);
- if (codingLine[this.codingPos] < columns) {
- this.addPixels(codingLine[this.codingPos] + code2, blackPixels ^ 1);
- }
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- break;
- case twoDimVertR3:
- this.addPixels(refLine[refPos] + 3, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- ++refPos;
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVertR2:
- this.addPixels(refLine[refPos] + 2, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- ++refPos;
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVertR1:
- this.addPixels(refLine[refPos] + 1, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- ++refPos;
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVert0:
- this.addPixels(refLine[refPos], blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- ++refPos;
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVertL3:
- this.addPixelsNeg(refLine[refPos] - 3, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- if (refPos > 0) {
- --refPos;
- } else {
- ++refPos;
- }
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVertL2:
- this.addPixelsNeg(refLine[refPos] - 2, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- if (refPos > 0) {
- --refPos;
- } else {
- ++refPos;
- }
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVertL1:
- this.addPixelsNeg(refLine[refPos] - 1, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- if (refPos > 0) {
- --refPos;
- } else {
- ++refPos;
- }
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case ccittEOF:
- this.addPixels(columns, 0);
- this.eof = true;
- break;
- default:
- info('bad 2d code');
- this.addPixels(columns, 0);
- this.err = true;
- }
- }
- } else {
- codingLine[0] = 0;
- this.codingPos = 0;
- blackPixels = 0;
- while (codingLine[this.codingPos] < columns) {
- code1 = 0;
- if (blackPixels) {
- do {
- code1 += code3 = this.getBlackCode();
- } while (code3 >= 64);
- } else {
- do {
- code1 += code3 = this.getWhiteCode();
- } while (code3 >= 64);
- }
- this.addPixels(codingLine[this.codingPos] + code1, blackPixels);
- blackPixels ^= 1;
- }
- }
- var gotEOL = false;
- if (this.byteAlign) {
- this.inputBits &= ~7;
- }
- if (!this.eoblock && this.row === this.rows - 1) {
- this.eof = true;
- } else {
- code1 = this.lookBits(12);
- if (this.eoline) {
- while (code1 !== ccittEOF && code1 !== 1) {
- this.eatBits(1);
- code1 = this.lookBits(12);
- }
- } else {
- while (code1 === 0) {
- this.eatBits(1);
- code1 = this.lookBits(12);
- }
- }
- if (code1 === 1) {
- this.eatBits(12);
- gotEOL = true;
- } else if (code1 === ccittEOF) {
- this.eof = true;
- }
- }
- if (!this.eof && this.encoding > 0) {
- this.nextLine2D = !this.lookBits(1);
- this.eatBits(1);
- }
- if (this.eoblock && gotEOL && this.byteAlign) {
- code1 = this.lookBits(12);
- if (code1 === 1) {
- this.eatBits(12);
- if (this.encoding > 0) {
- this.lookBits(1);
- this.eatBits(1);
- }
- if (this.encoding >= 0) {
- for (i = 0; i < 4; ++i) {
- code1 = this.lookBits(12);
- if (code1 !== 1) {
- info('bad rtc code: ' + code1);
- }
- this.eatBits(12);
- if (this.encoding > 0) {
- this.lookBits(1);
- this.eatBits(1);
- }
- }
- }
- this.eof = true;
- }
- } else if (this.err && this.eoline) {
- while (true) {
- code1 = this.lookBits(13);
- if (code1 === ccittEOF) {
- this.eof = true;
- return null;
- }
- if (code1 >> 1 === 1) {
- break;
- }
- this.eatBits(1);
- }
- this.eatBits(12);
- if (this.encoding > 0) {
- this.eatBits(1);
- this.nextLine2D = !(code1 & 1);
- }
- }
- if (codingLine[0] > 0) {
- this.outputBits = codingLine[this.codingPos = 0];
- } else {
- this.outputBits = codingLine[this.codingPos = 1];
- }
- this.row++;
- }
- var c;
- if (this.outputBits >= 8) {
- c = this.codingPos & 1 ? 0 : 0xFF;
- this.outputBits -= 8;
- if (this.outputBits === 0 && codingLine[this.codingPos] < columns) {
- this.codingPos++;
- this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];
- }
- } else {
- bits = 8;
- c = 0;
- do {
- if (this.outputBits > bits) {
- c <<= bits;
- if (!(this.codingPos & 1)) {
- c |= 0xFF >> 8 - bits;
- }
- this.outputBits -= bits;
- bits = 0;
- } else {
- c <<= this.outputBits;
- if (!(this.codingPos & 1)) {
- c |= 0xFF >> 8 - this.outputBits;
- }
- bits -= this.outputBits;
- this.outputBits = 0;
- if (codingLine[this.codingPos] < columns) {
- this.codingPos++;
- this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];
- } else if (bits > 0) {
- c <<= bits;
- bits = 0;
- }
- }
- } while (bits);
- }
- if (this.black) {
- c ^= 0xFF;
- }
- return c;
- };
- // This functions returns the code found from the table.
- // The start and end parameters set the boundaries for searching the table.
- // The limit parameter is optional. Function returns an array with three
- // values. The first array element indicates whether a valid code is being
- // returned. The second array element is the actual code. The third array
- // element indicates whether EOF was reached.
- CCITTFaxStream.prototype.findTableCode = function ccittFaxStreamFindTableCode(start, end, table, limit) {
- var limitValue = limit || 0;
- for (var i = start; i <= end; ++i) {
- var code = this.lookBits(i);
- if (code === ccittEOF) {
- return [
- true,
- 1,
- false
- ];
- }
- if (i < end) {
- code <<= end - i;
- }
- if (!limitValue || code >= limitValue) {
- var p = table[code - limitValue];
- if (p[0] === i) {
- this.eatBits(i);
- return [
- true,
- p[1],
- true
- ];
- }
- }
- }
- return [
- false,
- 0,
- false
- ];
- };
- CCITTFaxStream.prototype.getTwoDimCode = function ccittFaxStreamGetTwoDimCode() {
- var code = 0;
- var p;
- if (this.eoblock) {
- code = this.lookBits(7);
- p = twoDimTable[code];
- if (p && p[0] > 0) {
- this.eatBits(p[0]);
- return p[1];
- }
- } else {
- var result = this.findTableCode(1, 7, twoDimTable);
- if (result[0] && result[2]) {
- return result[1];
- }
- }
- info('Bad two dim code');
- return ccittEOF;
- };
- CCITTFaxStream.prototype.getWhiteCode = function ccittFaxStreamGetWhiteCode() {
- var code = 0;
- var p;
- if (this.eoblock) {
- code = this.lookBits(12);
- if (code === ccittEOF) {
- return 1;
- }
- if (code >> 5 === 0) {
- p = whiteTable1[code];
- } else {
- p = whiteTable2[code >> 3];
- }
- if (p[0] > 0) {
- this.eatBits(p[0]);
- return p[1];
- }
- } else {
- var result = this.findTableCode(1, 9, whiteTable2);
- if (result[0]) {
- return result[1];
- }
- result = this.findTableCode(11, 12, whiteTable1);
- if (result[0]) {
- return result[1];
- }
- }
- info('bad white code');
- this.eatBits(1);
- return 1;
- };
- CCITTFaxStream.prototype.getBlackCode = function ccittFaxStreamGetBlackCode() {
- var code, p;
- if (this.eoblock) {
- code = this.lookBits(13);
- if (code === ccittEOF) {
- return 1;
- }
- if (code >> 7 === 0) {
- p = blackTable1[code];
- } else if (code >> 9 === 0 && code >> 7 !== 0) {
- p = blackTable2[(code >> 1) - 64];
- } else {
- p = blackTable3[code >> 7];
- }
- if (p[0] > 0) {
- this.eatBits(p[0]);
- return p[1];
- }
- } else {
- var result = this.findTableCode(2, 6, blackTable3);
- if (result[0]) {
- return result[1];
- }
- result = this.findTableCode(7, 12, blackTable2, 64);
- if (result[0]) {
- return result[1];
- }
- result = this.findTableCode(10, 13, blackTable1);
- if (result[0]) {
- return result[1];
- }
- }
- info('bad black code');
- this.eatBits(1);
- return 1;
- };
- CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) {
- var c;
- while (this.inputBits < n) {
- if ((c = this.str.getByte()) === -1) {
- if (this.inputBits === 0) {
- return ccittEOF;
- }
- return this.inputBuf << n - this.inputBits & 0xFFFF >> 16 - n;
- }
- this.inputBuf = this.inputBuf << 8 | c;
- this.inputBits += 8;
- }
- return this.inputBuf >> this.inputBits - n & 0xFFFF >> 16 - n;
- };
- CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) {
- if ((this.inputBits -= n) < 0) {
- this.inputBits = 0;
- }
- };
- return CCITTFaxStream;
- }();
- var LZWStream = function LZWStreamClosure() {
- function LZWStream(str, maybeLength, earlyChange) {
- this.str = str;
- this.dict = str.dict;
- this.cachedData = 0;
- this.bitsCached = 0;
- var maxLzwDictionarySize = 4096;
- var lzwState = {
- earlyChange: earlyChange,
- codeLength: 9,
- nextCode: 258,
- dictionaryValues: new Uint8Array(maxLzwDictionarySize),
- dictionaryLengths: new Uint16Array(maxLzwDictionarySize),
- dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize),
- currentSequence: new Uint8Array(maxLzwDictionarySize),
- currentSequenceLength: 0
- };
- for (var i = 0; i < 256; ++i) {
- lzwState.dictionaryValues[i] = i;
- lzwState.dictionaryLengths[i] = 1;
- }
- this.lzwState = lzwState;
- DecodeStream.call(this, maybeLength);
- }
- LZWStream.prototype = Object.create(DecodeStream.prototype);
- LZWStream.prototype.readBits = function LZWStream_readBits(n) {
- var bitsCached = this.bitsCached;
- var cachedData = this.cachedData;
- while (bitsCached < n) {
- var c = this.str.getByte();
- if (c === -1) {
- this.eof = true;
- return null;
- }
- cachedData = cachedData << 8 | c;
- bitsCached += 8;
- }
- this.bitsCached = bitsCached -= n;
- this.cachedData = cachedData;
- this.lastCode = null;
- return cachedData >>> bitsCached & (1 << n) - 1;
- };
- LZWStream.prototype.readBlock = function LZWStream_readBlock() {
- var blockSize = 512;
- var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize;
- var i, j, q;
- var lzwState = this.lzwState;
- if (!lzwState) {
- return;
- }
- // eof was found
- var earlyChange = lzwState.earlyChange;
- var nextCode = lzwState.nextCode;
- var dictionaryValues = lzwState.dictionaryValues;
- var dictionaryLengths = lzwState.dictionaryLengths;
- var dictionaryPrevCodes = lzwState.dictionaryPrevCodes;
- var codeLength = lzwState.codeLength;
- var prevCode = lzwState.prevCode;
- var currentSequence = lzwState.currentSequence;
- var currentSequenceLength = lzwState.currentSequenceLength;
- var decodedLength = 0;
- var currentBufferLength = this.bufferLength;
- var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
- for (i = 0; i < blockSize; i++) {
- var code = this.readBits(codeLength);
- var hasPrev = currentSequenceLength > 0;
- if (code < 256) {
- currentSequence[0] = code;
- currentSequenceLength = 1;
- } else if (code >= 258) {
- if (code < nextCode) {
- currentSequenceLength = dictionaryLengths[code];
- for (j = currentSequenceLength - 1, q = code; j >= 0; j--) {
- currentSequence[j] = dictionaryValues[q];
- q = dictionaryPrevCodes[q];
- }
- } else {
- currentSequence[currentSequenceLength++] = currentSequence[0];
- }
- } else if (code === 256) {
- codeLength = 9;
- nextCode = 258;
- currentSequenceLength = 0;
- continue;
- } else {
- this.eof = true;
- delete this.lzwState;
- break;
- }
- if (hasPrev) {
- dictionaryPrevCodes[nextCode] = prevCode;
- dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
- dictionaryValues[nextCode] = currentSequence[0];
- nextCode++;
- codeLength = nextCode + earlyChange & nextCode + earlyChange - 1 ? codeLength : Math.min(Math.log(nextCode + earlyChange) / 0.6931471805599453 + 1, 12) | 0;
- }
- prevCode = code;
- decodedLength += currentSequenceLength;
- if (estimatedDecodedSize < decodedLength) {
- do {
- estimatedDecodedSize += decodedSizeDelta;
- } while (estimatedDecodedSize < decodedLength);
- buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
- }
- for (j = 0; j < currentSequenceLength; j++) {
- buffer[currentBufferLength++] = currentSequence[j];
- }
- }
- lzwState.nextCode = nextCode;
- lzwState.codeLength = codeLength;
- lzwState.prevCode = prevCode;
- lzwState.currentSequenceLength = currentSequenceLength;
- this.bufferLength = currentBufferLength;
- };
- return LZWStream;
- }();
- var NullStream = function NullStreamClosure() {
- function NullStream() {
- Stream.call(this, new Uint8Array(0));
- }
- NullStream.prototype = Stream.prototype;
- return NullStream;
- }();
- exports.Ascii85Stream = Ascii85Stream;
- exports.AsciiHexStream = AsciiHexStream;
- exports.CCITTFaxStream = CCITTFaxStream;
- exports.DecryptStream = DecryptStream;
- exports.DecodeStream = DecodeStream;
- exports.FlateStream = FlateStream;
- exports.Jbig2Stream = Jbig2Stream;
- exports.JpegStream = JpegStream;
- exports.JpxStream = JpxStream;
- exports.NullStream = NullStream;
- exports.PredictorStream = PredictorStream;
- exports.RunLengthStream = RunLengthStream;
- exports.Stream = Stream;
- exports.StreamsSequenceStream = StreamsSequenceStream;
- exports.StringStream = StringStream;
- exports.LZWStream = LZWStream;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreCrypto = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreStream);
- }(this, function (exports, sharedUtil, corePrimitives, coreStream) {
- var PasswordException = sharedUtil.PasswordException;
- var PasswordResponses = sharedUtil.PasswordResponses;
- var bytesToString = sharedUtil.bytesToString;
- var warn = sharedUtil.warn;
- var error = sharedUtil.error;
- var assert = sharedUtil.assert;
- var isInt = sharedUtil.isInt;
- var stringToBytes = sharedUtil.stringToBytes;
- var utf8StringToString = sharedUtil.utf8StringToString;
- var Name = corePrimitives.Name;
- var isName = corePrimitives.isName;
- var isDict = corePrimitives.isDict;
- var DecryptStream = coreStream.DecryptStream;
- var ARCFourCipher = function ARCFourCipherClosure() {
- function ARCFourCipher(key) {
- this.a = 0;
- this.b = 0;
- var s = new Uint8Array(256);
- var i, j = 0, tmp, keyLength = key.length;
- for (i = 0; i < 256; ++i) {
- s[i] = i;
- }
- for (i = 0; i < 256; ++i) {
- tmp = s[i];
- j = j + tmp + key[i % keyLength] & 0xFF;
- s[i] = s[j];
- s[j] = tmp;
- }
- this.s = s;
- }
- ARCFourCipher.prototype = {
- encryptBlock: function ARCFourCipher_encryptBlock(data) {
- var i, n = data.length, tmp, tmp2;
- var a = this.a, b = this.b, s = this.s;
- var output = new Uint8Array(n);
- for (i = 0; i < n; ++i) {
- a = a + 1 & 0xFF;
- tmp = s[a];
- b = b + tmp & 0xFF;
- tmp2 = s[b];
- s[a] = tmp2;
- s[b] = tmp;
- output[i] = data[i] ^ s[tmp + tmp2 & 0xFF];
- }
- this.a = a;
- this.b = b;
- return output;
- }
- };
- ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock;
- return ARCFourCipher;
- }();
- var calculateMD5 = function calculateMD5Closure() {
- var r = new Uint8Array([
- 7,
- 12,
- 17,
- 22,
- 7,
- 12,
- 17,
- 22,
- 7,
- 12,
- 17,
- 22,
- 7,
- 12,
- 17,
- 22,
- 5,
- 9,
- 14,
- 20,
- 5,
- 9,
- 14,
- 20,
- 5,
- 9,
- 14,
- 20,
- 5,
- 9,
- 14,
- 20,
- 4,
- 11,
- 16,
- 23,
- 4,
- 11,
- 16,
- 23,
- 4,
- 11,
- 16,
- 23,
- 4,
- 11,
- 16,
- 23,
- 6,
- 10,
- 15,
- 21,
- 6,
- 10,
- 15,
- 21,
- 6,
- 10,
- 15,
- 21,
- 6,
- 10,
- 15,
- 21
- ]);
- var k = new Int32Array([
- -680876936,
- -389564586,
- 606105819,
- -1044525330,
- -176418897,
- 1200080426,
- -1473231341,
- -45705983,
- 1770035416,
- -1958414417,
- -42063,
- -1990404162,
- 1804603682,
- -40341101,
- -1502002290,
- 1236535329,
- -165796510,
- -1069501632,
- 643717713,
- -373897302,
- -701558691,
- 38016083,
- -660478335,
- -405537848,
- 568446438,
- -1019803690,
- -187363961,
- 1163531501,
- -1444681467,
- -51403784,
- 1735328473,
- -1926607734,
- -378558,
- -2022574463,
- 1839030562,
- -35309556,
- -1530992060,
- 1272893353,
- -155497632,
- -1094730640,
- 681279174,
- -358537222,
- -722521979,
- 76029189,
- -640364487,
- -421815835,
- 530742520,
- -995338651,
- -198630844,
- 1126891415,
- -1416354905,
- -57434055,
- 1700485571,
- -1894986606,
- -1051523,
- -2054922799,
- 1873313359,
- -30611744,
- -1560198380,
- 1309151649,
- -145523070,
- -1120210379,
- 718787259,
- -343485551
- ]);
- function hash(data, offset, length) {
- var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878;
- // pre-processing
- var paddedLength = length + 72 & ~63;
- // data + 9 extra bytes
- var padded = new Uint8Array(paddedLength);
- var i, j, n;
- for (i = 0; i < length; ++i) {
- padded[i] = data[offset++];
- }
- padded[i++] = 0x80;
- n = paddedLength - 8;
- while (i < n) {
- padded[i++] = 0;
- }
- padded[i++] = length << 3 & 0xFF;
- padded[i++] = length >> 5 & 0xFF;
- padded[i++] = length >> 13 & 0xFF;
- padded[i++] = length >> 21 & 0xFF;
- padded[i++] = length >>> 29 & 0xFF;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- var w = new Int32Array(16);
- for (i = 0; i < paddedLength;) {
- for (j = 0; j < 16; ++j, i += 4) {
- w[j] = padded[i] | padded[i + 1] << 8 | padded[i + 2] << 16 | padded[i + 3] << 24;
- }
- var a = h0, b = h1, c = h2, d = h3, f, g;
- for (j = 0; j < 64; ++j) {
- if (j < 16) {
- f = b & c | ~b & d;
- g = j;
- } else if (j < 32) {
- f = d & b | ~d & c;
- g = 5 * j + 1 & 15;
- } else if (j < 48) {
- f = b ^ c ^ d;
- g = 3 * j + 5 & 15;
- } else {
- f = c ^ (b | ~d);
- g = 7 * j & 15;
- }
- var tmp = d, rotateArg = a + f + k[j] + w[g] | 0, rotate = r[j];
- d = c;
- c = b;
- b = b + (rotateArg << rotate | rotateArg >>> 32 - rotate) | 0;
- a = tmp;
- }
- h0 = h0 + a | 0;
- h1 = h1 + b | 0;
- h2 = h2 + c | 0;
- h3 = h3 + d | 0;
- }
- return new Uint8Array([
- h0 & 0xFF,
- h0 >> 8 & 0xFF,
- h0 >> 16 & 0xFF,
- h0 >>> 24 & 0xFF,
- h1 & 0xFF,
- h1 >> 8 & 0xFF,
- h1 >> 16 & 0xFF,
- h1 >>> 24 & 0xFF,
- h2 & 0xFF,
- h2 >> 8 & 0xFF,
- h2 >> 16 & 0xFF,
- h2 >>> 24 & 0xFF,
- h3 & 0xFF,
- h3 >> 8 & 0xFF,
- h3 >> 16 & 0xFF,
- h3 >>> 24 & 0xFF
- ]);
- }
- return hash;
- }();
- var Word64 = function Word64Closure() {
- function Word64(highInteger, lowInteger) {
- this.high = highInteger | 0;
- this.low = lowInteger | 0;
- }
- Word64.prototype = {
- and: function Word64_and(word) {
- this.high &= word.high;
- this.low &= word.low;
- },
- xor: function Word64_xor(word) {
- this.high ^= word.high;
- this.low ^= word.low;
- },
- or: function Word64_or(word) {
- this.high |= word.high;
- this.low |= word.low;
- },
- shiftRight: function Word64_shiftRight(places) {
- if (places >= 32) {
- this.low = this.high >>> places - 32 | 0;
- this.high = 0;
- } else {
- this.low = this.low >>> places | this.high << 32 - places;
- this.high = this.high >>> places | 0;
- }
- },
- shiftLeft: function Word64_shiftLeft(places) {
- if (places >= 32) {
- this.high = this.low << places - 32;
- this.low = 0;
- } else {
- this.high = this.high << places | this.low >>> 32 - places;
- this.low = this.low << places;
- }
- },
- rotateRight: function Word64_rotateRight(places) {
- var low, high;
- if (places & 32) {
- high = this.low;
- low = this.high;
- } else {
- low = this.low;
- high = this.high;
- }
- places &= 31;
- this.low = low >>> places | high << 32 - places;
- this.high = high >>> places | low << 32 - places;
- },
- not: function Word64_not() {
- this.high = ~this.high;
- this.low = ~this.low;
- },
- add: function Word64_add(word) {
- var lowAdd = (this.low >>> 0) + (word.low >>> 0);
- var highAdd = (this.high >>> 0) + (word.high >>> 0);
- if (lowAdd > 0xFFFFFFFF) {
- highAdd += 1;
- }
- this.low = lowAdd | 0;
- this.high = highAdd | 0;
- },
- copyTo: function Word64_copyTo(bytes, offset) {
- bytes[offset] = this.high >>> 24 & 0xFF;
- bytes[offset + 1] = this.high >> 16 & 0xFF;
- bytes[offset + 2] = this.high >> 8 & 0xFF;
- bytes[offset + 3] = this.high & 0xFF;
- bytes[offset + 4] = this.low >>> 24 & 0xFF;
- bytes[offset + 5] = this.low >> 16 & 0xFF;
- bytes[offset + 6] = this.low >> 8 & 0xFF;
- bytes[offset + 7] = this.low & 0xFF;
- },
- assign: function Word64_assign(word) {
- this.high = word.high;
- this.low = word.low;
- }
- };
- return Word64;
- }();
- var calculateSHA256 = function calculateSHA256Closure() {
- function rotr(x, n) {
- return x >>> n | x << 32 - n;
- }
- function ch(x, y, z) {
- return x & y ^ ~x & z;
- }
- function maj(x, y, z) {
- return x & y ^ x & z ^ y & z;
- }
- function sigma(x) {
- return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);
- }
- function sigmaPrime(x) {
- return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);
- }
- function littleSigma(x) {
- return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3;
- }
- function littleSigmaPrime(x) {
- return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10;
- }
- var k = [
- 0x428a2f98,
- 0x71374491,
- 0xb5c0fbcf,
- 0xe9b5dba5,
- 0x3956c25b,
- 0x59f111f1,
- 0x923f82a4,
- 0xab1c5ed5,
- 0xd807aa98,
- 0x12835b01,
- 0x243185be,
- 0x550c7dc3,
- 0x72be5d74,
- 0x80deb1fe,
- 0x9bdc06a7,
- 0xc19bf174,
- 0xe49b69c1,
- 0xefbe4786,
- 0x0fc19dc6,
- 0x240ca1cc,
- 0x2de92c6f,
- 0x4a7484aa,
- 0x5cb0a9dc,
- 0x76f988da,
- 0x983e5152,
- 0xa831c66d,
- 0xb00327c8,
- 0xbf597fc7,
- 0xc6e00bf3,
- 0xd5a79147,
- 0x06ca6351,
- 0x14292967,
- 0x27b70a85,
- 0x2e1b2138,
- 0x4d2c6dfc,
- 0x53380d13,
- 0x650a7354,
- 0x766a0abb,
- 0x81c2c92e,
- 0x92722c85,
- 0xa2bfe8a1,
- 0xa81a664b,
- 0xc24b8b70,
- 0xc76c51a3,
- 0xd192e819,
- 0xd6990624,
- 0xf40e3585,
- 0x106aa070,
- 0x19a4c116,
- 0x1e376c08,
- 0x2748774c,
- 0x34b0bcb5,
- 0x391c0cb3,
- 0x4ed8aa4a,
- 0x5b9cca4f,
- 0x682e6ff3,
- 0x748f82ee,
- 0x78a5636f,
- 0x84c87814,
- 0x8cc70208,
- 0x90befffa,
- 0xa4506ceb,
- 0xbef9a3f7,
- 0xc67178f2
- ];
- function hash(data, offset, length) {
- // initial hash values
- var h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, h3 = 0xa54ff53a, h4 = 0x510e527f, h5 = 0x9b05688c, h6 = 0x1f83d9ab, h7 = 0x5be0cd19;
- // pre-processing
- var paddedLength = Math.ceil((length + 9) / 64) * 64;
- var padded = new Uint8Array(paddedLength);
- var i, j, n;
- for (i = 0; i < length; ++i) {
- padded[i] = data[offset++];
- }
- padded[i++] = 0x80;
- n = paddedLength - 8;
- while (i < n) {
- padded[i++] = 0;
- }
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = length >>> 29 & 0xFF;
- padded[i++] = length >> 21 & 0xFF;
- padded[i++] = length >> 13 & 0xFF;
- padded[i++] = length >> 5 & 0xFF;
- padded[i++] = length << 3 & 0xFF;
- var w = new Uint32Array(64);
- // for each 512 bit block
- for (i = 0; i < paddedLength;) {
- for (j = 0; j < 16; ++j) {
- w[j] = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3];
- i += 4;
- }
- for (j = 16; j < 64; ++j) {
- w[j] = littleSigmaPrime(w[j - 2]) + w[j - 7] + littleSigma(w[j - 15]) + w[j - 16] | 0;
- }
- var a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7, t1, t2;
- for (j = 0; j < 64; ++j) {
- t1 = h + sigmaPrime(e) + ch(e, f, g) + k[j] + w[j];
- t2 = sigma(a) + maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + t1 | 0;
- d = c;
- c = b;
- b = a;
- a = t1 + t2 | 0;
- }
- h0 = h0 + a | 0;
- h1 = h1 + b | 0;
- h2 = h2 + c | 0;
- h3 = h3 + d | 0;
- h4 = h4 + e | 0;
- h5 = h5 + f | 0;
- h6 = h6 + g | 0;
- h7 = h7 + h | 0;
- }
- return new Uint8Array([
- h0 >> 24 & 0xFF,
- h0 >> 16 & 0xFF,
- h0 >> 8 & 0xFF,
- h0 & 0xFF,
- h1 >> 24 & 0xFF,
- h1 >> 16 & 0xFF,
- h1 >> 8 & 0xFF,
- h1 & 0xFF,
- h2 >> 24 & 0xFF,
- h2 >> 16 & 0xFF,
- h2 >> 8 & 0xFF,
- h2 & 0xFF,
- h3 >> 24 & 0xFF,
- h3 >> 16 & 0xFF,
- h3 >> 8 & 0xFF,
- h3 & 0xFF,
- h4 >> 24 & 0xFF,
- h4 >> 16 & 0xFF,
- h4 >> 8 & 0xFF,
- h4 & 0xFF,
- h5 >> 24 & 0xFF,
- h5 >> 16 & 0xFF,
- h5 >> 8 & 0xFF,
- h5 & 0xFF,
- h6 >> 24 & 0xFF,
- h6 >> 16 & 0xFF,
- h6 >> 8 & 0xFF,
- h6 & 0xFF,
- h7 >> 24 & 0xFF,
- h7 >> 16 & 0xFF,
- h7 >> 8 & 0xFF,
- h7 & 0xFF
- ]);
- }
- return hash;
- }();
- var calculateSHA512 = function calculateSHA512Closure() {
- function ch(result, x, y, z, tmp) {
- result.assign(x);
- result.and(y);
- tmp.assign(x);
- tmp.not();
- tmp.and(z);
- result.xor(tmp);
- }
- function maj(result, x, y, z, tmp) {
- result.assign(x);
- result.and(y);
- tmp.assign(x);
- tmp.and(z);
- result.xor(tmp);
- tmp.assign(y);
- tmp.and(z);
- result.xor(tmp);
- }
- function sigma(result, x, tmp) {
- result.assign(x);
- result.rotateRight(28);
- tmp.assign(x);
- tmp.rotateRight(34);
- result.xor(tmp);
- tmp.assign(x);
- tmp.rotateRight(39);
- result.xor(tmp);
- }
- function sigmaPrime(result, x, tmp) {
- result.assign(x);
- result.rotateRight(14);
- tmp.assign(x);
- tmp.rotateRight(18);
- result.xor(tmp);
- tmp.assign(x);
- tmp.rotateRight(41);
- result.xor(tmp);
- }
- function littleSigma(result, x, tmp) {
- result.assign(x);
- result.rotateRight(1);
- tmp.assign(x);
- tmp.rotateRight(8);
- result.xor(tmp);
- tmp.assign(x);
- tmp.shiftRight(7);
- result.xor(tmp);
- }
- function littleSigmaPrime(result, x, tmp) {
- result.assign(x);
- result.rotateRight(19);
- tmp.assign(x);
- tmp.rotateRight(61);
- result.xor(tmp);
- tmp.assign(x);
- tmp.shiftRight(6);
- result.xor(tmp);
- }
- var k = [
- new Word64(0x428a2f98, 0xd728ae22),
- new Word64(0x71374491, 0x23ef65cd),
- new Word64(0xb5c0fbcf, 0xec4d3b2f),
- new Word64(0xe9b5dba5, 0x8189dbbc),
- new Word64(0x3956c25b, 0xf348b538),
- new Word64(0x59f111f1, 0xb605d019),
- new Word64(0x923f82a4, 0xaf194f9b),
- new Word64(0xab1c5ed5, 0xda6d8118),
- new Word64(0xd807aa98, 0xa3030242),
- new Word64(0x12835b01, 0x45706fbe),
- new Word64(0x243185be, 0x4ee4b28c),
- new Word64(0x550c7dc3, 0xd5ffb4e2),
- new Word64(0x72be5d74, 0xf27b896f),
- new Word64(0x80deb1fe, 0x3b1696b1),
- new Word64(0x9bdc06a7, 0x25c71235),
- new Word64(0xc19bf174, 0xcf692694),
- new Word64(0xe49b69c1, 0x9ef14ad2),
- new Word64(0xefbe4786, 0x384f25e3),
- new Word64(0x0fc19dc6, 0x8b8cd5b5),
- new Word64(0x240ca1cc, 0x77ac9c65),
- new Word64(0x2de92c6f, 0x592b0275),
- new Word64(0x4a7484aa, 0x6ea6e483),
- new Word64(0x5cb0a9dc, 0xbd41fbd4),
- new Word64(0x76f988da, 0x831153b5),
- new Word64(0x983e5152, 0xee66dfab),
- new Word64(0xa831c66d, 0x2db43210),
- new Word64(0xb00327c8, 0x98fb213f),
- new Word64(0xbf597fc7, 0xbeef0ee4),
- new Word64(0xc6e00bf3, 0x3da88fc2),
- new Word64(0xd5a79147, 0x930aa725),
- new Word64(0x06ca6351, 0xe003826f),
- new Word64(0x14292967, 0x0a0e6e70),
- new Word64(0x27b70a85, 0x46d22ffc),
- new Word64(0x2e1b2138, 0x5c26c926),
- new Word64(0x4d2c6dfc, 0x5ac42aed),
- new Word64(0x53380d13, 0x9d95b3df),
- new Word64(0x650a7354, 0x8baf63de),
- new Word64(0x766a0abb, 0x3c77b2a8),
- new Word64(0x81c2c92e, 0x47edaee6),
- new Word64(0x92722c85, 0x1482353b),
- new Word64(0xa2bfe8a1, 0x4cf10364),
- new Word64(0xa81a664b, 0xbc423001),
- new Word64(0xc24b8b70, 0xd0f89791),
- new Word64(0xc76c51a3, 0x0654be30),
- new Word64(0xd192e819, 0xd6ef5218),
- new Word64(0xd6990624, 0x5565a910),
- new Word64(0xf40e3585, 0x5771202a),
- new Word64(0x106aa070, 0x32bbd1b8),
- new Word64(0x19a4c116, 0xb8d2d0c8),
- new Word64(0x1e376c08, 0x5141ab53),
- new Word64(0x2748774c, 0xdf8eeb99),
- new Word64(0x34b0bcb5, 0xe19b48a8),
- new Word64(0x391c0cb3, 0xc5c95a63),
- new Word64(0x4ed8aa4a, 0xe3418acb),
- new Word64(0x5b9cca4f, 0x7763e373),
- new Word64(0x682e6ff3, 0xd6b2b8a3),
- new Word64(0x748f82ee, 0x5defb2fc),
- new Word64(0x78a5636f, 0x43172f60),
- new Word64(0x84c87814, 0xa1f0ab72),
- new Word64(0x8cc70208, 0x1a6439ec),
- new Word64(0x90befffa, 0x23631e28),
- new Word64(0xa4506ceb, 0xde82bde9),
- new Word64(0xbef9a3f7, 0xb2c67915),
- new Word64(0xc67178f2, 0xe372532b),
- new Word64(0xca273ece, 0xea26619c),
- new Word64(0xd186b8c7, 0x21c0c207),
- new Word64(0xeada7dd6, 0xcde0eb1e),
- new Word64(0xf57d4f7f, 0xee6ed178),
- new Word64(0x06f067aa, 0x72176fba),
- new Word64(0x0a637dc5, 0xa2c898a6),
- new Word64(0x113f9804, 0xbef90dae),
- new Word64(0x1b710b35, 0x131c471b),
- new Word64(0x28db77f5, 0x23047d84),
- new Word64(0x32caab7b, 0x40c72493),
- new Word64(0x3c9ebe0a, 0x15c9bebc),
- new Word64(0x431d67c4, 0x9c100d4c),
- new Word64(0x4cc5d4be, 0xcb3e42b6),
- new Word64(0x597f299c, 0xfc657e2a),
- new Word64(0x5fcb6fab, 0x3ad6faec),
- new Word64(0x6c44198c, 0x4a475817)
- ];
- function hash(data, offset, length, mode384) {
- mode384 = !!mode384;
- // initial hash values
- var h0, h1, h2, h3, h4, h5, h6, h7;
- if (!mode384) {
- h0 = new Word64(0x6a09e667, 0xf3bcc908);
- h1 = new Word64(0xbb67ae85, 0x84caa73b);
- h2 = new Word64(0x3c6ef372, 0xfe94f82b);
- h3 = new Word64(0xa54ff53a, 0x5f1d36f1);
- h4 = new Word64(0x510e527f, 0xade682d1);
- h5 = new Word64(0x9b05688c, 0x2b3e6c1f);
- h6 = new Word64(0x1f83d9ab, 0xfb41bd6b);
- h7 = new Word64(0x5be0cd19, 0x137e2179);
- } else {
- // SHA384 is exactly the same
- // except with different starting values and a trimmed result
- h0 = new Word64(0xcbbb9d5d, 0xc1059ed8);
- h1 = new Word64(0x629a292a, 0x367cd507);
- h2 = new Word64(0x9159015a, 0x3070dd17);
- h3 = new Word64(0x152fecd8, 0xf70e5939);
- h4 = new Word64(0x67332667, 0xffc00b31);
- h5 = new Word64(0x8eb44a87, 0x68581511);
- h6 = new Word64(0xdb0c2e0d, 0x64f98fa7);
- h7 = new Word64(0x47b5481d, 0xbefa4fa4);
- }
- // pre-processing
- var paddedLength = Math.ceil((length + 17) / 128) * 128;
- var padded = new Uint8Array(paddedLength);
- var i, j, n;
- for (i = 0; i < length; ++i) {
- padded[i] = data[offset++];
- }
- padded[i++] = 0x80;
- n = paddedLength - 16;
- while (i < n) {
- padded[i++] = 0;
- }
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = length >>> 29 & 0xFF;
- padded[i++] = length >> 21 & 0xFF;
- padded[i++] = length >> 13 & 0xFF;
- padded[i++] = length >> 5 & 0xFF;
- padded[i++] = length << 3 & 0xFF;
- var w = new Array(80);
- for (i = 0; i < 80; i++) {
- w[i] = new Word64(0, 0);
- }
- var a = new Word64(0, 0), b = new Word64(0, 0), c = new Word64(0, 0);
- var d = new Word64(0, 0), e = new Word64(0, 0), f = new Word64(0, 0);
- var g = new Word64(0, 0), h = new Word64(0, 0);
- var t1 = new Word64(0, 0), t2 = new Word64(0, 0);
- var tmp1 = new Word64(0, 0), tmp2 = new Word64(0, 0), tmp3;
- // for each 1024 bit block
- for (i = 0; i < paddedLength;) {
- for (j = 0; j < 16; ++j) {
- w[j].high = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3];
- w[j].low = padded[i + 4] << 24 | padded[i + 5] << 16 | padded[i + 6] << 8 | padded[i + 7];
- i += 8;
- }
- for (j = 16; j < 80; ++j) {
- tmp3 = w[j];
- littleSigmaPrime(tmp3, w[j - 2], tmp2);
- tmp3.add(w[j - 7]);
- littleSigma(tmp1, w[j - 15], tmp2);
- tmp3.add(tmp1);
- tmp3.add(w[j - 16]);
- }
- a.assign(h0);
- b.assign(h1);
- c.assign(h2);
- d.assign(h3);
- e.assign(h4);
- f.assign(h5);
- g.assign(h6);
- h.assign(h7);
- for (j = 0; j < 80; ++j) {
- t1.assign(h);
- sigmaPrime(tmp1, e, tmp2);
- t1.add(tmp1);
- ch(tmp1, e, f, g, tmp2);
- t1.add(tmp1);
- t1.add(k[j]);
- t1.add(w[j]);
- sigma(t2, a, tmp2);
- maj(tmp1, a, b, c, tmp2);
- t2.add(tmp1);
- tmp3 = h;
- h = g;
- g = f;
- f = e;
- d.add(t1);
- e = d;
- d = c;
- c = b;
- b = a;
- tmp3.assign(t1);
- tmp3.add(t2);
- a = tmp3;
- }
- h0.add(a);
- h1.add(b);
- h2.add(c);
- h3.add(d);
- h4.add(e);
- h5.add(f);
- h6.add(g);
- h7.add(h);
- }
- var result;
- if (!mode384) {
- result = new Uint8Array(64);
- h0.copyTo(result, 0);
- h1.copyTo(result, 8);
- h2.copyTo(result, 16);
- h3.copyTo(result, 24);
- h4.copyTo(result, 32);
- h5.copyTo(result, 40);
- h6.copyTo(result, 48);
- h7.copyTo(result, 56);
- } else {
- result = new Uint8Array(48);
- h0.copyTo(result, 0);
- h1.copyTo(result, 8);
- h2.copyTo(result, 16);
- h3.copyTo(result, 24);
- h4.copyTo(result, 32);
- h5.copyTo(result, 40);
- }
- return result;
- }
- return hash;
- }();
- var calculateSHA384 = function calculateSHA384Closure() {
- function hash(data, offset, length) {
- return calculateSHA512(data, offset, length, true);
- }
- return hash;
- }();
- var NullCipher = function NullCipherClosure() {
- function NullCipher() {
- }
- NullCipher.prototype = {
- decryptBlock: function NullCipher_decryptBlock(data) {
- return data;
- }
- };
- return NullCipher;
- }();
- var AES128Cipher = function AES128CipherClosure() {
- var rcon = new Uint8Array([
- 0x8d,
- 0x01,
- 0x02,
- 0x04,
- 0x08,
- 0x10,
- 0x20,
- 0x40,
- 0x80,
- 0x1b,
- 0x36,
- 0x6c,
- 0xd8,
- 0xab,
- 0x4d,
- 0x9a,
- 0x2f,
- 0x5e,
- 0xbc,
- 0x63,
- 0xc6,
- 0x97,
- 0x35,
- 0x6a,
- 0xd4,
- 0xb3,
- 0x7d,
- 0xfa,
- 0xef,
- 0xc5,
- 0x91,
- 0x39,
- 0x72,
- 0xe4,
- 0xd3,
- 0xbd,
- 0x61,
- 0xc2,
- 0x9f,
- 0x25,
- 0x4a,
- 0x94,
- 0x33,
- 0x66,
- 0xcc,
- 0x83,
- 0x1d,
- 0x3a,
- 0x74,
- 0xe8,
- 0xcb,
- 0x8d,
- 0x01,
- 0x02,
- 0x04,
- 0x08,
- 0x10,
- 0x20,
- 0x40,
- 0x80,
- 0x1b,
- 0x36,
- 0x6c,
- 0xd8,
- 0xab,
- 0x4d,
- 0x9a,
- 0x2f,
- 0x5e,
- 0xbc,
- 0x63,
- 0xc6,
- 0x97,
- 0x35,
- 0x6a,
- 0xd4,
- 0xb3,
- 0x7d,
- 0xfa,
- 0xef,
- 0xc5,
- 0x91,
- 0x39,
- 0x72,
- 0xe4,
- 0xd3,
- 0xbd,
- 0x61,
- 0xc2,
- 0x9f,
- 0x25,
- 0x4a,
- 0x94,
- 0x33,
- 0x66,
- 0xcc,
- 0x83,
- 0x1d,
- 0x3a,
- 0x74,
- 0xe8,
- 0xcb,
- 0x8d,
- 0x01,
- 0x02,
- 0x04,
- 0x08,
- 0x10,
- 0x20,
- 0x40,
- 0x80,
- 0x1b,
- 0x36,
- 0x6c,
- 0xd8,
- 0xab,
- 0x4d,
- 0x9a,
- 0x2f,
- 0x5e,
- 0xbc,
- 0x63,
- 0xc6,
- 0x97,
- 0x35,
- 0x6a,
- 0xd4,
- 0xb3,
- 0x7d,
- 0xfa,
- 0xef,
- 0xc5,
- 0x91,
- 0x39,
- 0x72,
- 0xe4,
- 0xd3,
- 0xbd,
- 0x61,
- 0xc2,
- 0x9f,
- 0x25,
- 0x4a,
- 0x94,
- 0x33,
- 0x66,
- 0xcc,
- 0x83,
- 0x1d,
- 0x3a,
- 0x74,
- 0xe8,
- 0xcb,
- 0x8d,
- 0x01,
- 0x02,
- 0x04,
- 0x08,
- 0x10,
- 0x20,
- 0x40,
- 0x80,
- 0x1b,
- 0x36,
- 0x6c,
- 0xd8,
- 0xab,
- 0x4d,
- 0x9a,
- 0x2f,
- 0x5e,
- 0xbc,
- 0x63,
- 0xc6,
- 0x97,
- 0x35,
- 0x6a,
- 0xd4,
- 0xb3,
- 0x7d,
- 0xfa,
- 0xef,
- 0xc5,
- 0x91,
- 0x39,
- 0x72,
- 0xe4,
- 0xd3,
- 0xbd,
- 0x61,
- 0xc2,
- 0x9f,
- 0x25,
- 0x4a,
- 0x94,
- 0x33,
- 0x66,
- 0xcc,
- 0x83,
- 0x1d,
- 0x3a,
- 0x74,
- 0xe8,
- 0xcb,
- 0x8d,
- 0x01,
- 0x02,
- 0x04,
- 0x08,
- 0x10,
- 0x20,
- 0x40,
- 0x80,
- 0x1b,
- 0x36,
- 0x6c,
- 0xd8,
- 0xab,
- 0x4d,
- 0x9a,
- 0x2f,
- 0x5e,
- 0xbc,
- 0x63,
- 0xc6,
- 0x97,
- 0x35,
- 0x6a,
- 0xd4,
- 0xb3,
- 0x7d,
- 0xfa,
- 0xef,
- 0xc5,
- 0x91,
- 0x39,
- 0x72,
- 0xe4,
- 0xd3,
- 0xbd,
- 0x61,
- 0xc2,
- 0x9f,
- 0x25,
- 0x4a,
- 0x94,
- 0x33,
- 0x66,
- 0xcc,
- 0x83,
- 0x1d,
- 0x3a,
- 0x74,
- 0xe8,
- 0xcb,
- 0x8d
- ]);
- var s = new Uint8Array([
- 0x63,
- 0x7c,
- 0x77,
- 0x7b,
- 0xf2,
- 0x6b,
- 0x6f,
- 0xc5,
- 0x30,
- 0x01,
- 0x67,
- 0x2b,
- 0xfe,
- 0xd7,
- 0xab,
- 0x76,
- 0xca,
- 0x82,
- 0xc9,
- 0x7d,
- 0xfa,
- 0x59,
- 0x47,
- 0xf0,
- 0xad,
- 0xd4,
- 0xa2,
- 0xaf,
- 0x9c,
- 0xa4,
- 0x72,
- 0xc0,
- 0xb7,
- 0xfd,
- 0x93,
- 0x26,
- 0x36,
- 0x3f,
- 0xf7,
- 0xcc,
- 0x34,
- 0xa5,
- 0xe5,
- 0xf1,
- 0x71,
- 0xd8,
- 0x31,
- 0x15,
- 0x04,
- 0xc7,
- 0x23,
- 0xc3,
- 0x18,
- 0x96,
- 0x05,
- 0x9a,
- 0x07,
- 0x12,
- 0x80,
- 0xe2,
- 0xeb,
- 0x27,
- 0xb2,
- 0x75,
- 0x09,
- 0x83,
- 0x2c,
- 0x1a,
- 0x1b,
- 0x6e,
- 0x5a,
- 0xa0,
- 0x52,
- 0x3b,
- 0xd6,
- 0xb3,
- 0x29,
- 0xe3,
- 0x2f,
- 0x84,
- 0x53,
- 0xd1,
- 0x00,
- 0xed,
- 0x20,
- 0xfc,
- 0xb1,
- 0x5b,
- 0x6a,
- 0xcb,
- 0xbe,
- 0x39,
- 0x4a,
- 0x4c,
- 0x58,
- 0xcf,
- 0xd0,
- 0xef,
- 0xaa,
- 0xfb,
- 0x43,
- 0x4d,
- 0x33,
- 0x85,
- 0x45,
- 0xf9,
- 0x02,
- 0x7f,
- 0x50,
- 0x3c,
- 0x9f,
- 0xa8,
- 0x51,
- 0xa3,
- 0x40,
- 0x8f,
- 0x92,
- 0x9d,
- 0x38,
- 0xf5,
- 0xbc,
- 0xb6,
- 0xda,
- 0x21,
- 0x10,
- 0xff,
- 0xf3,
- 0xd2,
- 0xcd,
- 0x0c,
- 0x13,
- 0xec,
- 0x5f,
- 0x97,
- 0x44,
- 0x17,
- 0xc4,
- 0xa7,
- 0x7e,
- 0x3d,
- 0x64,
- 0x5d,
- 0x19,
- 0x73,
- 0x60,
- 0x81,
- 0x4f,
- 0xdc,
- 0x22,
- 0x2a,
- 0x90,
- 0x88,
- 0x46,
- 0xee,
- 0xb8,
- 0x14,
- 0xde,
- 0x5e,
- 0x0b,
- 0xdb,
- 0xe0,
- 0x32,
- 0x3a,
- 0x0a,
- 0x49,
- 0x06,
- 0x24,
- 0x5c,
- 0xc2,
- 0xd3,
- 0xac,
- 0x62,
- 0x91,
- 0x95,
- 0xe4,
- 0x79,
- 0xe7,
- 0xc8,
- 0x37,
- 0x6d,
- 0x8d,
- 0xd5,
- 0x4e,
- 0xa9,
- 0x6c,
- 0x56,
- 0xf4,
- 0xea,
- 0x65,
- 0x7a,
- 0xae,
- 0x08,
- 0xba,
- 0x78,
- 0x25,
- 0x2e,
- 0x1c,
- 0xa6,
- 0xb4,
- 0xc6,
- 0xe8,
- 0xdd,
- 0x74,
- 0x1f,
- 0x4b,
- 0xbd,
- 0x8b,
- 0x8a,
- 0x70,
- 0x3e,
- 0xb5,
- 0x66,
- 0x48,
- 0x03,
- 0xf6,
- 0x0e,
- 0x61,
- 0x35,
- 0x57,
- 0xb9,
- 0x86,
- 0xc1,
- 0x1d,
- 0x9e,
- 0xe1,
- 0xf8,
- 0x98,
- 0x11,
- 0x69,
- 0xd9,
- 0x8e,
- 0x94,
- 0x9b,
- 0x1e,
- 0x87,
- 0xe9,
- 0xce,
- 0x55,
- 0x28,
- 0xdf,
- 0x8c,
- 0xa1,
- 0x89,
- 0x0d,
- 0xbf,
- 0xe6,
- 0x42,
- 0x68,
- 0x41,
- 0x99,
- 0x2d,
- 0x0f,
- 0xb0,
- 0x54,
- 0xbb,
- 0x16
- ]);
- var inv_s = new Uint8Array([
- 0x52,
- 0x09,
- 0x6a,
- 0xd5,
- 0x30,
- 0x36,
- 0xa5,
- 0x38,
- 0xbf,
- 0x40,
- 0xa3,
- 0x9e,
- 0x81,
- 0xf3,
- 0xd7,
- 0xfb,
- 0x7c,
- 0xe3,
- 0x39,
- 0x82,
- 0x9b,
- 0x2f,
- 0xff,
- 0x87,
- 0x34,
- 0x8e,
- 0x43,
- 0x44,
- 0xc4,
- 0xde,
- 0xe9,
- 0xcb,
- 0x54,
- 0x7b,
- 0x94,
- 0x32,
- 0xa6,
- 0xc2,
- 0x23,
- 0x3d,
- 0xee,
- 0x4c,
- 0x95,
- 0x0b,
- 0x42,
- 0xfa,
- 0xc3,
- 0x4e,
- 0x08,
- 0x2e,
- 0xa1,
- 0x66,
- 0x28,
- 0xd9,
- 0x24,
- 0xb2,
- 0x76,
- 0x5b,
- 0xa2,
- 0x49,
- 0x6d,
- 0x8b,
- 0xd1,
- 0x25,
- 0x72,
- 0xf8,
- 0xf6,
- 0x64,
- 0x86,
- 0x68,
- 0x98,
- 0x16,
- 0xd4,
- 0xa4,
- 0x5c,
- 0xcc,
- 0x5d,
- 0x65,
- 0xb6,
- 0x92,
- 0x6c,
- 0x70,
- 0x48,
- 0x50,
- 0xfd,
- 0xed,
- 0xb9,
- 0xda,
- 0x5e,
- 0x15,
- 0x46,
- 0x57,
- 0xa7,
- 0x8d,
- 0x9d,
- 0x84,
- 0x90,
- 0xd8,
- 0xab,
- 0x00,
- 0x8c,
- 0xbc,
- 0xd3,
- 0x0a,
- 0xf7,
- 0xe4,
- 0x58,
- 0x05,
- 0xb8,
- 0xb3,
- 0x45,
- 0x06,
- 0xd0,
- 0x2c,
- 0x1e,
- 0x8f,
- 0xca,
- 0x3f,
- 0x0f,
- 0x02,
- 0xc1,
- 0xaf,
- 0xbd,
- 0x03,
- 0x01,
- 0x13,
- 0x8a,
- 0x6b,
- 0x3a,
- 0x91,
- 0x11,
- 0x41,
- 0x4f,
- 0x67,
- 0xdc,
- 0xea,
- 0x97,
- 0xf2,
- 0xcf,
- 0xce,
- 0xf0,
- 0xb4,
- 0xe6,
- 0x73,
- 0x96,
- 0xac,
- 0x74,
- 0x22,
- 0xe7,
- 0xad,
- 0x35,
- 0x85,
- 0xe2,
- 0xf9,
- 0x37,
- 0xe8,
- 0x1c,
- 0x75,
- 0xdf,
- 0x6e,
- 0x47,
- 0xf1,
- 0x1a,
- 0x71,
- 0x1d,
- 0x29,
- 0xc5,
- 0x89,
- 0x6f,
- 0xb7,
- 0x62,
- 0x0e,
- 0xaa,
- 0x18,
- 0xbe,
- 0x1b,
- 0xfc,
- 0x56,
- 0x3e,
- 0x4b,
- 0xc6,
- 0xd2,
- 0x79,
- 0x20,
- 0x9a,
- 0xdb,
- 0xc0,
- 0xfe,
- 0x78,
- 0xcd,
- 0x5a,
- 0xf4,
- 0x1f,
- 0xdd,
- 0xa8,
- 0x33,
- 0x88,
- 0x07,
- 0xc7,
- 0x31,
- 0xb1,
- 0x12,
- 0x10,
- 0x59,
- 0x27,
- 0x80,
- 0xec,
- 0x5f,
- 0x60,
- 0x51,
- 0x7f,
- 0xa9,
- 0x19,
- 0xb5,
- 0x4a,
- 0x0d,
- 0x2d,
- 0xe5,
- 0x7a,
- 0x9f,
- 0x93,
- 0xc9,
- 0x9c,
- 0xef,
- 0xa0,
- 0xe0,
- 0x3b,
- 0x4d,
- 0xae,
- 0x2a,
- 0xf5,
- 0xb0,
- 0xc8,
- 0xeb,
- 0xbb,
- 0x3c,
- 0x83,
- 0x53,
- 0x99,
- 0x61,
- 0x17,
- 0x2b,
- 0x04,
- 0x7e,
- 0xba,
- 0x77,
- 0xd6,
- 0x26,
- 0xe1,
- 0x69,
- 0x14,
- 0x63,
- 0x55,
- 0x21,
- 0x0c,
- 0x7d
- ]);
- var mixCol = new Uint8Array(256);
- for (var i = 0; i < 256; i++) {
- if (i < 128) {
- mixCol[i] = i << 1;
- } else {
- mixCol[i] = i << 1 ^ 0x1b;
- }
- }
- var mix = new Uint32Array([
- 0x00000000,
- 0x0e090d0b,
- 0x1c121a16,
- 0x121b171d,
- 0x3824342c,
- 0x362d3927,
- 0x24362e3a,
- 0x2a3f2331,
- 0x70486858,
- 0x7e416553,
- 0x6c5a724e,
- 0x62537f45,
- 0x486c5c74,
- 0x4665517f,
- 0x547e4662,
- 0x5a774b69,
- 0xe090d0b0,
- 0xee99ddbb,
- 0xfc82caa6,
- 0xf28bc7ad,
- 0xd8b4e49c,
- 0xd6bde997,
- 0xc4a6fe8a,
- 0xcaaff381,
- 0x90d8b8e8,
- 0x9ed1b5e3,
- 0x8ccaa2fe,
- 0x82c3aff5,
- 0xa8fc8cc4,
- 0xa6f581cf,
- 0xb4ee96d2,
- 0xbae79bd9,
- 0xdb3bbb7b,
- 0xd532b670,
- 0xc729a16d,
- 0xc920ac66,
- 0xe31f8f57,
- 0xed16825c,
- 0xff0d9541,
- 0xf104984a,
- 0xab73d323,
- 0xa57ade28,
- 0xb761c935,
- 0xb968c43e,
- 0x9357e70f,
- 0x9d5eea04,
- 0x8f45fd19,
- 0x814cf012,
- 0x3bab6bcb,
- 0x35a266c0,
- 0x27b971dd,
- 0x29b07cd6,
- 0x038f5fe7,
- 0x0d8652ec,
- 0x1f9d45f1,
- 0x119448fa,
- 0x4be30393,
- 0x45ea0e98,
- 0x57f11985,
- 0x59f8148e,
- 0x73c737bf,
- 0x7dce3ab4,
- 0x6fd52da9,
- 0x61dc20a2,
- 0xad766df6,
- 0xa37f60fd,
- 0xb16477e0,
- 0xbf6d7aeb,
- 0x955259da,
- 0x9b5b54d1,
- 0x894043cc,
- 0x87494ec7,
- 0xdd3e05ae,
- 0xd33708a5,
- 0xc12c1fb8,
- 0xcf2512b3,
- 0xe51a3182,
- 0xeb133c89,
- 0xf9082b94,
- 0xf701269f,
- 0x4de6bd46,
- 0x43efb04d,
- 0x51f4a750,
- 0x5ffdaa5b,
- 0x75c2896a,
- 0x7bcb8461,
- 0x69d0937c,
- 0x67d99e77,
- 0x3daed51e,
- 0x33a7d815,
- 0x21bccf08,
- 0x2fb5c203,
- 0x058ae132,
- 0x0b83ec39,
- 0x1998fb24,
- 0x1791f62f,
- 0x764dd68d,
- 0x7844db86,
- 0x6a5fcc9b,
- 0x6456c190,
- 0x4e69e2a1,
- 0x4060efaa,
- 0x527bf8b7,
- 0x5c72f5bc,
- 0x0605bed5,
- 0x080cb3de,
- 0x1a17a4c3,
- 0x141ea9c8,
- 0x3e218af9,
- 0x302887f2,
- 0x223390ef,
- 0x2c3a9de4,
- 0x96dd063d,
- 0x98d40b36,
- 0x8acf1c2b,
- 0x84c61120,
- 0xaef93211,
- 0xa0f03f1a,
- 0xb2eb2807,
- 0xbce2250c,
- 0xe6956e65,
- 0xe89c636e,
- 0xfa877473,
- 0xf48e7978,
- 0xdeb15a49,
- 0xd0b85742,
- 0xc2a3405f,
- 0xccaa4d54,
- 0x41ecdaf7,
- 0x4fe5d7fc,
- 0x5dfec0e1,
- 0x53f7cdea,
- 0x79c8eedb,
- 0x77c1e3d0,
- 0x65daf4cd,
- 0x6bd3f9c6,
- 0x31a4b2af,
- 0x3fadbfa4,
- 0x2db6a8b9,
- 0x23bfa5b2,
- 0x09808683,
- 0x07898b88,
- 0x15929c95,
- 0x1b9b919e,
- 0xa17c0a47,
- 0xaf75074c,
- 0xbd6e1051,
- 0xb3671d5a,
- 0x99583e6b,
- 0x97513360,
- 0x854a247d,
- 0x8b432976,
- 0xd134621f,
- 0xdf3d6f14,
- 0xcd267809,
- 0xc32f7502,
- 0xe9105633,
- 0xe7195b38,
- 0xf5024c25,
- 0xfb0b412e,
- 0x9ad7618c,
- 0x94de6c87,
- 0x86c57b9a,
- 0x88cc7691,
- 0xa2f355a0,
- 0xacfa58ab,
- 0xbee14fb6,
- 0xb0e842bd,
- 0xea9f09d4,
- 0xe49604df,
- 0xf68d13c2,
- 0xf8841ec9,
- 0xd2bb3df8,
- 0xdcb230f3,
- 0xcea927ee,
- 0xc0a02ae5,
- 0x7a47b13c,
- 0x744ebc37,
- 0x6655ab2a,
- 0x685ca621,
- 0x42638510,
- 0x4c6a881b,
- 0x5e719f06,
- 0x5078920d,
- 0x0a0fd964,
- 0x0406d46f,
- 0x161dc372,
- 0x1814ce79,
- 0x322bed48,
- 0x3c22e043,
- 0x2e39f75e,
- 0x2030fa55,
- 0xec9ab701,
- 0xe293ba0a,
- 0xf088ad17,
- 0xfe81a01c,
- 0xd4be832d,
- 0xdab78e26,
- 0xc8ac993b,
- 0xc6a59430,
- 0x9cd2df59,
- 0x92dbd252,
- 0x80c0c54f,
- 0x8ec9c844,
- 0xa4f6eb75,
- 0xaaffe67e,
- 0xb8e4f163,
- 0xb6edfc68,
- 0x0c0a67b1,
- 0x02036aba,
- 0x10187da7,
- 0x1e1170ac,
- 0x342e539d,
- 0x3a275e96,
- 0x283c498b,
- 0x26354480,
- 0x7c420fe9,
- 0x724b02e2,
- 0x605015ff,
- 0x6e5918f4,
- 0x44663bc5,
- 0x4a6f36ce,
- 0x587421d3,
- 0x567d2cd8,
- 0x37a10c7a,
- 0x39a80171,
- 0x2bb3166c,
- 0x25ba1b67,
- 0x0f853856,
- 0x018c355d,
- 0x13972240,
- 0x1d9e2f4b,
- 0x47e96422,
- 0x49e06929,
- 0x5bfb7e34,
- 0x55f2733f,
- 0x7fcd500e,
- 0x71c45d05,
- 0x63df4a18,
- 0x6dd64713,
- 0xd731dcca,
- 0xd938d1c1,
- 0xcb23c6dc,
- 0xc52acbd7,
- 0xef15e8e6,
- 0xe11ce5ed,
- 0xf307f2f0,
- 0xfd0efffb,
- 0xa779b492,
- 0xa970b999,
- 0xbb6bae84,
- 0xb562a38f,
- 0x9f5d80be,
- 0x91548db5,
- 0x834f9aa8,
- 0x8d4697a3
- ]);
- function expandKey128(cipherKey) {
- var b = 176, result = new Uint8Array(b);
- result.set(cipherKey);
- for (var j = 16, i = 1; j < b; ++i) {
- // RotWord
- var t1 = result[j - 3], t2 = result[j - 2], t3 = result[j - 1], t4 = result[j - 4];
- // SubWord
- t1 = s[t1];
- t2 = s[t2];
- t3 = s[t3];
- t4 = s[t4];
- // Rcon
- t1 = t1 ^ rcon[i];
- for (var n = 0; n < 4; ++n) {
- result[j] = t1 ^= result[j - 16];
- j++;
- result[j] = t2 ^= result[j - 16];
- j++;
- result[j] = t3 ^= result[j - 16];
- j++;
- result[j] = t4 ^= result[j - 16];
- j++;
- }
- }
- return result;
- }
- function decrypt128(input, key) {
- var state = new Uint8Array(16);
- state.set(input);
- var i, j, k;
- var t, u, v;
- // AddRoundKey
- for (j = 0, k = 160; j < 16; ++j, ++k) {
- state[j] ^= key[k];
- }
- for (i = 9; i >= 1; --i) {
- // InvShiftRows
- t = state[13];
- state[13] = state[9];
- state[9] = state[5];
- state[5] = state[1];
- state[1] = t;
- t = state[14];
- u = state[10];
- state[14] = state[6];
- state[10] = state[2];
- state[6] = t;
- state[2] = u;
- t = state[15];
- u = state[11];
- v = state[7];
- state[15] = state[3];
- state[11] = t;
- state[7] = u;
- state[3] = v;
- // InvSubBytes
- for (j = 0; j < 16; ++j) {
- state[j] = inv_s[state[j]];
- }
- // AddRoundKey
- for (j = 0, k = i * 16; j < 16; ++j, ++k) {
- state[j] ^= key[k];
- }
- // InvMixColumns
- for (j = 0; j < 16; j += 4) {
- var s0 = mix[state[j]], s1 = mix[state[j + 1]], s2 = mix[state[j + 2]], s3 = mix[state[j + 3]];
- t = s0 ^ s1 >>> 8 ^ s1 << 24 ^ s2 >>> 16 ^ s2 << 16 ^ s3 >>> 24 ^ s3 << 8;
- state[j] = t >>> 24 & 0xFF;
- state[j + 1] = t >> 16 & 0xFF;
- state[j + 2] = t >> 8 & 0xFF;
- state[j + 3] = t & 0xFF;
- }
- }
- // InvShiftRows
- t = state[13];
- state[13] = state[9];
- state[9] = state[5];
- state[5] = state[1];
- state[1] = t;
- t = state[14];
- u = state[10];
- state[14] = state[6];
- state[10] = state[2];
- state[6] = t;
- state[2] = u;
- t = state[15];
- u = state[11];
- v = state[7];
- state[15] = state[3];
- state[11] = t;
- state[7] = u;
- state[3] = v;
- for (j = 0; j < 16; ++j) {
- // InvSubBytes
- state[j] = inv_s[state[j]];
- // AddRoundKey
- state[j] ^= key[j];
- }
- return state;
- }
- function encrypt128(input, key) {
- var t, u, v, k;
- var state = new Uint8Array(16);
- state.set(input);
- for (j = 0; j < 16; ++j) {
- // AddRoundKey
- state[j] ^= key[j];
- }
- for (i = 1; i < 10; i++) {
- //SubBytes
- for (j = 0; j < 16; ++j) {
- state[j] = s[state[j]];
- }
- //ShiftRows
- v = state[1];
- state[1] = state[5];
- state[5] = state[9];
- state[9] = state[13];
- state[13] = v;
- v = state[2];
- u = state[6];
- state[2] = state[10];
- state[6] = state[14];
- state[10] = v;
- state[14] = u;
- v = state[3];
- u = state[7];
- t = state[11];
- state[3] = state[15];
- state[7] = v;
- state[11] = u;
- state[15] = t;
- //MixColumns
- for (var j = 0; j < 16; j += 4) {
- var s0 = state[j + 0], s1 = state[j + 1];
- var s2 = state[j + 2], s3 = state[j + 3];
- t = s0 ^ s1 ^ s2 ^ s3;
- state[j + 0] ^= t ^ mixCol[s0 ^ s1];
- state[j + 1] ^= t ^ mixCol[s1 ^ s2];
- state[j + 2] ^= t ^ mixCol[s2 ^ s3];
- state[j + 3] ^= t ^ mixCol[s3 ^ s0];
- }
- //AddRoundKey
- for (j = 0, k = i * 16; j < 16; ++j, ++k) {
- state[j] ^= key[k];
- }
- }
- //SubBytes
- for (j = 0; j < 16; ++j) {
- state[j] = s[state[j]];
- }
- //ShiftRows
- v = state[1];
- state[1] = state[5];
- state[5] = state[9];
- state[9] = state[13];
- state[13] = v;
- v = state[2];
- u = state[6];
- state[2] = state[10];
- state[6] = state[14];
- state[10] = v;
- state[14] = u;
- v = state[3];
- u = state[7];
- t = state[11];
- state[3] = state[15];
- state[7] = v;
- state[11] = u;
- state[15] = t;
- //AddRoundKey
- for (j = 0, k = 160; j < 16; ++j, ++k) {
- state[j] ^= key[k];
- }
- return state;
- }
- function AES128Cipher(key) {
- this.key = expandKey128(key);
- this.buffer = new Uint8Array(16);
- this.bufferPosition = 0;
- }
- function decryptBlock2(data, finalize) {
- var i, j, ii, sourceLength = data.length, buffer = this.buffer, bufferLength = this.bufferPosition, result = [], iv = this.iv;
- for (i = 0; i < sourceLength; ++i) {
- buffer[bufferLength] = data[i];
- ++bufferLength;
- if (bufferLength < 16) {
- continue;
- }
- // buffer is full, decrypting
- var plain = decrypt128(buffer, this.key);
- // xor-ing the IV vector to get plain text
- for (j = 0; j < 16; ++j) {
- plain[j] ^= iv[j];
- }
- iv = buffer;
- result.push(plain);
- buffer = new Uint8Array(16);
- bufferLength = 0;
- }
- // saving incomplete buffer
- this.buffer = buffer;
- this.bufferLength = bufferLength;
- this.iv = iv;
- if (result.length === 0) {
- return new Uint8Array([]);
- }
- // combining plain text blocks into one
- var outputLength = 16 * result.length;
- if (finalize) {
- // undo a padding that is described in RFC 2898
- var lastBlock = result[result.length - 1];
- var psLen = lastBlock[15];
- if (psLen <= 16) {
- for (i = 15, ii = 16 - psLen; i >= ii; --i) {
- if (lastBlock[i] !== psLen) {
- // Invalid padding, assume that the block has no padding.
- psLen = 0;
- break;
- }
- }
- outputLength -= psLen;
- result[result.length - 1] = lastBlock.subarray(0, 16 - psLen);
- }
- }
- var output = new Uint8Array(outputLength);
- for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
- output.set(result[i], j);
- }
- return output;
- }
- AES128Cipher.prototype = {
- decryptBlock: function AES128Cipher_decryptBlock(data, finalize) {
- var i, sourceLength = data.length;
- var buffer = this.buffer, bufferLength = this.bufferPosition;
- // waiting for IV values -- they are at the start of the stream
- for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) {
- buffer[bufferLength] = data[i];
- }
- if (bufferLength < 16) {
- // need more data
- this.bufferLength = bufferLength;
- return new Uint8Array([]);
- }
- this.iv = buffer;
- this.buffer = new Uint8Array(16);
- this.bufferLength = 0;
- // starting decryption
- this.decryptBlock = decryptBlock2;
- return this.decryptBlock(data.subarray(16), finalize);
- },
- encrypt: function AES128Cipher_encrypt(data, iv) {
- var i, j, ii, sourceLength = data.length, buffer = this.buffer, bufferLength = this.bufferPosition, result = [];
- if (!iv) {
- iv = new Uint8Array(16);
- }
- for (i = 0; i < sourceLength; ++i) {
- buffer[bufferLength] = data[i];
- ++bufferLength;
- if (bufferLength < 16) {
- continue;
- }
- for (j = 0; j < 16; ++j) {
- buffer[j] ^= iv[j];
- }
- // buffer is full, encrypting
- var cipher = encrypt128(buffer, this.key);
- iv = cipher;
- result.push(cipher);
- buffer = new Uint8Array(16);
- bufferLength = 0;
- }
- // saving incomplete buffer
- this.buffer = buffer;
- this.bufferLength = bufferLength;
- this.iv = iv;
- if (result.length === 0) {
- return new Uint8Array([]);
- }
- // combining plain text blocks into one
- var outputLength = 16 * result.length;
- var output = new Uint8Array(outputLength);
- for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
- output.set(result[i], j);
- }
- return output;
- }
- };
- return AES128Cipher;
- }();
- var AES256Cipher = function AES256CipherClosure() {
- var rcon = new Uint8Array([
- 0x8d,
- 0x01,
- 0x02,
- 0x04,
- 0x08,
- 0x10,
- 0x20,
- 0x40,
- 0x80,
- 0x1b,
- 0x36,
- 0x6c,
- 0xd8,
- 0xab,
- 0x4d,
- 0x9a,
- 0x2f,
- 0x5e,
- 0xbc,
- 0x63,
- 0xc6,
- 0x97,
- 0x35,
- 0x6a,
- 0xd4,
- 0xb3,
- 0x7d,
- 0xfa,
- 0xef,
- 0xc5,
- 0x91,
- 0x39,
- 0x72,
- 0xe4,
- 0xd3,
- 0xbd,
- 0x61,
- 0xc2,
- 0x9f,
- 0x25,
- 0x4a,
- 0x94,
- 0x33,
- 0x66,
- 0xcc,
- 0x83,
- 0x1d,
- 0x3a,
- 0x74,
- 0xe8,
- 0xcb,
- 0x8d,
- 0x01,
- 0x02,
- 0x04,
- 0x08,
- 0x10,
- 0x20,
- 0x40,
- 0x80,
- 0x1b,
- 0x36,
- 0x6c,
- 0xd8,
- 0xab,
- 0x4d,
- 0x9a,
- 0x2f,
- 0x5e,
- 0xbc,
- 0x63,
- 0xc6,
- 0x97,
- 0x35,
- 0x6a,
- 0xd4,
- 0xb3,
- 0x7d,
- 0xfa,
- 0xef,
- 0xc5,
- 0x91,
- 0x39,
- 0x72,
- 0xe4,
- 0xd3,
- 0xbd,
- 0x61,
- 0xc2,
- 0x9f,
- 0x25,
- 0x4a,
- 0x94,
- 0x33,
- 0x66,
- 0xcc,
- 0x83,
- 0x1d,
- 0x3a,
- 0x74,
- 0xe8,
- 0xcb,
- 0x8d,
- 0x01,
- 0x02,
- 0x04,
- 0x08,
- 0x10,
- 0x20,
- 0x40,
- 0x80,
- 0x1b,
- 0x36,
- 0x6c,
- 0xd8,
- 0xab,
- 0x4d,
- 0x9a,
- 0x2f,
- 0x5e,
- 0xbc,
- 0x63,
- 0xc6,
- 0x97,
- 0x35,
- 0x6a,
- 0xd4,
- 0xb3,
- 0x7d,
- 0xfa,
- 0xef,
- 0xc5,
- 0x91,
- 0x39,
- 0x72,
- 0xe4,
- 0xd3,
- 0xbd,
- 0x61,
- 0xc2,
- 0x9f,
- 0x25,
- 0x4a,
- 0x94,
- 0x33,
- 0x66,
- 0xcc,
- 0x83,
- 0x1d,
- 0x3a,
- 0x74,
- 0xe8,
- 0xcb,
- 0x8d,
- 0x01,
- 0x02,
- 0x04,
- 0x08,
- 0x10,
- 0x20,
- 0x40,
- 0x80,
- 0x1b,
- 0x36,
- 0x6c,
- 0xd8,
- 0xab,
- 0x4d,
- 0x9a,
- 0x2f,
- 0x5e,
- 0xbc,
- 0x63,
- 0xc6,
- 0x97,
- 0x35,
- 0x6a,
- 0xd4,
- 0xb3,
- 0x7d,
- 0xfa,
- 0xef,
- 0xc5,
- 0x91,
- 0x39,
- 0x72,
- 0xe4,
- 0xd3,
- 0xbd,
- 0x61,
- 0xc2,
- 0x9f,
- 0x25,
- 0x4a,
- 0x94,
- 0x33,
- 0x66,
- 0xcc,
- 0x83,
- 0x1d,
- 0x3a,
- 0x74,
- 0xe8,
- 0xcb,
- 0x8d,
- 0x01,
- 0x02,
- 0x04,
- 0x08,
- 0x10,
- 0x20,
- 0x40,
- 0x80,
- 0x1b,
- 0x36,
- 0x6c,
- 0xd8,
- 0xab,
- 0x4d,
- 0x9a,
- 0x2f,
- 0x5e,
- 0xbc,
- 0x63,
- 0xc6,
- 0x97,
- 0x35,
- 0x6a,
- 0xd4,
- 0xb3,
- 0x7d,
- 0xfa,
- 0xef,
- 0xc5,
- 0x91,
- 0x39,
- 0x72,
- 0xe4,
- 0xd3,
- 0xbd,
- 0x61,
- 0xc2,
- 0x9f,
- 0x25,
- 0x4a,
- 0x94,
- 0x33,
- 0x66,
- 0xcc,
- 0x83,
- 0x1d,
- 0x3a,
- 0x74,
- 0xe8,
- 0xcb,
- 0x8d
- ]);
- var s = new Uint8Array([
- 0x63,
- 0x7c,
- 0x77,
- 0x7b,
- 0xf2,
- 0x6b,
- 0x6f,
- 0xc5,
- 0x30,
- 0x01,
- 0x67,
- 0x2b,
- 0xfe,
- 0xd7,
- 0xab,
- 0x76,
- 0xca,
- 0x82,
- 0xc9,
- 0x7d,
- 0xfa,
- 0x59,
- 0x47,
- 0xf0,
- 0xad,
- 0xd4,
- 0xa2,
- 0xaf,
- 0x9c,
- 0xa4,
- 0x72,
- 0xc0,
- 0xb7,
- 0xfd,
- 0x93,
- 0x26,
- 0x36,
- 0x3f,
- 0xf7,
- 0xcc,
- 0x34,
- 0xa5,
- 0xe5,
- 0xf1,
- 0x71,
- 0xd8,
- 0x31,
- 0x15,
- 0x04,
- 0xc7,
- 0x23,
- 0xc3,
- 0x18,
- 0x96,
- 0x05,
- 0x9a,
- 0x07,
- 0x12,
- 0x80,
- 0xe2,
- 0xeb,
- 0x27,
- 0xb2,
- 0x75,
- 0x09,
- 0x83,
- 0x2c,
- 0x1a,
- 0x1b,
- 0x6e,
- 0x5a,
- 0xa0,
- 0x52,
- 0x3b,
- 0xd6,
- 0xb3,
- 0x29,
- 0xe3,
- 0x2f,
- 0x84,
- 0x53,
- 0xd1,
- 0x00,
- 0xed,
- 0x20,
- 0xfc,
- 0xb1,
- 0x5b,
- 0x6a,
- 0xcb,
- 0xbe,
- 0x39,
- 0x4a,
- 0x4c,
- 0x58,
- 0xcf,
- 0xd0,
- 0xef,
- 0xaa,
- 0xfb,
- 0x43,
- 0x4d,
- 0x33,
- 0x85,
- 0x45,
- 0xf9,
- 0x02,
- 0x7f,
- 0x50,
- 0x3c,
- 0x9f,
- 0xa8,
- 0x51,
- 0xa3,
- 0x40,
- 0x8f,
- 0x92,
- 0x9d,
- 0x38,
- 0xf5,
- 0xbc,
- 0xb6,
- 0xda,
- 0x21,
- 0x10,
- 0xff,
- 0xf3,
- 0xd2,
- 0xcd,
- 0x0c,
- 0x13,
- 0xec,
- 0x5f,
- 0x97,
- 0x44,
- 0x17,
- 0xc4,
- 0xa7,
- 0x7e,
- 0x3d,
- 0x64,
- 0x5d,
- 0x19,
- 0x73,
- 0x60,
- 0x81,
- 0x4f,
- 0xdc,
- 0x22,
- 0x2a,
- 0x90,
- 0x88,
- 0x46,
- 0xee,
- 0xb8,
- 0x14,
- 0xde,
- 0x5e,
- 0x0b,
- 0xdb,
- 0xe0,
- 0x32,
- 0x3a,
- 0x0a,
- 0x49,
- 0x06,
- 0x24,
- 0x5c,
- 0xc2,
- 0xd3,
- 0xac,
- 0x62,
- 0x91,
- 0x95,
- 0xe4,
- 0x79,
- 0xe7,
- 0xc8,
- 0x37,
- 0x6d,
- 0x8d,
- 0xd5,
- 0x4e,
- 0xa9,
- 0x6c,
- 0x56,
- 0xf4,
- 0xea,
- 0x65,
- 0x7a,
- 0xae,
- 0x08,
- 0xba,
- 0x78,
- 0x25,
- 0x2e,
- 0x1c,
- 0xa6,
- 0xb4,
- 0xc6,
- 0xe8,
- 0xdd,
- 0x74,
- 0x1f,
- 0x4b,
- 0xbd,
- 0x8b,
- 0x8a,
- 0x70,
- 0x3e,
- 0xb5,
- 0x66,
- 0x48,
- 0x03,
- 0xf6,
- 0x0e,
- 0x61,
- 0x35,
- 0x57,
- 0xb9,
- 0x86,
- 0xc1,
- 0x1d,
- 0x9e,
- 0xe1,
- 0xf8,
- 0x98,
- 0x11,
- 0x69,
- 0xd9,
- 0x8e,
- 0x94,
- 0x9b,
- 0x1e,
- 0x87,
- 0xe9,
- 0xce,
- 0x55,
- 0x28,
- 0xdf,
- 0x8c,
- 0xa1,
- 0x89,
- 0x0d,
- 0xbf,
- 0xe6,
- 0x42,
- 0x68,
- 0x41,
- 0x99,
- 0x2d,
- 0x0f,
- 0xb0,
- 0x54,
- 0xbb,
- 0x16
- ]);
- var inv_s = new Uint8Array([
- 0x52,
- 0x09,
- 0x6a,
- 0xd5,
- 0x30,
- 0x36,
- 0xa5,
- 0x38,
- 0xbf,
- 0x40,
- 0xa3,
- 0x9e,
- 0x81,
- 0xf3,
- 0xd7,
- 0xfb,
- 0x7c,
- 0xe3,
- 0x39,
- 0x82,
- 0x9b,
- 0x2f,
- 0xff,
- 0x87,
- 0x34,
- 0x8e,
- 0x43,
- 0x44,
- 0xc4,
- 0xde,
- 0xe9,
- 0xcb,
- 0x54,
- 0x7b,
- 0x94,
- 0x32,
- 0xa6,
- 0xc2,
- 0x23,
- 0x3d,
- 0xee,
- 0x4c,
- 0x95,
- 0x0b,
- 0x42,
- 0xfa,
- 0xc3,
- 0x4e,
- 0x08,
- 0x2e,
- 0xa1,
- 0x66,
- 0x28,
- 0xd9,
- 0x24,
- 0xb2,
- 0x76,
- 0x5b,
- 0xa2,
- 0x49,
- 0x6d,
- 0x8b,
- 0xd1,
- 0x25,
- 0x72,
- 0xf8,
- 0xf6,
- 0x64,
- 0x86,
- 0x68,
- 0x98,
- 0x16,
- 0xd4,
- 0xa4,
- 0x5c,
- 0xcc,
- 0x5d,
- 0x65,
- 0xb6,
- 0x92,
- 0x6c,
- 0x70,
- 0x48,
- 0x50,
- 0xfd,
- 0xed,
- 0xb9,
- 0xda,
- 0x5e,
- 0x15,
- 0x46,
- 0x57,
- 0xa7,
- 0x8d,
- 0x9d,
- 0x84,
- 0x90,
- 0xd8,
- 0xab,
- 0x00,
- 0x8c,
- 0xbc,
- 0xd3,
- 0x0a,
- 0xf7,
- 0xe4,
- 0x58,
- 0x05,
- 0xb8,
- 0xb3,
- 0x45,
- 0x06,
- 0xd0,
- 0x2c,
- 0x1e,
- 0x8f,
- 0xca,
- 0x3f,
- 0x0f,
- 0x02,
- 0xc1,
- 0xaf,
- 0xbd,
- 0x03,
- 0x01,
- 0x13,
- 0x8a,
- 0x6b,
- 0x3a,
- 0x91,
- 0x11,
- 0x41,
- 0x4f,
- 0x67,
- 0xdc,
- 0xea,
- 0x97,
- 0xf2,
- 0xcf,
- 0xce,
- 0xf0,
- 0xb4,
- 0xe6,
- 0x73,
- 0x96,
- 0xac,
- 0x74,
- 0x22,
- 0xe7,
- 0xad,
- 0x35,
- 0x85,
- 0xe2,
- 0xf9,
- 0x37,
- 0xe8,
- 0x1c,
- 0x75,
- 0xdf,
- 0x6e,
- 0x47,
- 0xf1,
- 0x1a,
- 0x71,
- 0x1d,
- 0x29,
- 0xc5,
- 0x89,
- 0x6f,
- 0xb7,
- 0x62,
- 0x0e,
- 0xaa,
- 0x18,
- 0xbe,
- 0x1b,
- 0xfc,
- 0x56,
- 0x3e,
- 0x4b,
- 0xc6,
- 0xd2,
- 0x79,
- 0x20,
- 0x9a,
- 0xdb,
- 0xc0,
- 0xfe,
- 0x78,
- 0xcd,
- 0x5a,
- 0xf4,
- 0x1f,
- 0xdd,
- 0xa8,
- 0x33,
- 0x88,
- 0x07,
- 0xc7,
- 0x31,
- 0xb1,
- 0x12,
- 0x10,
- 0x59,
- 0x27,
- 0x80,
- 0xec,
- 0x5f,
- 0x60,
- 0x51,
- 0x7f,
- 0xa9,
- 0x19,
- 0xb5,
- 0x4a,
- 0x0d,
- 0x2d,
- 0xe5,
- 0x7a,
- 0x9f,
- 0x93,
- 0xc9,
- 0x9c,
- 0xef,
- 0xa0,
- 0xe0,
- 0x3b,
- 0x4d,
- 0xae,
- 0x2a,
- 0xf5,
- 0xb0,
- 0xc8,
- 0xeb,
- 0xbb,
- 0x3c,
- 0x83,
- 0x53,
- 0x99,
- 0x61,
- 0x17,
- 0x2b,
- 0x04,
- 0x7e,
- 0xba,
- 0x77,
- 0xd6,
- 0x26,
- 0xe1,
- 0x69,
- 0x14,
- 0x63,
- 0x55,
- 0x21,
- 0x0c,
- 0x7d
- ]);
- var mixCol = new Uint8Array(256);
- for (var i = 0; i < 256; i++) {
- if (i < 128) {
- mixCol[i] = i << 1;
- } else {
- mixCol[i] = i << 1 ^ 0x1b;
- }
- }
- var mix = new Uint32Array([
- 0x00000000,
- 0x0e090d0b,
- 0x1c121a16,
- 0x121b171d,
- 0x3824342c,
- 0x362d3927,
- 0x24362e3a,
- 0x2a3f2331,
- 0x70486858,
- 0x7e416553,
- 0x6c5a724e,
- 0x62537f45,
- 0x486c5c74,
- 0x4665517f,
- 0x547e4662,
- 0x5a774b69,
- 0xe090d0b0,
- 0xee99ddbb,
- 0xfc82caa6,
- 0xf28bc7ad,
- 0xd8b4e49c,
- 0xd6bde997,
- 0xc4a6fe8a,
- 0xcaaff381,
- 0x90d8b8e8,
- 0x9ed1b5e3,
- 0x8ccaa2fe,
- 0x82c3aff5,
- 0xa8fc8cc4,
- 0xa6f581cf,
- 0xb4ee96d2,
- 0xbae79bd9,
- 0xdb3bbb7b,
- 0xd532b670,
- 0xc729a16d,
- 0xc920ac66,
- 0xe31f8f57,
- 0xed16825c,
- 0xff0d9541,
- 0xf104984a,
- 0xab73d323,
- 0xa57ade28,
- 0xb761c935,
- 0xb968c43e,
- 0x9357e70f,
- 0x9d5eea04,
- 0x8f45fd19,
- 0x814cf012,
- 0x3bab6bcb,
- 0x35a266c0,
- 0x27b971dd,
- 0x29b07cd6,
- 0x038f5fe7,
- 0x0d8652ec,
- 0x1f9d45f1,
- 0x119448fa,
- 0x4be30393,
- 0x45ea0e98,
- 0x57f11985,
- 0x59f8148e,
- 0x73c737bf,
- 0x7dce3ab4,
- 0x6fd52da9,
- 0x61dc20a2,
- 0xad766df6,
- 0xa37f60fd,
- 0xb16477e0,
- 0xbf6d7aeb,
- 0x955259da,
- 0x9b5b54d1,
- 0x894043cc,
- 0x87494ec7,
- 0xdd3e05ae,
- 0xd33708a5,
- 0xc12c1fb8,
- 0xcf2512b3,
- 0xe51a3182,
- 0xeb133c89,
- 0xf9082b94,
- 0xf701269f,
- 0x4de6bd46,
- 0x43efb04d,
- 0x51f4a750,
- 0x5ffdaa5b,
- 0x75c2896a,
- 0x7bcb8461,
- 0x69d0937c,
- 0x67d99e77,
- 0x3daed51e,
- 0x33a7d815,
- 0x21bccf08,
- 0x2fb5c203,
- 0x058ae132,
- 0x0b83ec39,
- 0x1998fb24,
- 0x1791f62f,
- 0x764dd68d,
- 0x7844db86,
- 0x6a5fcc9b,
- 0x6456c190,
- 0x4e69e2a1,
- 0x4060efaa,
- 0x527bf8b7,
- 0x5c72f5bc,
- 0x0605bed5,
- 0x080cb3de,
- 0x1a17a4c3,
- 0x141ea9c8,
- 0x3e218af9,
- 0x302887f2,
- 0x223390ef,
- 0x2c3a9de4,
- 0x96dd063d,
- 0x98d40b36,
- 0x8acf1c2b,
- 0x84c61120,
- 0xaef93211,
- 0xa0f03f1a,
- 0xb2eb2807,
- 0xbce2250c,
- 0xe6956e65,
- 0xe89c636e,
- 0xfa877473,
- 0xf48e7978,
- 0xdeb15a49,
- 0xd0b85742,
- 0xc2a3405f,
- 0xccaa4d54,
- 0x41ecdaf7,
- 0x4fe5d7fc,
- 0x5dfec0e1,
- 0x53f7cdea,
- 0x79c8eedb,
- 0x77c1e3d0,
- 0x65daf4cd,
- 0x6bd3f9c6,
- 0x31a4b2af,
- 0x3fadbfa4,
- 0x2db6a8b9,
- 0x23bfa5b2,
- 0x09808683,
- 0x07898b88,
- 0x15929c95,
- 0x1b9b919e,
- 0xa17c0a47,
- 0xaf75074c,
- 0xbd6e1051,
- 0xb3671d5a,
- 0x99583e6b,
- 0x97513360,
- 0x854a247d,
- 0x8b432976,
- 0xd134621f,
- 0xdf3d6f14,
- 0xcd267809,
- 0xc32f7502,
- 0xe9105633,
- 0xe7195b38,
- 0xf5024c25,
- 0xfb0b412e,
- 0x9ad7618c,
- 0x94de6c87,
- 0x86c57b9a,
- 0x88cc7691,
- 0xa2f355a0,
- 0xacfa58ab,
- 0xbee14fb6,
- 0xb0e842bd,
- 0xea9f09d4,
- 0xe49604df,
- 0xf68d13c2,
- 0xf8841ec9,
- 0xd2bb3df8,
- 0xdcb230f3,
- 0xcea927ee,
- 0xc0a02ae5,
- 0x7a47b13c,
- 0x744ebc37,
- 0x6655ab2a,
- 0x685ca621,
- 0x42638510,
- 0x4c6a881b,
- 0x5e719f06,
- 0x5078920d,
- 0x0a0fd964,
- 0x0406d46f,
- 0x161dc372,
- 0x1814ce79,
- 0x322bed48,
- 0x3c22e043,
- 0x2e39f75e,
- 0x2030fa55,
- 0xec9ab701,
- 0xe293ba0a,
- 0xf088ad17,
- 0xfe81a01c,
- 0xd4be832d,
- 0xdab78e26,
- 0xc8ac993b,
- 0xc6a59430,
- 0x9cd2df59,
- 0x92dbd252,
- 0x80c0c54f,
- 0x8ec9c844,
- 0xa4f6eb75,
- 0xaaffe67e,
- 0xb8e4f163,
- 0xb6edfc68,
- 0x0c0a67b1,
- 0x02036aba,
- 0x10187da7,
- 0x1e1170ac,
- 0x342e539d,
- 0x3a275e96,
- 0x283c498b,
- 0x26354480,
- 0x7c420fe9,
- 0x724b02e2,
- 0x605015ff,
- 0x6e5918f4,
- 0x44663bc5,
- 0x4a6f36ce,
- 0x587421d3,
- 0x567d2cd8,
- 0x37a10c7a,
- 0x39a80171,
- 0x2bb3166c,
- 0x25ba1b67,
- 0x0f853856,
- 0x018c355d,
- 0x13972240,
- 0x1d9e2f4b,
- 0x47e96422,
- 0x49e06929,
- 0x5bfb7e34,
- 0x55f2733f,
- 0x7fcd500e,
- 0x71c45d05,
- 0x63df4a18,
- 0x6dd64713,
- 0xd731dcca,
- 0xd938d1c1,
- 0xcb23c6dc,
- 0xc52acbd7,
- 0xef15e8e6,
- 0xe11ce5ed,
- 0xf307f2f0,
- 0xfd0efffb,
- 0xa779b492,
- 0xa970b999,
- 0xbb6bae84,
- 0xb562a38f,
- 0x9f5d80be,
- 0x91548db5,
- 0x834f9aa8,
- 0x8d4697a3
- ]);
- function expandKey256(cipherKey) {
- var b = 240, result = new Uint8Array(b);
- var r = 1;
- result.set(cipherKey);
- for (var j = 32, i = 1; j < b; ++i) {
- if (j % 32 === 16) {
- t1 = s[t1];
- t2 = s[t2];
- t3 = s[t3];
- t4 = s[t4];
- } else if (j % 32 === 0) {
- // RotWord
- var t1 = result[j - 3], t2 = result[j - 2], t3 = result[j - 1], t4 = result[j - 4];
- // SubWord
- t1 = s[t1];
- t2 = s[t2];
- t3 = s[t3];
- t4 = s[t4];
- // Rcon
- t1 = t1 ^ r;
- if ((r <<= 1) >= 256) {
- r = (r ^ 0x1b) & 0xFF;
- }
- }
- for (var n = 0; n < 4; ++n) {
- result[j] = t1 ^= result[j - 32];
- j++;
- result[j] = t2 ^= result[j - 32];
- j++;
- result[j] = t3 ^= result[j - 32];
- j++;
- result[j] = t4 ^= result[j - 32];
- j++;
- }
- }
- return result;
- }
- function decrypt256(input, key) {
- var state = new Uint8Array(16);
- state.set(input);
- var i, j, k;
- var t, u, v;
- // AddRoundKey
- for (j = 0, k = 224; j < 16; ++j, ++k) {
- state[j] ^= key[k];
- }
- for (i = 13; i >= 1; --i) {
- // InvShiftRows
- t = state[13];
- state[13] = state[9];
- state[9] = state[5];
- state[5] = state[1];
- state[1] = t;
- t = state[14];
- u = state[10];
- state[14] = state[6];
- state[10] = state[2];
- state[6] = t;
- state[2] = u;
- t = state[15];
- u = state[11];
- v = state[7];
- state[15] = state[3];
- state[11] = t;
- state[7] = u;
- state[3] = v;
- // InvSubBytes
- for (j = 0; j < 16; ++j) {
- state[j] = inv_s[state[j]];
- }
- // AddRoundKey
- for (j = 0, k = i * 16; j < 16; ++j, ++k) {
- state[j] ^= key[k];
- }
- // InvMixColumns
- for (j = 0; j < 16; j += 4) {
- var s0 = mix[state[j]], s1 = mix[state[j + 1]], s2 = mix[state[j + 2]], s3 = mix[state[j + 3]];
- t = s0 ^ s1 >>> 8 ^ s1 << 24 ^ s2 >>> 16 ^ s2 << 16 ^ s3 >>> 24 ^ s3 << 8;
- state[j] = t >>> 24 & 0xFF;
- state[j + 1] = t >> 16 & 0xFF;
- state[j + 2] = t >> 8 & 0xFF;
- state[j + 3] = t & 0xFF;
- }
- }
- // InvShiftRows
- t = state[13];
- state[13] = state[9];
- state[9] = state[5];
- state[5] = state[1];
- state[1] = t;
- t = state[14];
- u = state[10];
- state[14] = state[6];
- state[10] = state[2];
- state[6] = t;
- state[2] = u;
- t = state[15];
- u = state[11];
- v = state[7];
- state[15] = state[3];
- state[11] = t;
- state[7] = u;
- state[3] = v;
- for (j = 0; j < 16; ++j) {
- // InvSubBytes
- state[j] = inv_s[state[j]];
- // AddRoundKey
- state[j] ^= key[j];
- }
- return state;
- }
- function encrypt256(input, key) {
- var t, u, v, k;
- var state = new Uint8Array(16);
- state.set(input);
- for (j = 0; j < 16; ++j) {
- // AddRoundKey
- state[j] ^= key[j];
- }
- for (i = 1; i < 14; i++) {
- //SubBytes
- for (j = 0; j < 16; ++j) {
- state[j] = s[state[j]];
- }
- //ShiftRows
- v = state[1];
- state[1] = state[5];
- state[5] = state[9];
- state[9] = state[13];
- state[13] = v;
- v = state[2];
- u = state[6];
- state[2] = state[10];
- state[6] = state[14];
- state[10] = v;
- state[14] = u;
- v = state[3];
- u = state[7];
- t = state[11];
- state[3] = state[15];
- state[7] = v;
- state[11] = u;
- state[15] = t;
- //MixColumns
- for (var j = 0; j < 16; j += 4) {
- var s0 = state[j + 0], s1 = state[j + 1];
- var s2 = state[j + 2], s3 = state[j + 3];
- t = s0 ^ s1 ^ s2 ^ s3;
- state[j + 0] ^= t ^ mixCol[s0 ^ s1];
- state[j + 1] ^= t ^ mixCol[s1 ^ s2];
- state[j + 2] ^= t ^ mixCol[s2 ^ s3];
- state[j + 3] ^= t ^ mixCol[s3 ^ s0];
- }
- //AddRoundKey
- for (j = 0, k = i * 16; j < 16; ++j, ++k) {
- state[j] ^= key[k];
- }
- }
- //SubBytes
- for (j = 0; j < 16; ++j) {
- state[j] = s[state[j]];
- }
- //ShiftRows
- v = state[1];
- state[1] = state[5];
- state[5] = state[9];
- state[9] = state[13];
- state[13] = v;
- v = state[2];
- u = state[6];
- state[2] = state[10];
- state[6] = state[14];
- state[10] = v;
- state[14] = u;
- v = state[3];
- u = state[7];
- t = state[11];
- state[3] = state[15];
- state[7] = v;
- state[11] = u;
- state[15] = t;
- //AddRoundKey
- for (j = 0, k = 224; j < 16; ++j, ++k) {
- state[j] ^= key[k];
- }
- return state;
- }
- function AES256Cipher(key) {
- this.key = expandKey256(key);
- this.buffer = new Uint8Array(16);
- this.bufferPosition = 0;
- }
- function decryptBlock2(data, finalize) {
- var i, j, ii, sourceLength = data.length, buffer = this.buffer, bufferLength = this.bufferPosition, result = [], iv = this.iv;
- for (i = 0; i < sourceLength; ++i) {
- buffer[bufferLength] = data[i];
- ++bufferLength;
- if (bufferLength < 16) {
- continue;
- }
- // buffer is full, decrypting
- var plain = decrypt256(buffer, this.key);
- // xor-ing the IV vector to get plain text
- for (j = 0; j < 16; ++j) {
- plain[j] ^= iv[j];
- }
- iv = buffer;
- result.push(plain);
- buffer = new Uint8Array(16);
- bufferLength = 0;
- }
- // saving incomplete buffer
- this.buffer = buffer;
- this.bufferLength = bufferLength;
- this.iv = iv;
- if (result.length === 0) {
- return new Uint8Array([]);
- }
- // combining plain text blocks into one
- var outputLength = 16 * result.length;
- if (finalize) {
- // undo a padding that is described in RFC 2898
- var lastBlock = result[result.length - 1];
- var psLen = lastBlock[15];
- if (psLen <= 16) {
- for (i = 15, ii = 16 - psLen; i >= ii; --i) {
- if (lastBlock[i] !== psLen) {
- // Invalid padding, assume that the block has no padding.
- psLen = 0;
- break;
- }
- }
- outputLength -= psLen;
- result[result.length - 1] = lastBlock.subarray(0, 16 - psLen);
- }
- }
- var output = new Uint8Array(outputLength);
- for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
- output.set(result[i], j);
- }
- return output;
- }
- AES256Cipher.prototype = {
- decryptBlock: function AES256Cipher_decryptBlock(data, finalize, iv) {
- var i, sourceLength = data.length;
- var buffer = this.buffer, bufferLength = this.bufferPosition;
- // if not supplied an IV wait for IV values
- // they are at the start of the stream
- if (iv) {
- this.iv = iv;
- } else {
- for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) {
- buffer[bufferLength] = data[i];
- }
- if (bufferLength < 16) {
- //need more data
- this.bufferLength = bufferLength;
- return new Uint8Array([]);
- }
- this.iv = buffer;
- data = data.subarray(16);
- }
- this.buffer = new Uint8Array(16);
- this.bufferLength = 0;
- // starting decryption
- this.decryptBlock = decryptBlock2;
- return this.decryptBlock(data, finalize);
- },
- encrypt: function AES256Cipher_encrypt(data, iv) {
- var i, j, ii, sourceLength = data.length, buffer = this.buffer, bufferLength = this.bufferPosition, result = [];
- if (!iv) {
- iv = new Uint8Array(16);
- }
- for (i = 0; i < sourceLength; ++i) {
- buffer[bufferLength] = data[i];
- ++bufferLength;
- if (bufferLength < 16) {
- continue;
- }
- for (j = 0; j < 16; ++j) {
- buffer[j] ^= iv[j];
- }
- // buffer is full, encrypting
- var cipher = encrypt256(buffer, this.key);
- this.iv = cipher;
- result.push(cipher);
- buffer = new Uint8Array(16);
- bufferLength = 0;
- }
- // saving incomplete buffer
- this.buffer = buffer;
- this.bufferLength = bufferLength;
- this.iv = iv;
- if (result.length === 0) {
- return new Uint8Array([]);
- }
- // combining plain text blocks into one
- var outputLength = 16 * result.length;
- var output = new Uint8Array(outputLength);
- for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
- output.set(result[i], j);
- }
- return output;
- }
- };
- return AES256Cipher;
- }();
- var PDF17 = function PDF17Closure() {
- function compareByteArrays(array1, array2) {
- if (array1.length !== array2.length) {
- return false;
- }
- for (var i = 0; i < array1.length; i++) {
- if (array1[i] !== array2[i]) {
- return false;
- }
- }
- return true;
- }
- function PDF17() {
- }
- PDF17.prototype = {
- checkOwnerPassword: function PDF17_checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) {
- var hashData = new Uint8Array(password.length + 56);
- hashData.set(password, 0);
- hashData.set(ownerValidationSalt, password.length);
- hashData.set(userBytes, password.length + ownerValidationSalt.length);
- var result = calculateSHA256(hashData, 0, hashData.length);
- return compareByteArrays(result, ownerPassword);
- },
- checkUserPassword: function PDF17_checkUserPassword(password, userValidationSalt, userPassword) {
- var hashData = new Uint8Array(password.length + 8);
- hashData.set(password, 0);
- hashData.set(userValidationSalt, password.length);
- var result = calculateSHA256(hashData, 0, hashData.length);
- return compareByteArrays(result, userPassword);
- },
- getOwnerKey: function PDF17_getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) {
- var hashData = new Uint8Array(password.length + 56);
- hashData.set(password, 0);
- hashData.set(ownerKeySalt, password.length);
- hashData.set(userBytes, password.length + ownerKeySalt.length);
- var key = calculateSHA256(hashData, 0, hashData.length);
- var cipher = new AES256Cipher(key);
- return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16));
- },
- getUserKey: function PDF17_getUserKey(password, userKeySalt, userEncryption) {
- var hashData = new Uint8Array(password.length + 8);
- hashData.set(password, 0);
- hashData.set(userKeySalt, password.length);
- //key is the decryption key for the UE string
- var key = calculateSHA256(hashData, 0, hashData.length);
- var cipher = new AES256Cipher(key);
- return cipher.decryptBlock(userEncryption, false, new Uint8Array(16));
- }
- };
- return PDF17;
- }();
- var PDF20 = function PDF20Closure() {
- function concatArrays(array1, array2) {
- var t = new Uint8Array(array1.length + array2.length);
- t.set(array1, 0);
- t.set(array2, array1.length);
- return t;
- }
- function calculatePDF20Hash(password, input, userBytes) {
- //This refers to Algorithm 2.B as defined in ISO 32000-2
- var k = calculateSHA256(input, 0, input.length).subarray(0, 32);
- var e = [0];
- var i = 0;
- while (i < 64 || e[e.length - 1] > i - 32) {
- var arrayLength = password.length + k.length + userBytes.length;
- var k1 = new Uint8Array(arrayLength * 64);
- var array = concatArrays(password, k);
- array = concatArrays(array, userBytes);
- for (var j = 0, pos = 0; j < 64; j++, pos += arrayLength) {
- k1.set(array, pos);
- }
- //AES128 CBC NO PADDING with
- //first 16 bytes of k as the key and the second 16 as the iv.
- var cipher = new AES128Cipher(k.subarray(0, 16));
- e = cipher.encrypt(k1, k.subarray(16, 32));
- //Now we have to take the first 16 bytes of an unsigned
- //big endian integer... and compute the remainder
- //modulo 3.... That is a fairly large number and
- //JavaScript isn't going to handle that well...
- //So we're using a trick that allows us to perform
- //modulo math byte by byte
- var remainder = 0;
- for (var z = 0; z < 16; z++) {
- remainder *= 256 % 3;
- remainder %= 3;
- remainder += (e[z] >>> 0) % 3;
- remainder %= 3;
- }
- if (remainder === 0) {
- k = calculateSHA256(e, 0, e.length);
- } else if (remainder === 1) {
- k = calculateSHA384(e, 0, e.length);
- } else if (remainder === 2) {
- k = calculateSHA512(e, 0, e.length);
- }
- i++;
- }
- return k.subarray(0, 32);
- }
- function PDF20() {
- }
- function compareByteArrays(array1, array2) {
- if (array1.length !== array2.length) {
- return false;
- }
- for (var i = 0; i < array1.length; i++) {
- if (array1[i] !== array2[i]) {
- return false;
- }
- }
- return true;
- }
- PDF20.prototype = {
- hash: function PDF20_hash(password, concatBytes, userBytes) {
- return calculatePDF20Hash(password, concatBytes, userBytes);
- },
- checkOwnerPassword: function PDF20_checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) {
- var hashData = new Uint8Array(password.length + 56);
- hashData.set(password, 0);
- hashData.set(ownerValidationSalt, password.length);
- hashData.set(userBytes, password.length + ownerValidationSalt.length);
- var result = calculatePDF20Hash(password, hashData, userBytes);
- return compareByteArrays(result, ownerPassword);
- },
- checkUserPassword: function PDF20_checkUserPassword(password, userValidationSalt, userPassword) {
- var hashData = new Uint8Array(password.length + 8);
- hashData.set(password, 0);
- hashData.set(userValidationSalt, password.length);
- var result = calculatePDF20Hash(password, hashData, []);
- return compareByteArrays(result, userPassword);
- },
- getOwnerKey: function PDF20_getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) {
- var hashData = new Uint8Array(password.length + 56);
- hashData.set(password, 0);
- hashData.set(ownerKeySalt, password.length);
- hashData.set(userBytes, password.length + ownerKeySalt.length);
- var key = calculatePDF20Hash(password, hashData, userBytes);
- var cipher = new AES256Cipher(key);
- return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16));
- },
- getUserKey: function PDF20_getUserKey(password, userKeySalt, userEncryption) {
- var hashData = new Uint8Array(password.length + 8);
- hashData.set(password, 0);
- hashData.set(userKeySalt, password.length);
- //key is the decryption key for the UE string
- var key = calculatePDF20Hash(password, hashData, []);
- var cipher = new AES256Cipher(key);
- return cipher.decryptBlock(userEncryption, false, new Uint8Array(16));
- }
- };
- return PDF20;
- }();
- var CipherTransform = function CipherTransformClosure() {
- function CipherTransform(stringCipherConstructor, streamCipherConstructor) {
- this.stringCipherConstructor = stringCipherConstructor;
- this.streamCipherConstructor = streamCipherConstructor;
- }
- CipherTransform.prototype = {
- createStream: function CipherTransform_createStream(stream, length) {
- var cipher = new this.streamCipherConstructor();
- return new DecryptStream(stream, length, function cipherTransformDecryptStream(data, finalize) {
- return cipher.decryptBlock(data, finalize);
- });
- },
- decryptString: function CipherTransform_decryptString(s) {
- var cipher = new this.stringCipherConstructor();
- var data = stringToBytes(s);
- data = cipher.decryptBlock(data, true);
- return bytesToString(data);
- }
- };
- return CipherTransform;
- }();
- var CipherTransformFactory = function CipherTransformFactoryClosure() {
- var defaultPasswordBytes = new Uint8Array([
- 0x28,
- 0xBF,
- 0x4E,
- 0x5E,
- 0x4E,
- 0x75,
- 0x8A,
- 0x41,
- 0x64,
- 0x00,
- 0x4E,
- 0x56,
- 0xFF,
- 0xFA,
- 0x01,
- 0x08,
- 0x2E,
- 0x2E,
- 0x00,
- 0xB6,
- 0xD0,
- 0x68,
- 0x3E,
- 0x80,
- 0x2F,
- 0x0C,
- 0xA9,
- 0xFE,
- 0x64,
- 0x53,
- 0x69,
- 0x7A
- ]);
- function createEncryptionKey20(revision, password, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms) {
- if (password) {
- var passwordLength = Math.min(127, password.length);
- password = password.subarray(0, passwordLength);
- } else {
- password = [];
- }
- var pdfAlgorithm;
- if (revision === 6) {
- pdfAlgorithm = new PDF20();
- } else {
- pdfAlgorithm = new PDF17();
- }
- if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, userPassword)) {
- return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption);
- } else if (password.length && pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, uBytes, ownerPassword)) {
- return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption);
- }
- return null;
- }
- function prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) {
- var hashDataSize = 40 + ownerPassword.length + fileId.length;
- var hashData = new Uint8Array(hashDataSize), i = 0, j, n;
- if (password) {
- n = Math.min(32, password.length);
- for (; i < n; ++i) {
- hashData[i] = password[i];
- }
- }
- j = 0;
- while (i < 32) {
- hashData[i++] = defaultPasswordBytes[j++];
- }
- // as now the padded password in the hashData[0..i]
- for (j = 0, n = ownerPassword.length; j < n; ++j) {
- hashData[i++] = ownerPassword[j];
- }
- hashData[i++] = flags & 0xFF;
- hashData[i++] = flags >> 8 & 0xFF;
- hashData[i++] = flags >> 16 & 0xFF;
- hashData[i++] = flags >>> 24 & 0xFF;
- for (j = 0, n = fileId.length; j < n; ++j) {
- hashData[i++] = fileId[j];
- }
- if (revision >= 4 && !encryptMetadata) {
- hashData[i++] = 0xFF;
- hashData[i++] = 0xFF;
- hashData[i++] = 0xFF;
- hashData[i++] = 0xFF;
- }
- var hash = calculateMD5(hashData, 0, i);
- var keyLengthInBytes = keyLength >> 3;
- if (revision >= 3) {
- for (j = 0; j < 50; ++j) {
- hash = calculateMD5(hash, 0, keyLengthInBytes);
- }
- }
- var encryptionKey = hash.subarray(0, keyLengthInBytes);
- var cipher, checkData;
- if (revision >= 3) {
- for (i = 0; i < 32; ++i) {
- hashData[i] = defaultPasswordBytes[i];
- }
- for (j = 0, n = fileId.length; j < n; ++j) {
- hashData[i++] = fileId[j];
- }
- cipher = new ARCFourCipher(encryptionKey);
- checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i));
- n = encryptionKey.length;
- var derivedKey = new Uint8Array(n), k;
- for (j = 1; j <= 19; ++j) {
- for (k = 0; k < n; ++k) {
- derivedKey[k] = encryptionKey[k] ^ j;
- }
- cipher = new ARCFourCipher(derivedKey);
- checkData = cipher.encryptBlock(checkData);
- }
- for (j = 0, n = checkData.length; j < n; ++j) {
- if (userPassword[j] !== checkData[j]) {
- return null;
- }
- }
- } else {
- cipher = new ARCFourCipher(encryptionKey);
- checkData = cipher.encryptBlock(defaultPasswordBytes);
- for (j = 0, n = checkData.length; j < n; ++j) {
- if (userPassword[j] !== checkData[j]) {
- return null;
- }
- }
- }
- return encryptionKey;
- }
- function decodeUserPassword(password, ownerPassword, revision, keyLength) {
- var hashData = new Uint8Array(32), i = 0, j, n;
- n = Math.min(32, password.length);
- for (; i < n; ++i) {
- hashData[i] = password[i];
- }
- j = 0;
- while (i < 32) {
- hashData[i++] = defaultPasswordBytes[j++];
- }
- var hash = calculateMD5(hashData, 0, i);
- var keyLengthInBytes = keyLength >> 3;
- if (revision >= 3) {
- for (j = 0; j < 50; ++j) {
- hash = calculateMD5(hash, 0, hash.length);
- }
- }
- var cipher, userPassword;
- if (revision >= 3) {
- userPassword = ownerPassword;
- var derivedKey = new Uint8Array(keyLengthInBytes), k;
- for (j = 19; j >= 0; j--) {
- for (k = 0; k < keyLengthInBytes; ++k) {
- derivedKey[k] = hash[k] ^ j;
- }
- cipher = new ARCFourCipher(derivedKey);
- userPassword = cipher.encryptBlock(userPassword);
- }
- } else {
- cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes));
- userPassword = cipher.encryptBlock(ownerPassword);
- }
- return userPassword;
- }
- var identityName = Name.get('Identity');
- function CipherTransformFactory(dict, fileId, password) {
- var filter = dict.get('Filter');
- if (!isName(filter, 'Standard')) {
- error('unknown encryption method');
- }
- this.dict = dict;
- var algorithm = dict.get('V');
- if (!isInt(algorithm) || algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5) {
- error('unsupported encryption algorithm');
- }
- this.algorithm = algorithm;
- var keyLength = dict.get('Length');
- if (!keyLength) {
- // Spec asks to rely on encryption dictionary's Length entry, however
- // some PDFs don't have it. Trying to recover.
- if (algorithm <= 3) {
- // For 1 and 2 it's fixed to 40-bit, for 3 40-bit is a minimal value.
- keyLength = 40;
- } else {
- // Trying to find default handler -- it usually has Length.
- var cfDict = dict.get('CF');
- var streamCryptoName = dict.get('StmF');
- if (isDict(cfDict) && isName(streamCryptoName)) {
- cfDict.suppressEncryption = true;
- // See comment below.
- var handlerDict = cfDict.get(streamCryptoName.name);
- keyLength = handlerDict && handlerDict.get('Length') || 128;
- if (keyLength < 40) {
- // Sometimes it's incorrect value of bits, generators specify bytes.
- keyLength <<= 3;
- }
- }
- }
- }
- if (!isInt(keyLength) || keyLength < 40 || keyLength % 8 !== 0) {
- error('invalid key length');
- }
- // prepare keys
- var ownerPassword = stringToBytes(dict.get('O')).subarray(0, 32);
- var userPassword = stringToBytes(dict.get('U')).subarray(0, 32);
- var flags = dict.get('P');
- var revision = dict.get('R');
- // meaningful when V is 4 or 5
- var encryptMetadata = (algorithm === 4 || algorithm === 5) && dict.get('EncryptMetadata') !== false;
- this.encryptMetadata = encryptMetadata;
- var fileIdBytes = stringToBytes(fileId);
- var passwordBytes;
- if (password) {
- if (revision === 6) {
- try {
- password = utf8StringToString(password);
- } catch (ex) {
- warn('CipherTransformFactory: ' + 'Unable to convert UTF8 encoded password.');
- }
- }
- passwordBytes = stringToBytes(password);
- }
- var encryptionKey;
- if (algorithm !== 5) {
- encryptionKey = prepareKeyData(fileIdBytes, passwordBytes, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata);
- } else {
- var ownerValidationSalt = stringToBytes(dict.get('O')).subarray(32, 40);
- var ownerKeySalt = stringToBytes(dict.get('O')).subarray(40, 48);
- var uBytes = stringToBytes(dict.get('U')).subarray(0, 48);
- var userValidationSalt = stringToBytes(dict.get('U')).subarray(32, 40);
- var userKeySalt = stringToBytes(dict.get('U')).subarray(40, 48);
- var ownerEncryption = stringToBytes(dict.get('OE'));
- var userEncryption = stringToBytes(dict.get('UE'));
- var perms = stringToBytes(dict.get('Perms'));
- encryptionKey = createEncryptionKey20(revision, passwordBytes, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms);
- }
- if (!encryptionKey && !password) {
- throw new PasswordException('No password given', PasswordResponses.NEED_PASSWORD);
- } else if (!encryptionKey && password) {
- // Attempting use the password as an owner password
- var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword, revision, keyLength);
- encryptionKey = prepareKeyData(fileIdBytes, decodedPassword, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata);
- }
- if (!encryptionKey) {
- throw new PasswordException('Incorrect Password', PasswordResponses.INCORRECT_PASSWORD);
- }
- this.encryptionKey = encryptionKey;
- if (algorithm >= 4) {
- var cf = dict.get('CF');
- if (isDict(cf)) {
- // The 'CF' dictionary itself should not be encrypted, and by setting
- // `suppressEncryption` we can prevent an infinite loop inside of
- // `XRef_fetchUncompressed` if the dictionary contains indirect objects
- // (fixes issue7665.pdf).
- cf.suppressEncryption = true;
- }
- this.cf = cf;
- this.stmf = dict.get('StmF') || identityName;
- this.strf = dict.get('StrF') || identityName;
- this.eff = dict.get('EFF') || this.stmf;
- }
- }
- function buildObjectKey(num, gen, encryptionKey, isAes) {
- var key = new Uint8Array(encryptionKey.length + 9), i, n;
- for (i = 0, n = encryptionKey.length; i < n; ++i) {
- key[i] = encryptionKey[i];
- }
- key[i++] = num & 0xFF;
- key[i++] = num >> 8 & 0xFF;
- key[i++] = num >> 16 & 0xFF;
- key[i++] = gen & 0xFF;
- key[i++] = gen >> 8 & 0xFF;
- if (isAes) {
- key[i++] = 0x73;
- key[i++] = 0x41;
- key[i++] = 0x6C;
- key[i++] = 0x54;
- }
- var hash = calculateMD5(key, 0, i);
- return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
- }
- function buildCipherConstructor(cf, name, num, gen, key) {
- assert(isName(name), 'Invalid crypt filter name.');
- var cryptFilter = cf.get(name.name);
- var cfm;
- if (cryptFilter !== null && cryptFilter !== undefined) {
- cfm = cryptFilter.get('CFM');
- }
- if (!cfm || cfm.name === 'None') {
- return function cipherTransformFactoryBuildCipherConstructorNone() {
- return new NullCipher();
- };
- }
- if ('V2' === cfm.name) {
- return function cipherTransformFactoryBuildCipherConstructorV2() {
- return new ARCFourCipher(buildObjectKey(num, gen, key, false));
- };
- }
- if ('AESV2' === cfm.name) {
- return function cipherTransformFactoryBuildCipherConstructorAESV2() {
- return new AES128Cipher(buildObjectKey(num, gen, key, true));
- };
- }
- if ('AESV3' === cfm.name) {
- return function cipherTransformFactoryBuildCipherConstructorAESV3() {
- return new AES256Cipher(key);
- };
- }
- error('Unknown crypto method');
- }
- CipherTransformFactory.prototype = {
- createCipherTransform: function CipherTransformFactory_createCipherTransform(num, gen) {
- if (this.algorithm === 4 || this.algorithm === 5) {
- return new CipherTransform(buildCipherConstructor(this.cf, this.stmf, num, gen, this.encryptionKey), buildCipherConstructor(this.cf, this.strf, num, gen, this.encryptionKey));
- }
- // algorithms 1 and 2
- var key = buildObjectKey(num, gen, this.encryptionKey, false);
- var cipherConstructor = function buildCipherCipherConstructor() {
- return new ARCFourCipher(key);
- };
- return new CipherTransform(cipherConstructor, cipherConstructor);
- }
- };
- return CipherTransformFactory;
- }();
- exports.AES128Cipher = AES128Cipher;
- exports.AES256Cipher = AES256Cipher;
- exports.ARCFourCipher = ARCFourCipher;
- exports.CipherTransformFactory = CipherTransformFactory;
- exports.PDF17 = PDF17;
- exports.PDF20 = PDF20;
- exports.calculateMD5 = calculateMD5;
- exports.calculateSHA256 = calculateSHA256;
- exports.calculateSHA384 = calculateSHA384;
- exports.calculateSHA512 = calculateSHA512;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreFontRenderer = {}, root.pdfjsSharedUtil, root.pdfjsCoreStream, root.pdfjsCoreGlyphList, root.pdfjsCoreEncodings, root.pdfjsCoreCFFParser);
- }(this, function (exports, sharedUtil, coreStream, coreGlyphList, coreEncodings, coreCFFParser) {
- var Util = sharedUtil.Util;
- var bytesToString = sharedUtil.bytesToString;
- var error = sharedUtil.error;
- var Stream = coreStream.Stream;
- var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode;
- var StandardEncoding = coreEncodings.StandardEncoding;
- var CFFParser = coreCFFParser.CFFParser;
- var FontRendererFactory = function FontRendererFactoryClosure() {
- function getLong(data, offset) {
- return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
- }
- function getUshort(data, offset) {
- return data[offset] << 8 | data[offset + 1];
- }
- function parseCmap(data, start, end) {
- var offset = getUshort(data, start + 2) === 1 ? getLong(data, start + 8) : getLong(data, start + 16);
- var format = getUshort(data, start + offset);
- var length, ranges, p, i;
- if (format === 4) {
- length = getUshort(data, start + offset + 2);
- var segCount = getUshort(data, start + offset + 6) >> 1;
- p = start + offset + 14;
- ranges = [];
- for (i = 0; i < segCount; i++, p += 2) {
- ranges[i] = { end: getUshort(data, p) };
- }
- p += 2;
- for (i = 0; i < segCount; i++, p += 2) {
- ranges[i].start = getUshort(data, p);
- }
- for (i = 0; i < segCount; i++, p += 2) {
- ranges[i].idDelta = getUshort(data, p);
- }
- for (i = 0; i < segCount; i++, p += 2) {
- var idOffset = getUshort(data, p);
- if (idOffset === 0) {
- continue;
- }
- ranges[i].ids = [];
- for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) {
- ranges[i].ids[j] = getUshort(data, p + idOffset);
- idOffset += 2;
- }
- }
- return ranges;
- } else if (format === 12) {
- length = getLong(data, start + offset + 4);
- var groups = getLong(data, start + offset + 12);
- p = start + offset + 16;
- ranges = [];
- for (i = 0; i < groups; i++) {
- ranges.push({
- start: getLong(data, p),
- end: getLong(data, p + 4),
- idDelta: getLong(data, p + 8) - getLong(data, p)
- });
- p += 12;
- }
- return ranges;
- }
- error('not supported cmap: ' + format);
- }
- function parseCff(data, start, end, seacAnalysisEnabled) {
- var properties = {};
- var parser = new CFFParser(new Stream(data, start, end - start), properties, seacAnalysisEnabled);
- var cff = parser.parse();
- return {
- glyphs: cff.charStrings.objects,
- subrs: cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && cff.topDict.privateDict.subrsIndex.objects,
- gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects
- };
- }
- function parseGlyfTable(glyf, loca, isGlyphLocationsLong) {
- var itemSize, itemDecode;
- if (isGlyphLocationsLong) {
- itemSize = 4;
- itemDecode = function fontItemDecodeLong(data, offset) {
- return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
- };
- } else {
- itemSize = 2;
- itemDecode = function fontItemDecode(data, offset) {
- return data[offset] << 9 | data[offset + 1] << 1;
- };
- }
- var glyphs = [];
- var startOffset = itemDecode(loca, 0);
- for (var j = itemSize; j < loca.length; j += itemSize) {
- var endOffset = itemDecode(loca, j);
- glyphs.push(glyf.subarray(startOffset, endOffset));
- startOffset = endOffset;
- }
- return glyphs;
- }
- function lookupCmap(ranges, unicode) {
- var code = unicode.charCodeAt(0), gid = 0;
- var l = 0, r = ranges.length - 1;
- while (l < r) {
- var c = l + r + 1 >> 1;
- if (code < ranges[c].start) {
- r = c - 1;
- } else {
- l = c;
- }
- }
- if (ranges[l].start <= code && code <= ranges[l].end) {
- gid = ranges[l].idDelta + (ranges[l].ids ? ranges[l].ids[code - ranges[l].start] : code) & 0xFFFF;
- }
- return {
- charCode: code,
- glyphId: gid
- };
- }
- function compileGlyf(code, cmds, font) {
- function moveTo(x, y) {
- cmds.push({
- cmd: 'moveTo',
- args: [
- x,
- y
- ]
- });
- }
- function lineTo(x, y) {
- cmds.push({
- cmd: 'lineTo',
- args: [
- x,
- y
- ]
- });
- }
- function quadraticCurveTo(xa, ya, x, y) {
- cmds.push({
- cmd: 'quadraticCurveTo',
- args: [
- xa,
- ya,
- x,
- y
- ]
- });
- }
- var i = 0;
- var numberOfContours = (code[i] << 24 | code[i + 1] << 16) >> 16;
- var flags;
- var x = 0, y = 0;
- i += 10;
- if (numberOfContours < 0) {
- // composite glyph
- do {
- flags = code[i] << 8 | code[i + 1];
- var glyphIndex = code[i + 2] << 8 | code[i + 3];
- i += 4;
- var arg1, arg2;
- if (flags & 0x01) {
- arg1 = (code[i] << 24 | code[i + 1] << 16) >> 16;
- arg2 = (code[i + 2] << 24 | code[i + 3] << 16) >> 16;
- i += 4;
- } else {
- arg1 = code[i++];
- arg2 = code[i++];
- }
- if (flags & 0x02) {
- x = arg1;
- y = arg2;
- } else {
- x = 0;
- y = 0;
- }
- // TODO "they are points" ?
- var scaleX = 1, scaleY = 1, scale01 = 0, scale10 = 0;
- if (flags & 0x08) {
- scaleX = scaleY = (code[i] << 24 | code[i + 1] << 16) / 1073741824;
- i += 2;
- } else if (flags & 0x40) {
- scaleX = (code[i] << 24 | code[i + 1] << 16) / 1073741824;
- scaleY = (code[i + 2] << 24 | code[i + 3] << 16) / 1073741824;
- i += 4;
- } else if (flags & 0x80) {
- scaleX = (code[i] << 24 | code[i + 1] << 16) / 1073741824;
- scale01 = (code[i + 2] << 24 | code[i + 3] << 16) / 1073741824;
- scale10 = (code[i + 4] << 24 | code[i + 5] << 16) / 1073741824;
- scaleY = (code[i + 6] << 24 | code[i + 7] << 16) / 1073741824;
- i += 8;
- }
- var subglyph = font.glyphs[glyphIndex];
- if (subglyph) {
- cmds.push({ cmd: 'save' });
- cmds.push({
- cmd: 'transform',
- args: [
- scaleX,
- scale01,
- scale10,
- scaleY,
- x,
- y
- ]
- });
- compileGlyf(subglyph, cmds, font);
- cmds.push({ cmd: 'restore' });
- }
- } while (flags & 0x20);
- } else {
- // simple glyph
- var endPtsOfContours = [];
- var j, jj;
- for (j = 0; j < numberOfContours; j++) {
- endPtsOfContours.push(code[i] << 8 | code[i + 1]);
- i += 2;
- }
- var instructionLength = code[i] << 8 | code[i + 1];
- i += 2 + instructionLength;
- // skipping the instructions
- var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1;
- var points = [];
- while (points.length < numberOfPoints) {
- flags = code[i++];
- var repeat = 1;
- if (flags & 0x08) {
- repeat += code[i++];
- }
- while (repeat-- > 0) {
- points.push({ flags: flags });
- }
- }
- for (j = 0; j < numberOfPoints; j++) {
- switch (points[j].flags & 0x12) {
- case 0x00:
- x += (code[i] << 24 | code[i + 1] << 16) >> 16;
- i += 2;
- break;
- case 0x02:
- x -= code[i++];
- break;
- case 0x12:
- x += code[i++];
- break;
- }
- points[j].x = x;
- }
- for (j = 0; j < numberOfPoints; j++) {
- switch (points[j].flags & 0x24) {
- case 0x00:
- y += (code[i] << 24 | code[i + 1] << 16) >> 16;
- i += 2;
- break;
- case 0x04:
- y -= code[i++];
- break;
- case 0x24:
- y += code[i++];
- break;
- }
- points[j].y = y;
- }
- var startPoint = 0;
- for (i = 0; i < numberOfContours; i++) {
- var endPoint = endPtsOfContours[i];
- // contours might have implicit points, which is located in the middle
- // between two neighboring off-curve points
- var contour = points.slice(startPoint, endPoint + 1);
- if (contour[0].flags & 1) {
- contour.push(contour[0]);
- } else // using start point at the contour end
- if (contour[contour.length - 1].flags & 1) {
- // first is off-curve point, trying to use one from the end
- contour.unshift(contour[contour.length - 1]);
- } else {
- // start and end are off-curve points, creating implicit one
- var p = {
- flags: 1,
- x: (contour[0].x + contour[contour.length - 1].x) / 2,
- y: (contour[0].y + contour[contour.length - 1].y) / 2
- };
- contour.unshift(p);
- contour.push(p);
- }
- moveTo(contour[0].x, contour[0].y);
- for (j = 1, jj = contour.length; j < jj; j++) {
- if (contour[j].flags & 1) {
- lineTo(contour[j].x, contour[j].y);
- } else if (contour[j + 1].flags & 1) {
- quadraticCurveTo(contour[j].x, contour[j].y, contour[j + 1].x, contour[j + 1].y);
- j++;
- } else {
- quadraticCurveTo(contour[j].x, contour[j].y, (contour[j].x + contour[j + 1].x) / 2, (contour[j].y + contour[j + 1].y) / 2);
- }
- }
- startPoint = endPoint + 1;
- }
- }
- }
- function compileCharString(code, cmds, font) {
- var stack = [];
- var x = 0, y = 0;
- var stems = 0;
- function moveTo(x, y) {
- cmds.push({
- cmd: 'moveTo',
- args: [
- x,
- y
- ]
- });
- }
- function lineTo(x, y) {
- cmds.push({
- cmd: 'lineTo',
- args: [
- x,
- y
- ]
- });
- }
- function bezierCurveTo(x1, y1, x2, y2, x, y) {
- cmds.push({
- cmd: 'bezierCurveTo',
- args: [
- x1,
- y1,
- x2,
- y2,
- x,
- y
- ]
- });
- }
- function parse(code) {
- var i = 0;
- while (i < code.length) {
- var stackClean = false;
- var v = code[i++];
- var xa, xb, ya, yb, y1, y2, y3, n, subrCode;
- switch (v) {
- case 1:
- // hstem
- stems += stack.length >> 1;
- stackClean = true;
- break;
- case 3:
- // vstem
- stems += stack.length >> 1;
- stackClean = true;
- break;
- case 4:
- // vmoveto
- y += stack.pop();
- moveTo(x, y);
- stackClean = true;
- break;
- case 5:
- // rlineto
- while (stack.length > 0) {
- x += stack.shift();
- y += stack.shift();
- lineTo(x, y);
- }
- break;
- case 6:
- // hlineto
- while (stack.length > 0) {
- x += stack.shift();
- lineTo(x, y);
- if (stack.length === 0) {
- break;
- }
- y += stack.shift();
- lineTo(x, y);
- }
- break;
- case 7:
- // vlineto
- while (stack.length > 0) {
- y += stack.shift();
- lineTo(x, y);
- if (stack.length === 0) {
- break;
- }
- x += stack.shift();
- lineTo(x, y);
- }
- break;
- case 8:
- // rrcurveto
- while (stack.length > 0) {
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- break;
- case 10:
- // callsubr
- n = stack.pop() + font.subrsBias;
- subrCode = font.subrs[n];
- if (subrCode) {
- parse(subrCode);
- }
- break;
- case 11:
- // return
- return;
- case 12:
- v = code[i++];
- switch (v) {
- case 34:
- // flex
- xa = x + stack.shift();
- xb = xa + stack.shift();
- y1 = y + stack.shift();
- x = xb + stack.shift();
- bezierCurveTo(xa, y, xb, y1, x, y1);
- xa = x + stack.shift();
- xb = xa + stack.shift();
- x = xb + stack.shift();
- bezierCurveTo(xa, y1, xb, y, x, y);
- break;
- case 35:
- // flex
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- stack.pop();
- // fd
- break;
- case 36:
- // hflex1
- xa = x + stack.shift();
- y1 = y + stack.shift();
- xb = xa + stack.shift();
- y2 = y1 + stack.shift();
- x = xb + stack.shift();
- bezierCurveTo(xa, y1, xb, y2, x, y2);
- xa = x + stack.shift();
- xb = xa + stack.shift();
- y3 = y2 + stack.shift();
- x = xb + stack.shift();
- bezierCurveTo(xa, y2, xb, y3, x, y);
- break;
- case 37:
- // flex1
- var x0 = x, y0 = y;
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb;
- y = yb;
- if (Math.abs(x - x0) > Math.abs(y - y0)) {
- x += stack.shift();
- } else {
- y += stack.shift();
- }
- bezierCurveTo(xa, ya, xb, yb, x, y);
- break;
- default:
- error('unknown operator: 12 ' + v);
- }
- break;
- case 14:
- // endchar
- if (stack.length >= 4) {
- var achar = stack.pop();
- var bchar = stack.pop();
- y = stack.pop();
- x = stack.pop();
- cmds.push({ cmd: 'save' });
- cmds.push({
- cmd: 'translate',
- args: [
- x,
- y
- ]
- });
- var cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[achar]]));
- compileCharString(font.glyphs[cmap.glyphId], cmds, font);
- cmds.push({ cmd: 'restore' });
- cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[bchar]]));
- compileCharString(font.glyphs[cmap.glyphId], cmds, font);
- }
- return;
- case 18:
- // hstemhm
- stems += stack.length >> 1;
- stackClean = true;
- break;
- case 19:
- // hintmask
- stems += stack.length >> 1;
- i += stems + 7 >> 3;
- stackClean = true;
- break;
- case 20:
- // cntrmask
- stems += stack.length >> 1;
- i += stems + 7 >> 3;
- stackClean = true;
- break;
- case 21:
- // rmoveto
- y += stack.pop();
- x += stack.pop();
- moveTo(x, y);
- stackClean = true;
- break;
- case 22:
- // hmoveto
- x += stack.pop();
- moveTo(x, y);
- stackClean = true;
- break;
- case 23:
- // vstemhm
- stems += stack.length >> 1;
- stackClean = true;
- break;
- case 24:
- // rcurveline
- while (stack.length > 2) {
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- x += stack.shift();
- y += stack.shift();
- lineTo(x, y);
- break;
- case 25:
- // rlinecurve
- while (stack.length > 6) {
- x += stack.shift();
- y += stack.shift();
- lineTo(x, y);
- }
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- break;
- case 26:
- // vvcurveto
- if (stack.length % 2) {
- x += stack.shift();
- }
- while (stack.length > 0) {
- xa = x;
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb;
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- break;
- case 27:
- // hhcurveto
- if (stack.length % 2) {
- y += stack.shift();
- }
- while (stack.length > 0) {
- xa = x + stack.shift();
- ya = y;
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb;
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- break;
- case 28:
- stack.push((code[i] << 24 | code[i + 1] << 16) >> 16);
- i += 2;
- break;
- case 29:
- // callgsubr
- n = stack.pop() + font.gsubrsBias;
- subrCode = font.gsubrs[n];
- if (subrCode) {
- parse(subrCode);
- }
- break;
- case 30:
- // vhcurveto
- while (stack.length > 0) {
- xa = x;
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + (stack.length === 1 ? stack.shift() : 0);
- bezierCurveTo(xa, ya, xb, yb, x, y);
- if (stack.length === 0) {
- break;
- }
- xa = x + stack.shift();
- ya = y;
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- y = yb + stack.shift();
- x = xb + (stack.length === 1 ? stack.shift() : 0);
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- break;
- case 31:
- // hvcurveto
- while (stack.length > 0) {
- xa = x + stack.shift();
- ya = y;
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- y = yb + stack.shift();
- x = xb + (stack.length === 1 ? stack.shift() : 0);
- bezierCurveTo(xa, ya, xb, yb, x, y);
- if (stack.length === 0) {
- break;
- }
- xa = x;
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + (stack.length === 1 ? stack.shift() : 0);
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- break;
- default:
- if (v < 32) {
- error('unknown operator: ' + v);
- }
- if (v < 247) {
- stack.push(v - 139);
- } else if (v < 251) {
- stack.push((v - 247) * 256 + code[i++] + 108);
- } else if (v < 255) {
- stack.push(-(v - 251) * 256 - code[i++] - 108);
- } else {
- stack.push((code[i] << 24 | code[i + 1] << 16 | code[i + 2] << 8 | code[i + 3]) / 65536);
- i += 4;
- }
- break;
- }
- if (stackClean) {
- stack.length = 0;
- }
- }
- }
- parse(code);
- }
- var noop = '';
- function CompiledFont(fontMatrix) {
- this.compiledGlyphs = Object.create(null);
- this.compiledCharCodeToGlyphId = Object.create(null);
- this.fontMatrix = fontMatrix;
- }
- CompiledFont.prototype = {
- getPathJs: function (unicode) {
- var cmap = lookupCmap(this.cmap, unicode);
- var fn = this.compiledGlyphs[cmap.glyphId];
- if (!fn) {
- fn = this.compileGlyph(this.glyphs[cmap.glyphId]);
- this.compiledGlyphs[cmap.glyphId] = fn;
- }
- if (this.compiledCharCodeToGlyphId[cmap.charCode] === undefined) {
- this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId;
- }
- return fn;
- },
- compileGlyph: function (code) {
- if (!code || code.length === 0 || code[0] === 14) {
- return noop;
- }
- var cmds = [];
- cmds.push({ cmd: 'save' });
- cmds.push({
- cmd: 'transform',
- args: this.fontMatrix.slice()
- });
- cmds.push({
- cmd: 'scale',
- args: [
- 'size',
- '-size'
- ]
- });
- this.compileGlyphImpl(code, cmds);
- cmds.push({ cmd: 'restore' });
- return cmds;
- },
- compileGlyphImpl: function () {
- error('Children classes should implement this.');
- },
- hasBuiltPath: function (unicode) {
- var cmap = lookupCmap(this.cmap, unicode);
- return this.compiledGlyphs[cmap.glyphId] !== undefined && this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined;
- }
- };
- function TrueTypeCompiled(glyphs, cmap, fontMatrix) {
- fontMatrix = fontMatrix || [
- 0.000488,
- 0,
- 0,
- 0.000488,
- 0,
- 0
- ];
- CompiledFont.call(this, fontMatrix);
- this.glyphs = glyphs;
- this.cmap = cmap;
- }
- Util.inherit(TrueTypeCompiled, CompiledFont, {
- compileGlyphImpl: function (code, cmds) {
- compileGlyf(code, cmds, this);
- }
- });
- function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) {
- fontMatrix = fontMatrix || [
- 0.001,
- 0,
- 0,
- 0.001,
- 0,
- 0
- ];
- CompiledFont.call(this, fontMatrix);
- this.glyphs = cffInfo.glyphs;
- this.gsubrs = cffInfo.gsubrs || [];
- this.subrs = cffInfo.subrs || [];
- this.cmap = cmap;
- this.glyphNameMap = glyphNameMap || getGlyphsUnicode();
- this.gsubrsBias = this.gsubrs.length < 1240 ? 107 : this.gsubrs.length < 33900 ? 1131 : 32768;
- this.subrsBias = this.subrs.length < 1240 ? 107 : this.subrs.length < 33900 ? 1131 : 32768;
- }
- Util.inherit(Type2Compiled, CompiledFont, {
- compileGlyphImpl: function (code, cmds) {
- compileCharString(code, cmds, this);
- }
- });
- return {
- create: function FontRendererFactory_create(font, seacAnalysisEnabled) {
- var data = new Uint8Array(font.data);
- var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm;
- var numTables = getUshort(data, 4);
- for (var i = 0, p = 12; i < numTables; i++, p += 16) {
- var tag = bytesToString(data.subarray(p, p + 4));
- var offset = getLong(data, p + 8);
- var length = getLong(data, p + 12);
- switch (tag) {
- case 'cmap':
- cmap = parseCmap(data, offset, offset + length);
- break;
- case 'glyf':
- glyf = data.subarray(offset, offset + length);
- break;
- case 'loca':
- loca = data.subarray(offset, offset + length);
- break;
- case 'head':
- unitsPerEm = getUshort(data, offset + 18);
- indexToLocFormat = getUshort(data, offset + 50);
- break;
- case 'CFF ':
- cff = parseCff(data, offset, offset + length, seacAnalysisEnabled);
- break;
- }
- }
- if (glyf) {
- var fontMatrix = !unitsPerEm ? font.fontMatrix : [
- 1 / unitsPerEm,
- 0,
- 0,
- 1 / unitsPerEm,
- 0,
- 0
- ];
- return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);
- } else {
- return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap);
- }
- }
- };
- }();
- exports.FontRendererFactory = FontRendererFactory;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreParser = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreStream);
- }(this, function (exports, sharedUtil, corePrimitives, coreStream) {
- var MissingDataException = sharedUtil.MissingDataException;
- var StreamType = sharedUtil.StreamType;
- var assert = sharedUtil.assert;
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var isArray = sharedUtil.isArray;
- var isInt = sharedUtil.isInt;
- var isNum = sharedUtil.isNum;
- var isString = sharedUtil.isString;
- var warn = sharedUtil.warn;
- var Cmd = corePrimitives.Cmd;
- var Dict = corePrimitives.Dict;
- var Name = corePrimitives.Name;
- var Ref = corePrimitives.Ref;
- var isCmd = corePrimitives.isCmd;
- var isDict = corePrimitives.isDict;
- var isName = corePrimitives.isName;
- var Ascii85Stream = coreStream.Ascii85Stream;
- var AsciiHexStream = coreStream.AsciiHexStream;
- var CCITTFaxStream = coreStream.CCITTFaxStream;
- var FlateStream = coreStream.FlateStream;
- var Jbig2Stream = coreStream.Jbig2Stream;
- var JpegStream = coreStream.JpegStream;
- var JpxStream = coreStream.JpxStream;
- var LZWStream = coreStream.LZWStream;
- var NullStream = coreStream.NullStream;
- var PredictorStream = coreStream.PredictorStream;
- var RunLengthStream = coreStream.RunLengthStream;
- var EOF = {};
- function isEOF(v) {
- return v === EOF;
- }
- var MAX_LENGTH_TO_CACHE = 1000;
- var Parser = function ParserClosure() {
- function Parser(lexer, allowStreams, xref, recoveryMode) {
- this.lexer = lexer;
- this.allowStreams = allowStreams;
- this.xref = xref;
- this.recoveryMode = recoveryMode || false;
- this.imageCache = Object.create(null);
- this.refill();
- }
- Parser.prototype = {
- refill: function Parser_refill() {
- this.buf1 = this.lexer.getObj();
- this.buf2 = this.lexer.getObj();
- },
- shift: function Parser_shift() {
- if (isCmd(this.buf2, 'ID')) {
- this.buf1 = this.buf2;
- this.buf2 = null;
- } else {
- this.buf1 = this.buf2;
- this.buf2 = this.lexer.getObj();
- }
- },
- tryShift: function Parser_tryShift() {
- try {
- this.shift();
- return true;
- } catch (e) {
- if (e instanceof MissingDataException) {
- throw e;
- }
- // Upon failure, the caller should reset this.lexer.pos to a known good
- // state and call this.shift() twice to reset the buffers.
- return false;
- }
- },
- getObj: function Parser_getObj(cipherTransform) {
- var buf1 = this.buf1;
- this.shift();
- if (buf1 instanceof Cmd) {
- switch (buf1.cmd) {
- case 'BI':
- // inline image
- return this.makeInlineImage(cipherTransform);
- case '[':
- // array
- var array = [];
- while (!isCmd(this.buf1, ']') && !isEOF(this.buf1)) {
- array.push(this.getObj(cipherTransform));
- }
- if (isEOF(this.buf1)) {
- if (!this.recoveryMode) {
- error('End of file inside array');
- }
- return array;
- }
- this.shift();
- return array;
- case '<<':
- // dictionary or stream
- var dict = new Dict(this.xref);
- while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) {
- if (!isName(this.buf1)) {
- info('Malformed dictionary: key must be a name object');
- this.shift();
- continue;
- }
- var key = this.buf1.name;
- this.shift();
- if (isEOF(this.buf1)) {
- break;
- }
- dict.set(key, this.getObj(cipherTransform));
- }
- if (isEOF(this.buf1)) {
- if (!this.recoveryMode) {
- error('End of file inside dictionary');
- }
- return dict;
- }
- // Stream objects are not allowed inside content streams or
- // object streams.
- if (isCmd(this.buf2, 'stream')) {
- return this.allowStreams ? this.makeStream(dict, cipherTransform) : dict;
- }
- this.shift();
- return dict;
- default:
- // simple object
- return buf1;
- }
- }
- if (isInt(buf1)) {
- // indirect reference or integer
- var num = buf1;
- if (isInt(this.buf1) && isCmd(this.buf2, 'R')) {
- var ref = new Ref(num, this.buf1);
- this.shift();
- this.shift();
- return ref;
- }
- return num;
- }
- if (isString(buf1)) {
- // string
- var str = buf1;
- if (cipherTransform) {
- str = cipherTransform.decryptString(str);
- }
- return str;
- }
- // simple object
- return buf1;
- },
- /**
- * Find the end of the stream by searching for the /EI\s/.
- * @returns {number} The inline stream length.
- */
- findDefaultInlineStreamEnd: function Parser_findDefaultInlineStreamEnd(stream) {
- var E = 0x45, I = 0x49, SPACE = 0x20, LF = 0xA, CR = 0xD;
- var startPos = stream.pos, state = 0, ch, i, n, followingBytes;
- while ((ch = stream.getByte()) !== -1) {
- if (state === 0) {
- state = ch === E ? 1 : 0;
- } else if (state === 1) {
- state = ch === I ? 2 : 0;
- } else {
- assert(state === 2);
- if (ch === SPACE || ch === LF || ch === CR) {
- // Let's check the next five bytes are ASCII... just be sure.
- n = 5;
- followingBytes = stream.peekBytes(n);
- for (i = 0; i < n; i++) {
- ch = followingBytes[i];
- if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7F)) {
- // Not a LF, CR, SPACE or any visible ASCII character, i.e.
- // it's binary stuff. Resetting the state.
- state = 0;
- break;
- }
- }
- if (state === 2) {
- break;
- }
- } else
- // Finished!
- {
- state = 0;
- }
- }
- }
- return stream.pos - 4 - startPos;
- },
- /**
- * Find the EOI (end-of-image) marker 0xFFD9 of the stream.
- * @returns {number} The inline stream length.
- */
- findDCTDecodeInlineStreamEnd: function Parser_findDCTDecodeInlineStreamEnd(stream) {
- var startPos = stream.pos, foundEOI = false, b, markerLength, length;
- while ((b = stream.getByte()) !== -1) {
- if (b !== 0xFF) {
- // Not a valid marker.
- continue;
- }
- switch (stream.getByte()) {
- case 0x00:
- // Byte stuffing.
- // 0xFF00 appears to be a very common byte sequence in JPEG images.
- break;
- case 0xFF:
- // Fill byte.
- // Avoid skipping a valid marker, resetting the stream position.
- stream.skip(-1);
- break;
- case 0xD9:
- // EOI
- foundEOI = true;
- break;
- case 0xC0:
- // SOF0
- case 0xC1:
- // SOF1
- case 0xC2:
- // SOF2
- case 0xC3:
- // SOF3
- case 0xC5:
- // SOF5
- case 0xC6:
- // SOF6
- case 0xC7:
- // SOF7
- case 0xC9:
- // SOF9
- case 0xCA:
- // SOF10
- case 0xCB:
- // SOF11
- case 0xCD:
- // SOF13
- case 0xCE:
- // SOF14
- case 0xCF:
- // SOF15
- case 0xC4:
- // DHT
- case 0xCC:
- // DAC
- case 0xDA:
- // SOS
- case 0xDB:
- // DQT
- case 0xDC:
- // DNL
- case 0xDD:
- // DRI
- case 0xDE:
- // DHP
- case 0xDF:
- // EXP
- case 0xE0:
- // APP0
- case 0xE1:
- // APP1
- case 0xE2:
- // APP2
- case 0xE3:
- // APP3
- case 0xE4:
- // APP4
- case 0xE5:
- // APP5
- case 0xE6:
- // APP6
- case 0xE7:
- // APP7
- case 0xE8:
- // APP8
- case 0xE9:
- // APP9
- case 0xEA:
- // APP10
- case 0xEB:
- // APP11
- case 0xEC:
- // APP12
- case 0xED:
- // APP13
- case 0xEE:
- // APP14
- case 0xEF:
- // APP15
- case 0xFE:
- // COM
- // The marker should be followed by the length of the segment.
- markerLength = stream.getUint16();
- if (markerLength > 2) {
- // |markerLength| contains the byte length of the marker segment,
- // including its own length (2 bytes) and excluding the marker.
- stream.skip(markerLength - 2);
- } else
- // Jump to the next marker.
- {
- // The marker length is invalid, resetting the stream position.
- stream.skip(-2);
- }
- break;
- }
- if (foundEOI) {
- break;
- }
- }
- length = stream.pos - startPos;
- if (b === -1) {
- warn('Inline DCTDecode image stream: ' + 'EOI marker not found, searching for /EI/ instead.');
- stream.skip(-length);
- // Reset the stream position.
- return this.findDefaultInlineStreamEnd(stream);
- }
- this.inlineStreamSkipEI(stream);
- return length;
- },
- /**
- * Find the EOD (end-of-data) marker '~>' (i.e. TILDE + GT) of the stream.
- * @returns {number} The inline stream length.
- */
- findASCII85DecodeInlineStreamEnd: function Parser_findASCII85DecodeInlineStreamEnd(stream) {
- var TILDE = 0x7E, GT = 0x3E;
- var startPos = stream.pos, ch, length;
- while ((ch = stream.getByte()) !== -1) {
- if (ch === TILDE && stream.peekByte() === GT) {
- stream.skip();
- break;
- }
- }
- length = stream.pos - startPos;
- if (ch === -1) {
- warn('Inline ASCII85Decode image stream: ' + 'EOD marker not found, searching for /EI/ instead.');
- stream.skip(-length);
- // Reset the stream position.
- return this.findDefaultInlineStreamEnd(stream);
- }
- this.inlineStreamSkipEI(stream);
- return length;
- },
- /**
- * Find the EOD (end-of-data) marker '>' (i.e. GT) of the stream.
- * @returns {number} The inline stream length.
- */
- findASCIIHexDecodeInlineStreamEnd: function Parser_findASCIIHexDecodeInlineStreamEnd(stream) {
- var GT = 0x3E;
- var startPos = stream.pos, ch, length;
- while ((ch = stream.getByte()) !== -1) {
- if (ch === GT) {
- break;
- }
- }
- length = stream.pos - startPos;
- if (ch === -1) {
- warn('Inline ASCIIHexDecode image stream: ' + 'EOD marker not found, searching for /EI/ instead.');
- stream.skip(-length);
- // Reset the stream position.
- return this.findDefaultInlineStreamEnd(stream);
- }
- this.inlineStreamSkipEI(stream);
- return length;
- },
- /**
- * Skip over the /EI/ for streams where we search for an EOD marker.
- */
- inlineStreamSkipEI: function Parser_inlineStreamSkipEI(stream) {
- var E = 0x45, I = 0x49;
- var state = 0, ch;
- while ((ch = stream.getByte()) !== -1) {
- if (state === 0) {
- state = ch === E ? 1 : 0;
- } else if (state === 1) {
- state = ch === I ? 2 : 0;
- } else if (state === 2) {
- break;
- }
- }
- },
- makeInlineImage: function Parser_makeInlineImage(cipherTransform) {
- var lexer = this.lexer;
- var stream = lexer.stream;
- // Parse dictionary.
- var dict = new Dict(this.xref);
- while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
- if (!isName(this.buf1)) {
- error('Dictionary key must be a name object');
- }
- var key = this.buf1.name;
- this.shift();
- if (isEOF(this.buf1)) {
- break;
- }
- dict.set(key, this.getObj(cipherTransform));
- }
- // Extract the name of the first (i.e. the current) image filter.
- var filter = dict.get('Filter', 'F'), filterName;
- if (isName(filter)) {
- filterName = filter.name;
- } else if (isArray(filter) && isName(filter[0])) {
- filterName = filter[0].name;
- }
- // Parse image stream.
- var startPos = stream.pos, length, i, ii;
- if (filterName === 'DCTDecode' || filterName === 'DCT') {
- length = this.findDCTDecodeInlineStreamEnd(stream);
- } else if (filterName === 'ASCII85Decide' || filterName === 'A85') {
- length = this.findASCII85DecodeInlineStreamEnd(stream);
- } else if (filterName === 'ASCIIHexDecode' || filterName === 'AHx') {
- length = this.findASCIIHexDecodeInlineStreamEnd(stream);
- } else {
- length = this.findDefaultInlineStreamEnd(stream);
- }
- var imageStream = stream.makeSubStream(startPos, length, dict);
- // Cache all images below the MAX_LENGTH_TO_CACHE threshold by their
- // adler32 checksum.
- var adler32;
- if (length < MAX_LENGTH_TO_CACHE) {
- var imageBytes = imageStream.getBytes();
- imageStream.reset();
- var a = 1;
- var b = 0;
- for (i = 0, ii = imageBytes.length; i < ii; ++i) {
- // No modulo required in the loop if imageBytes.length < 5552.
- a += imageBytes[i] & 0xff;
- b += a;
- }
- adler32 = b % 65521 << 16 | a % 65521;
- if (this.imageCache.adler32 === adler32) {
- this.buf2 = Cmd.get('EI');
- this.shift();
- this.imageCache[adler32].reset();
- return this.imageCache[adler32];
- }
- }
- if (cipherTransform) {
- imageStream = cipherTransform.createStream(imageStream, length);
- }
- imageStream = this.filter(imageStream, dict, length);
- imageStream.dict = dict;
- if (adler32 !== undefined) {
- imageStream.cacheKey = 'inline_' + length + '_' + adler32;
- this.imageCache[adler32] = imageStream;
- }
- this.buf2 = Cmd.get('EI');
- this.shift();
- return imageStream;
- },
- makeStream: function Parser_makeStream(dict, cipherTransform) {
- var lexer = this.lexer;
- var stream = lexer.stream;
- // get stream start position
- lexer.skipToNextLine();
- var pos = stream.pos - 1;
- // get length
- var length = dict.get('Length');
- if (!isInt(length)) {
- info('Bad ' + length + ' attribute in stream');
- length = 0;
- }
- // skip over the stream data
- stream.pos = pos + length;
- lexer.nextChar();
- // Shift '>>' and check whether the new object marks the end of the stream
- if (this.tryShift() && isCmd(this.buf2, 'endstream')) {
- this.shift();
- } else
- // 'stream'
- {
- // bad stream length, scanning for endstream
- stream.pos = pos;
- var SCAN_BLOCK_SIZE = 2048;
- var ENDSTREAM_SIGNATURE_LENGTH = 9;
- var ENDSTREAM_SIGNATURE = [
- 0x65,
- 0x6E,
- 0x64,
- 0x73,
- 0x74,
- 0x72,
- 0x65,
- 0x61,
- 0x6D
- ];
- var skipped = 0, found = false, i, j;
- while (stream.pos < stream.end) {
- var scanBytes = stream.peekBytes(SCAN_BLOCK_SIZE);
- var scanLength = scanBytes.length - ENDSTREAM_SIGNATURE_LENGTH;
- if (scanLength <= 0) {
- break;
- }
- found = false;
- i = 0;
- while (i < scanLength) {
- j = 0;
- while (j < ENDSTREAM_SIGNATURE_LENGTH && scanBytes[i + j] === ENDSTREAM_SIGNATURE[j]) {
- j++;
- }
- if (j >= ENDSTREAM_SIGNATURE_LENGTH) {
- found = true;
- break;
- }
- i++;
- }
- if (found) {
- skipped += i;
- stream.pos += i;
- break;
- }
- skipped += scanLength;
- stream.pos += scanLength;
- }
- if (!found) {
- error('Missing endstream');
- }
- length = skipped;
- lexer.nextChar();
- this.shift();
- this.shift();
- }
- this.shift();
- // 'endstream'
- stream = stream.makeSubStream(pos, length, dict);
- if (cipherTransform) {
- stream = cipherTransform.createStream(stream, length);
- }
- stream = this.filter(stream, dict, length);
- stream.dict = dict;
- return stream;
- },
- filter: function Parser_filter(stream, dict, length) {
- var filter = dict.get('Filter', 'F');
- var params = dict.get('DecodeParms', 'DP');
- if (isName(filter)) {
- if (isArray(params)) {
- params = params[0];
- }
- return this.makeFilter(stream, filter.name, length, params);
- }
- var maybeLength = length;
- if (isArray(filter)) {
- var filterArray = filter;
- var paramsArray = params;
- for (var i = 0, ii = filterArray.length; i < ii; ++i) {
- filter = filterArray[i];
- if (!isName(filter)) {
- error('Bad filter name: ' + filter);
- }
- params = null;
- if (isArray(paramsArray) && i in paramsArray) {
- params = paramsArray[i];
- }
- stream = this.makeFilter(stream, filter.name, maybeLength, params);
- // after the first stream the length variable is invalid
- maybeLength = null;
- }
- }
- return stream;
- },
- makeFilter: function Parser_makeFilter(stream, name, maybeLength, params) {
- // Since the 'Length' entry in the stream dictionary can be completely
- // wrong, e.g. zero for non-empty streams, only skip parsing the stream
- // when we can be absolutely certain that it actually is empty.
- if (maybeLength === 0) {
- warn('Empty "' + name + '" stream.');
- return new NullStream(stream);
- }
- try {
- if (params && this.xref) {
- params = this.xref.fetchIfRef(params);
- }
- var xrefStreamStats = this.xref.stats.streamTypes;
- if (name === 'FlateDecode' || name === 'Fl') {
- xrefStreamStats[StreamType.FLATE] = true;
- if (params) {
- return new PredictorStream(new FlateStream(stream, maybeLength), maybeLength, params);
- }
- return new FlateStream(stream, maybeLength);
- }
- if (name === 'LZWDecode' || name === 'LZW') {
- xrefStreamStats[StreamType.LZW] = true;
- var earlyChange = 1;
- if (params) {
- if (params.has('EarlyChange')) {
- earlyChange = params.get('EarlyChange');
- }
- return new PredictorStream(new LZWStream(stream, maybeLength, earlyChange), maybeLength, params);
- }
- return new LZWStream(stream, maybeLength, earlyChange);
- }
- if (name === 'DCTDecode' || name === 'DCT') {
- xrefStreamStats[StreamType.DCT] = true;
- return new JpegStream(stream, maybeLength, stream.dict, params);
- }
- if (name === 'JPXDecode' || name === 'JPX') {
- xrefStreamStats[StreamType.JPX] = true;
- return new JpxStream(stream, maybeLength, stream.dict, params);
- }
- if (name === 'ASCII85Decode' || name === 'A85') {
- xrefStreamStats[StreamType.A85] = true;
- return new Ascii85Stream(stream, maybeLength);
- }
- if (name === 'ASCIIHexDecode' || name === 'AHx') {
- xrefStreamStats[StreamType.AHX] = true;
- return new AsciiHexStream(stream, maybeLength);
- }
- if (name === 'CCITTFaxDecode' || name === 'CCF') {
- xrefStreamStats[StreamType.CCF] = true;
- return new CCITTFaxStream(stream, maybeLength, params);
- }
- if (name === 'RunLengthDecode' || name === 'RL') {
- xrefStreamStats[StreamType.RL] = true;
- return new RunLengthStream(stream, maybeLength);
- }
- if (name === 'JBIG2Decode') {
- xrefStreamStats[StreamType.JBIG] = true;
- return new Jbig2Stream(stream, maybeLength, stream.dict, params);
- }
- warn('filter "' + name + '" not supported yet');
- return stream;
- } catch (ex) {
- if (ex instanceof MissingDataException) {
- throw ex;
- }
- warn('Invalid stream: \"' + ex + '\"');
- return new NullStream(stream);
- }
- }
- };
- return Parser;
- }();
- var Lexer = function LexerClosure() {
- function Lexer(stream, knownCommands) {
- this.stream = stream;
- this.nextChar();
- // While lexing, we build up many strings one char at a time. Using += for
- // this can result in lots of garbage strings. It's better to build an
- // array of single-char strings and then join() them together at the end.
- // And reusing a single array (i.e. |this.strBuf|) over and over for this
- // purpose uses less memory than using a new array for each string.
- this.strBuf = [];
- // The PDFs might have "glued" commands with other commands, operands or
- // literals, e.g. "q1". The knownCommands is a dictionary of the valid
- // commands and their prefixes. The prefixes are built the following way:
- // if there a command that is a prefix of the other valid command or
- // literal (e.g. 'f' and 'false') the following prefixes must be included,
- // 'fa', 'fal', 'fals'. The prefixes are not needed, if the command has no
- // other commands or literals as a prefix. The knowCommands is optional.
- this.knownCommands = knownCommands;
- }
- // A '1' in this array means the character is white space. A '1' or
- // '2' means the character ends a name or command.
- var specialChars = [
- 1,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 1,
- 1,
- 0,
- 1,
- 1,
- 0,
- 0,
- // 0x
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- // 1x
- 1,
- 0,
- 0,
- 0,
- 0,
- 2,
- 0,
- 0,
- 2,
- 2,
- 0,
- 0,
- 0,
- 0,
- 0,
- 2,
- // 2x
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 2,
- 0,
- 2,
- 0,
- // 3x
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- // 4x
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 2,
- 0,
- 2,
- 0,
- 0,
- // 5x
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- // 6x
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 2,
- 0,
- 2,
- 0,
- 0,
- // 7x
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- // 8x
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- // 9x
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- // ax
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- // bx
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- // cx
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- // dx
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- // ex
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0
- ];
- // fx
- function toHexDigit(ch) {
- if (ch >= 0x30 && ch <= 0x39) {
- // '0'-'9'
- return ch & 0x0F;
- }
- if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) {
- // 'A'-'F', 'a'-'f'
- return (ch & 0x0F) + 9;
- }
- return -1;
- }
- Lexer.prototype = {
- nextChar: function Lexer_nextChar() {
- return this.currentChar = this.stream.getByte();
- },
- peekChar: function Lexer_peekChar() {
- return this.stream.peekByte();
- },
- getNumber: function Lexer_getNumber() {
- var ch = this.currentChar;
- var eNotation = false;
- var divideBy = 0;
- // different from 0 if it's a floating point value
- var sign = 1;
- if (ch === 0x2D) {
- // '-'
- sign = -1;
- ch = this.nextChar();
- if (ch === 0x2D) {
- // '-'
- // Ignore double negative (this is consistent with Adobe Reader).
- ch = this.nextChar();
- }
- } else if (ch === 0x2B) {
- // '+'
- ch = this.nextChar();
- }
- if (ch === 0x2E) {
- // '.'
- divideBy = 10;
- ch = this.nextChar();
- }
- if (ch < 0x30 || ch > 0x39) {
- // '0' - '9'
- error('Invalid number: ' + String.fromCharCode(ch));
- return 0;
- }
- var baseValue = ch - 0x30;
- // '0'
- var powerValue = 0;
- var powerValueSign = 1;
- while ((ch = this.nextChar()) >= 0) {
- if (0x30 <= ch && ch <= 0x39) {
- // '0' - '9'
- var currentDigit = ch - 0x30;
- // '0'
- if (eNotation) {
- // We are after an 'e' or 'E'
- powerValue = powerValue * 10 + currentDigit;
- } else {
- if (divideBy !== 0) {
- // We are after a point
- divideBy *= 10;
- }
- baseValue = baseValue * 10 + currentDigit;
- }
- } else if (ch === 0x2E) {
- // '.'
- if (divideBy === 0) {
- divideBy = 1;
- } else {
- // A number can have only one '.'
- break;
- }
- } else if (ch === 0x2D) {
- // '-'
- // ignore minus signs in the middle of numbers to match
- // Adobe's behavior
- warn('Badly formatted number');
- } else if (ch === 0x45 || ch === 0x65) {
- // 'E', 'e'
- // 'E' can be either a scientific notation or the beginning of a new
- // operator
- ch = this.peekChar();
- if (ch === 0x2B || ch === 0x2D) {
- // '+', '-'
- powerValueSign = ch === 0x2D ? -1 : 1;
- this.nextChar();
- } else // Consume the sign character
- if (ch < 0x30 || ch > 0x39) {
- // '0' - '9'
- // The 'E' must be the beginning of a new operator
- break;
- }
- eNotation = true;
- } else {
- // the last character doesn't belong to us
- break;
- }
- }
- if (divideBy !== 0) {
- baseValue /= divideBy;
- }
- if (eNotation) {
- baseValue *= Math.pow(10, powerValueSign * powerValue);
- }
- return sign * baseValue;
- },
- getString: function Lexer_getString() {
- var numParen = 1;
- var done = false;
- var strBuf = this.strBuf;
- strBuf.length = 0;
- var ch = this.nextChar();
- while (true) {
- var charBuffered = false;
- switch (ch | 0) {
- case -1:
- warn('Unterminated string');
- done = true;
- break;
- case 0x28:
- // '('
- ++numParen;
- strBuf.push('(');
- break;
- case 0x29:
- // ')'
- if (--numParen === 0) {
- this.nextChar();
- // consume strings ')'
- done = true;
- } else {
- strBuf.push(')');
- }
- break;
- case 0x5C:
- // '\\'
- ch = this.nextChar();
- switch (ch) {
- case -1:
- warn('Unterminated string');
- done = true;
- break;
- case 0x6E:
- // 'n'
- strBuf.push('\n');
- break;
- case 0x72:
- // 'r'
- strBuf.push('\r');
- break;
- case 0x74:
- // 't'
- strBuf.push('\t');
- break;
- case 0x62:
- // 'b'
- strBuf.push('\b');
- break;
- case 0x66:
- // 'f'
- strBuf.push('\f');
- break;
- case 0x5C:
- // '\'
- case 0x28:
- // '('
- case 0x29:
- // ')'
- strBuf.push(String.fromCharCode(ch));
- break;
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- // '0'-'3'
- case 0x34:
- case 0x35:
- case 0x36:
- case 0x37:
- // '4'-'7'
- var x = ch & 0x0F;
- ch = this.nextChar();
- charBuffered = true;
- if (ch >= 0x30 && ch <= 0x37) {
- // '0'-'7'
- x = (x << 3) + (ch & 0x0F);
- ch = this.nextChar();
- if (ch >= 0x30 && ch <= 0x37) {
- // '0'-'7'
- charBuffered = false;
- x = (x << 3) + (ch & 0x0F);
- }
- }
- strBuf.push(String.fromCharCode(x));
- break;
- case 0x0D:
- // CR
- if (this.peekChar() === 0x0A) {
- // LF
- this.nextChar();
- }
- break;
- case 0x0A:
- // LF
- break;
- default:
- strBuf.push(String.fromCharCode(ch));
- break;
- }
- break;
- default:
- strBuf.push(String.fromCharCode(ch));
- break;
- }
- if (done) {
- break;
- }
- if (!charBuffered) {
- ch = this.nextChar();
- }
- }
- return strBuf.join('');
- },
- getName: function Lexer_getName() {
- var ch, previousCh;
- var strBuf = this.strBuf;
- strBuf.length = 0;
- while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
- if (ch === 0x23) {
- // '#'
- ch = this.nextChar();
- if (specialChars[ch]) {
- warn('Lexer_getName: ' + 'NUMBER SIGN (#) should be followed by a hexadecimal number.');
- strBuf.push('#');
- break;
- }
- var x = toHexDigit(ch);
- if (x !== -1) {
- previousCh = ch;
- ch = this.nextChar();
- var x2 = toHexDigit(ch);
- if (x2 === -1) {
- warn('Lexer_getName: Illegal digit (' + String.fromCharCode(ch) + ') in hexadecimal number.');
- strBuf.push('#', String.fromCharCode(previousCh));
- if (specialChars[ch]) {
- break;
- }
- strBuf.push(String.fromCharCode(ch));
- continue;
- }
- strBuf.push(String.fromCharCode(x << 4 | x2));
- } else {
- strBuf.push('#', String.fromCharCode(ch));
- }
- } else {
- strBuf.push(String.fromCharCode(ch));
- }
- }
- if (strBuf.length > 127) {
- warn('name token is longer than allowed by the spec: ' + strBuf.length);
- }
- return Name.get(strBuf.join(''));
- },
- getHexString: function Lexer_getHexString() {
- var strBuf = this.strBuf;
- strBuf.length = 0;
- var ch = this.currentChar;
- var isFirstHex = true;
- var firstDigit;
- var secondDigit;
- while (true) {
- if (ch < 0) {
- warn('Unterminated hex string');
- break;
- } else if (ch === 0x3E) {
- // '>'
- this.nextChar();
- break;
- } else if (specialChars[ch] === 1) {
- ch = this.nextChar();
- continue;
- } else {
- if (isFirstHex) {
- firstDigit = toHexDigit(ch);
- if (firstDigit === -1) {
- warn('Ignoring invalid character "' + ch + '" in hex string');
- ch = this.nextChar();
- continue;
- }
- } else {
- secondDigit = toHexDigit(ch);
- if (secondDigit === -1) {
- warn('Ignoring invalid character "' + ch + '" in hex string');
- ch = this.nextChar();
- continue;
- }
- strBuf.push(String.fromCharCode(firstDigit << 4 | secondDigit));
- }
- isFirstHex = !isFirstHex;
- ch = this.nextChar();
- }
- }
- return strBuf.join('');
- },
- getObj: function Lexer_getObj() {
- // skip whitespace and comments
- var comment = false;
- var ch = this.currentChar;
- while (true) {
- if (ch < 0) {
- return EOF;
- }
- if (comment) {
- if (ch === 0x0A || ch === 0x0D) {
- // LF, CR
- comment = false;
- }
- } else if (ch === 0x25) {
- // '%'
- comment = true;
- } else if (specialChars[ch] !== 1) {
- break;
- }
- ch = this.nextChar();
- }
- // start reading token
- switch (ch | 0) {
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- case 0x34:
- // '0'-'4'
- case 0x35:
- case 0x36:
- case 0x37:
- case 0x38:
- case 0x39:
- // '5'-'9'
- case 0x2B:
- case 0x2D:
- case 0x2E:
- // '+', '-', '.'
- return this.getNumber();
- case 0x28:
- // '('
- return this.getString();
- case 0x2F:
- // '/'
- return this.getName();
- // array punctuation
- case 0x5B:
- // '['
- this.nextChar();
- return Cmd.get('[');
- case 0x5D:
- // ']'
- this.nextChar();
- return Cmd.get(']');
- // hex string or dict punctuation
- case 0x3C:
- // '<'
- ch = this.nextChar();
- if (ch === 0x3C) {
- // dict punctuation
- this.nextChar();
- return Cmd.get('<<');
- }
- return this.getHexString();
- // dict punctuation
- case 0x3E:
- // '>'
- ch = this.nextChar();
- if (ch === 0x3E) {
- this.nextChar();
- return Cmd.get('>>');
- }
- return Cmd.get('>');
- case 0x7B:
- // '{'
- this.nextChar();
- return Cmd.get('{');
- case 0x7D:
- // '}'
- this.nextChar();
- return Cmd.get('}');
- case 0x29:
- // ')'
- error('Illegal character: ' + ch);
- break;
- }
- // command
- var str = String.fromCharCode(ch);
- var knownCommands = this.knownCommands;
- var knownCommandFound = knownCommands && knownCommands[str] !== undefined;
- while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
- // stop if known command is found and next character does not make
- // the str a command
- var possibleCommand = str + String.fromCharCode(ch);
- if (knownCommandFound && knownCommands[possibleCommand] === undefined) {
- break;
- }
- if (str.length === 128) {
- error('Command token too long: ' + str.length);
- }
- str = possibleCommand;
- knownCommandFound = knownCommands && knownCommands[str] !== undefined;
- }
- if (str === 'true') {
- return true;
- }
- if (str === 'false') {
- return false;
- }
- if (str === 'null') {
- return null;
- }
- return Cmd.get(str);
- },
- skipToNextLine: function Lexer_skipToNextLine() {
- var ch = this.currentChar;
- while (ch >= 0) {
- if (ch === 0x0D) {
- // CR
- ch = this.nextChar();
- if (ch === 0x0A) {
- // LF
- this.nextChar();
- }
- break;
- } else if (ch === 0x0A) {
- // LF
- this.nextChar();
- break;
- }
- ch = this.nextChar();
- }
- }
- };
- return Lexer;
- }();
- var Linearization = {
- create: function LinearizationCreate(stream) {
- function getInt(name, allowZeroValue) {
- var obj = linDict.get(name);
- if (isInt(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) {
- return obj;
- }
- throw new Error('The "' + name + '" parameter in the linearization ' + 'dictionary is invalid.');
- }
- function getHints() {
- var hints = linDict.get('H'), hintsLength, item;
- if (isArray(hints) && ((hintsLength = hints.length) === 2 || hintsLength === 4)) {
- for (var index = 0; index < hintsLength; index++) {
- if (!(isInt(item = hints[index]) && item > 0)) {
- throw new Error('Hint (' + index + ') in the linearization dictionary is invalid.');
- }
- }
- return hints;
- }
- throw new Error('Hint array in the linearization dictionary is invalid.');
- }
- var parser = new Parser(new Lexer(stream), false, null);
- var obj1 = parser.getObj();
- var obj2 = parser.getObj();
- var obj3 = parser.getObj();
- var linDict = parser.getObj();
- var obj, length;
- if (!(isInt(obj1) && isInt(obj2) && isCmd(obj3, 'obj') && isDict(linDict) && isNum(obj = linDict.get('Linearized')) && obj > 0)) {
- return null;
- } else // No valid linearization dictionary found.
- if ((length = getInt('L')) !== stream.length) {
- throw new Error('The "L" parameter in the linearization dictionary ' + 'does not equal the stream length.');
- }
- return {
- length: length,
- hints: getHints(),
- objectNumberFirst: getInt('O'),
- endFirst: getInt('E'),
- numPages: getInt('N'),
- mainXRefEntriesOffset: getInt('T'),
- pageFirst: linDict.has('P') ? getInt('P', true) : 0
- };
- }
- };
- exports.EOF = EOF;
- exports.Lexer = Lexer;
- exports.Linearization = Linearization;
- exports.Parser = Parser;
- exports.isEOF = isEOF;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreType1Parser = {}, root.pdfjsSharedUtil, root.pdfjsCoreStream, root.pdfjsCoreEncodings);
- }(this, function (exports, sharedUtil, coreStream, coreEncodings) {
- var warn = sharedUtil.warn;
- var isSpace = sharedUtil.isSpace;
- var Stream = coreStream.Stream;
- var getEncoding = coreEncodings.getEncoding;
- // Hinting is currently disabled due to unknown problems on windows
- // in tracemonkey and various other pdfs with type1 fonts.
- var HINTING_ENABLED = false;
- /*
- * CharStrings are encoded following the the CharString Encoding sequence
- * describe in Chapter 6 of the "Adobe Type1 Font Format" specification.
- * The value in a byte indicates a command, a number, or subsequent bytes
- * that are to be interpreted in a special way.
- *
- * CharString Number Encoding:
- * A CharString byte containing the values from 32 through 255 inclusive
- * indicate an integer. These values are decoded in four ranges.
- *
- * 1. A CharString byte containing a value, v, between 32 and 246 inclusive,
- * indicate the integer v - 139. Thus, the integer values from -107 through
- * 107 inclusive may be encoded in single byte.
- *
- * 2. A CharString byte containing a value, v, between 247 and 250 inclusive,
- * indicates an integer involving the next byte, w, according to the formula:
- * [(v - 247) x 256] + w + 108
- *
- * 3. A CharString byte containing a value, v, between 251 and 254 inclusive,
- * indicates an integer involving the next byte, w, according to the formula:
- * -[(v - 251) * 256] - w - 108
- *
- * 4. A CharString containing the value 255 indicates that the next 4 bytes
- * are a two complement signed integer. The first of these bytes contains the
- * highest order bits, the second byte contains the next higher order bits
- * and the fourth byte contain the lowest order bits.
- *
- *
- * CharString Command Encoding:
- * CharStrings commands are encoded in 1 or 2 bytes.
- *
- * Single byte commands are encoded in 1 byte that contains a value between
- * 0 and 31 inclusive.
- * If a command byte contains the value 12, then the value in the next byte
- * indicates a command. This "escape" mechanism allows many extra commands
- * to be encoded and this encoding technique helps to minimize the length of
- * the charStrings.
- */
- var Type1CharString = function Type1CharStringClosure() {
- var COMMAND_MAP = {
- 'hstem': [1],
- 'vstem': [3],
- 'vmoveto': [4],
- 'rlineto': [5],
- 'hlineto': [6],
- 'vlineto': [7],
- 'rrcurveto': [8],
- 'callsubr': [10],
- 'flex': [
- 12,
- 35
- ],
- 'drop': [
- 12,
- 18
- ],
- 'endchar': [14],
- 'rmoveto': [21],
- 'hmoveto': [22],
- 'vhcurveto': [30],
- 'hvcurveto': [31]
- };
- function Type1CharString() {
- this.width = 0;
- this.lsb = 0;
- this.flexing = false;
- this.output = [];
- this.stack = [];
- }
- Type1CharString.prototype = {
- convert: function Type1CharString_convert(encoded, subrs, seacAnalysisEnabled) {
- var count = encoded.length;
- var error = false;
- var wx, sbx, subrNumber;
- for (var i = 0; i < count; i++) {
- var value = encoded[i];
- if (value < 32) {
- if (value === 12) {
- value = (value << 8) + encoded[++i];
- }
- switch (value) {
- case 1:
- // hstem
- if (!HINTING_ENABLED) {
- this.stack = [];
- break;
- }
- error = this.executeCommand(2, COMMAND_MAP.hstem);
- break;
- case 3:
- // vstem
- if (!HINTING_ENABLED) {
- this.stack = [];
- break;
- }
- error = this.executeCommand(2, COMMAND_MAP.vstem);
- break;
- case 4:
- // vmoveto
- if (this.flexing) {
- if (this.stack.length < 1) {
- error = true;
- break;
- }
- // Add the dx for flex and but also swap the values so they are
- // the right order.
- var dy = this.stack.pop();
- this.stack.push(0, dy);
- break;
- }
- error = this.executeCommand(1, COMMAND_MAP.vmoveto);
- break;
- case 5:
- // rlineto
- error = this.executeCommand(2, COMMAND_MAP.rlineto);
- break;
- case 6:
- // hlineto
- error = this.executeCommand(1, COMMAND_MAP.hlineto);
- break;
- case 7:
- // vlineto
- error = this.executeCommand(1, COMMAND_MAP.vlineto);
- break;
- case 8:
- // rrcurveto
- error = this.executeCommand(6, COMMAND_MAP.rrcurveto);
- break;
- case 9:
- // closepath
- // closepath is a Type1 command that does not take argument and is
- // useless in Type2 and it can simply be ignored.
- this.stack = [];
- break;
- case 10:
- // callsubr
- if (this.stack.length < 1) {
- error = true;
- break;
- }
- subrNumber = this.stack.pop();
- error = this.convert(subrs[subrNumber], subrs, seacAnalysisEnabled);
- break;
- case 11:
- // return
- return error;
- case 13:
- // hsbw
- if (this.stack.length < 2) {
- error = true;
- break;
- }
- // To convert to type2 we have to move the width value to the
- // first part of the charstring and then use hmoveto with lsb.
- wx = this.stack.pop();
- sbx = this.stack.pop();
- this.lsb = sbx;
- this.width = wx;
- this.stack.push(wx, sbx);
- error = this.executeCommand(2, COMMAND_MAP.hmoveto);
- break;
- case 14:
- // endchar
- this.output.push(COMMAND_MAP.endchar[0]);
- break;
- case 21:
- // rmoveto
- if (this.flexing) {
- break;
- }
- error = this.executeCommand(2, COMMAND_MAP.rmoveto);
- break;
- case 22:
- // hmoveto
- if (this.flexing) {
- // Add the dy for flex.
- this.stack.push(0);
- break;
- }
- error = this.executeCommand(1, COMMAND_MAP.hmoveto);
- break;
- case 30:
- // vhcurveto
- error = this.executeCommand(4, COMMAND_MAP.vhcurveto);
- break;
- case 31:
- // hvcurveto
- error = this.executeCommand(4, COMMAND_MAP.hvcurveto);
- break;
- case (12 << 8) + 0:
- // dotsection
- // dotsection is a Type1 command to specify some hinting feature
- // for dots that do not take a parameter and it can safely be
- // ignored for Type2.
- this.stack = [];
- break;
- case (12 << 8) + 1:
- // vstem3
- if (!HINTING_ENABLED) {
- this.stack = [];
- break;
- }
- // [vh]stem3 are Type1 only and Type2 supports [vh]stem with
- // multiple parameters, so instead of returning [vh]stem3 take a
- // shortcut and return [vhstem] instead.
- error = this.executeCommand(2, COMMAND_MAP.vstem);
- break;
- case (12 << 8) + 2:
- // hstem3
- if (!HINTING_ENABLED) {
- this.stack = [];
- break;
- }
- // See vstem3.
- error = this.executeCommand(2, COMMAND_MAP.hstem);
- break;
- case (12 << 8) + 6:
- // seac
- // seac is like type 2's special endchar but it doesn't use the
- // first argument asb, so remove it.
- if (seacAnalysisEnabled) {
- this.seac = this.stack.splice(-4, 4);
- error = this.executeCommand(0, COMMAND_MAP.endchar);
- } else {
- error = this.executeCommand(4, COMMAND_MAP.endchar);
- }
- break;
- case (12 << 8) + 7:
- // sbw
- if (this.stack.length < 4) {
- error = true;
- break;
- }
- // To convert to type2 we have to move the width value to the
- // first part of the charstring and then use rmoveto with
- // (dx, dy). The height argument will not be used for vmtx and
- // vhea tables reconstruction -- ignoring it.
- var wy = this.stack.pop();
- wx = this.stack.pop();
- var sby = this.stack.pop();
- sbx = this.stack.pop();
- this.lsb = sbx;
- this.width = wx;
- this.stack.push(wx, sbx, sby);
- error = this.executeCommand(3, COMMAND_MAP.rmoveto);
- break;
- case (12 << 8) + 12:
- // div
- if (this.stack.length < 2) {
- error = true;
- break;
- }
- var num2 = this.stack.pop();
- var num1 = this.stack.pop();
- this.stack.push(num1 / num2);
- break;
- case (12 << 8) + 16:
- // callothersubr
- if (this.stack.length < 2) {
- error = true;
- break;
- }
- subrNumber = this.stack.pop();
- var numArgs = this.stack.pop();
- if (subrNumber === 0 && numArgs === 3) {
- var flexArgs = this.stack.splice(this.stack.length - 17, 17);
- this.stack.push(flexArgs[2] + flexArgs[0], // bcp1x + rpx
- flexArgs[3] + flexArgs[1], // bcp1y + rpy
- flexArgs[4], // bcp2x
- flexArgs[5], // bcp2y
- flexArgs[6], // p2x
- flexArgs[7], // p2y
- flexArgs[8], // bcp3x
- flexArgs[9], // bcp3y
- flexArgs[10], // bcp4x
- flexArgs[11], // bcp4y
- flexArgs[12], // p3x
- flexArgs[13], // p3y
- flexArgs[14]);
- // flexDepth
- // 15 = finalx unused by flex
- // 16 = finaly unused by flex
- error = this.executeCommand(13, COMMAND_MAP.flex, true);
- this.flexing = false;
- this.stack.push(flexArgs[15], flexArgs[16]);
- } else if (subrNumber === 1 && numArgs === 0) {
- this.flexing = true;
- }
- break;
- case (12 << 8) + 17:
- // pop
- // Ignore this since it is only used with othersubr.
- break;
- case (12 << 8) + 33:
- // setcurrentpoint
- // Ignore for now.
- this.stack = [];
- break;
- default:
- warn('Unknown type 1 charstring command of "' + value + '"');
- break;
- }
- if (error) {
- break;
- }
- continue;
- } else if (value <= 246) {
- value = value - 139;
- } else if (value <= 250) {
- value = (value - 247) * 256 + encoded[++i] + 108;
- } else if (value <= 254) {
- value = -((value - 251) * 256) - encoded[++i] - 108;
- } else {
- value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 | (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0;
- }
- this.stack.push(value);
- }
- return error;
- },
- executeCommand: function (howManyArgs, command, keepStack) {
- var stackLength = this.stack.length;
- if (howManyArgs > stackLength) {
- return true;
- }
- var start = stackLength - howManyArgs;
- for (var i = start; i < stackLength; i++) {
- var value = this.stack[i];
- if (value === (value | 0)) {
- // int
- this.output.push(28, value >> 8 & 0xff, value & 0xff);
- } else {
- // fixed point
- value = 65536 * value | 0;
- this.output.push(255, value >> 24 & 0xFF, value >> 16 & 0xFF, value >> 8 & 0xFF, value & 0xFF);
- }
- }
- this.output.push.apply(this.output, command);
- if (keepStack) {
- this.stack.splice(start, howManyArgs);
- } else {
- this.stack.length = 0;
- }
- return false;
- }
- };
- return Type1CharString;
- }();
- /*
- * Type1Parser encapsulate the needed code for parsing a Type1 font
- * program. Some of its logic depends on the Type2 charstrings
- * structure.
- * Note: this doesn't really parse the font since that would require evaluation
- * of PostScript, but it is possible in most cases to extract what we need
- * without a full parse.
- */
- var Type1Parser = function Type1ParserClosure() {
- /*
- * Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence
- * of Plaintext Bytes. The function took a key as a parameter which can be
- * for decrypting the eexec block of for decoding charStrings.
- */
- var EEXEC_ENCRYPT_KEY = 55665;
- var CHAR_STRS_ENCRYPT_KEY = 4330;
- function isHexDigit(code) {
- return code >= 48 && code <= 57 || // '0'-'9'
- code >= 65 && code <= 70 || // 'A'-'F'
- code >= 97 && code <= 102;
- }
- // 'a'-'f'
- function decrypt(data, key, discardNumber) {
- if (discardNumber >= data.length) {
- return new Uint8Array(0);
- }
- var r = key | 0, c1 = 52845, c2 = 22719, i, j;
- for (i = 0; i < discardNumber; i++) {
- r = (data[i] + r) * c1 + c2 & (1 << 16) - 1;
- }
- var count = data.length - discardNumber;
- var decrypted = new Uint8Array(count);
- for (i = discardNumber, j = 0; j < count; i++, j++) {
- var value = data[i];
- decrypted[j] = value ^ r >> 8;
- r = (value + r) * c1 + c2 & (1 << 16) - 1;
- }
- return decrypted;
- }
- function decryptAscii(data, key, discardNumber) {
- var r = key | 0, c1 = 52845, c2 = 22719;
- var count = data.length, maybeLength = count >>> 1;
- var decrypted = new Uint8Array(maybeLength);
- var i, j;
- for (i = 0, j = 0; i < count; i++) {
- var digit1 = data[i];
- if (!isHexDigit(digit1)) {
- continue;
- }
- i++;
- var digit2;
- while (i < count && !isHexDigit(digit2 = data[i])) {
- i++;
- }
- if (i < count) {
- var value = parseInt(String.fromCharCode(digit1, digit2), 16);
- decrypted[j++] = value ^ r >> 8;
- r = (value + r) * c1 + c2 & (1 << 16) - 1;
- }
- }
- return Array.prototype.slice.call(decrypted, discardNumber, j);
- }
- function isSpecial(c) {
- return c === 0x2F || // '/'
- c === 0x5B || c === 0x5D || // '[', ']'
- c === 0x7B || c === 0x7D || // '{', '}'
- c === 0x28 || c === 0x29;
- }
- // '(', ')'
- function Type1Parser(stream, encrypted, seacAnalysisEnabled) {
- if (encrypted) {
- var data = stream.getBytes();
- var isBinary = !(isHexDigit(data[0]) && isHexDigit(data[1]) && isHexDigit(data[2]) && isHexDigit(data[3]));
- stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : decryptAscii(data, EEXEC_ENCRYPT_KEY, 4));
- }
- this.seacAnalysisEnabled = !!seacAnalysisEnabled;
- this.stream = stream;
- this.nextChar();
- }
- Type1Parser.prototype = {
- readNumberArray: function Type1Parser_readNumberArray() {
- this.getToken();
- // read '[' or '{' (arrays can start with either)
- var array = [];
- while (true) {
- var token = this.getToken();
- if (token === null || token === ']' || token === '}') {
- break;
- }
- array.push(parseFloat(token || 0));
- }
- return array;
- },
- readNumber: function Type1Parser_readNumber() {
- var token = this.getToken();
- return parseFloat(token || 0);
- },
- readInt: function Type1Parser_readInt() {
- // Use '| 0' to prevent setting a double into length such as the double
- // does not flow into the loop variable.
- var token = this.getToken();
- return parseInt(token || 0, 10) | 0;
- },
- readBoolean: function Type1Parser_readBoolean() {
- var token = this.getToken();
- // Use 1 and 0 since that's what type2 charstrings use.
- return token === 'true' ? 1 : 0;
- },
- nextChar: function Type1_nextChar() {
- return this.currentChar = this.stream.getByte();
- },
- getToken: function Type1Parser_getToken() {
- // Eat whitespace and comments.
- var comment = false;
- var ch = this.currentChar;
- while (true) {
- if (ch === -1) {
- return null;
- }
- if (comment) {
- if (ch === 0x0A || ch === 0x0D) {
- comment = false;
- }
- } else if (ch === 0x25) {
- // '%'
- comment = true;
- } else if (!isSpace(ch)) {
- break;
- }
- ch = this.nextChar();
- }
- if (isSpecial(ch)) {
- this.nextChar();
- return String.fromCharCode(ch);
- }
- var token = '';
- do {
- token += String.fromCharCode(ch);
- ch = this.nextChar();
- } while (ch >= 0 && !isSpace(ch) && !isSpecial(ch));
- return token;
- },
- /*
- * Returns an object containing a Subrs array and a CharStrings
- * array extracted from and eexec encrypted block of data
- */
- extractFontProgram: function Type1Parser_extractFontProgram() {
- var stream = this.stream;
- var subrs = [], charstrings = [];
- var privateData = Object.create(null);
- privateData['lenIV'] = 4;
- var program = {
- subrs: [],
- charstrings: [],
- properties: { 'privateData': privateData }
- };
- var token, length, data, lenIV, encoded;
- while ((token = this.getToken()) !== null) {
- if (token !== '/') {
- continue;
- }
- token = this.getToken();
- switch (token) {
- case 'CharStrings':
- // The number immediately following CharStrings must be greater or
- // equal to the number of CharStrings.
- this.getToken();
- this.getToken();
- // read in 'dict'
- this.getToken();
- // read in 'dup'
- this.getToken();
- // read in 'begin'
- while (true) {
- token = this.getToken();
- if (token === null || token === 'end') {
- break;
- }
- if (token !== '/') {
- continue;
- }
- var glyph = this.getToken();
- length = this.readInt();
- this.getToken();
- // read in 'RD' or '-|'
- data = stream.makeSubStream(stream.pos, length);
- lenIV = program.properties.privateData['lenIV'];
- encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV);
- // Skip past the required space and binary data.
- stream.skip(length);
- this.nextChar();
- token = this.getToken();
- // read in 'ND' or '|-'
- if (token === 'noaccess') {
- this.getToken();
- }
- // read in 'def'
- charstrings.push({
- glyph: glyph,
- encoded: encoded
- });
- }
- break;
- case 'Subrs':
- var num = this.readInt();
- this.getToken();
- // read in 'array'
- while ((token = this.getToken()) === 'dup') {
- var index = this.readInt();
- length = this.readInt();
- this.getToken();
- // read in 'RD' or '-|'
- data = stream.makeSubStream(stream.pos, length);
- lenIV = program.properties.privateData['lenIV'];
- encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV);
- // Skip past the required space and binary data.
- stream.skip(length);
- this.nextChar();
- token = this.getToken();
- // read in 'NP' or '|'
- if (token === 'noaccess') {
- this.getToken();
- }
- // read in 'put'
- subrs[index] = encoded;
- }
- break;
- case 'BlueValues':
- case 'OtherBlues':
- case 'FamilyBlues':
- case 'FamilyOtherBlues':
- var blueArray = this.readNumberArray();
- // *Blue* values may contain invalid data: disables reading of
- // those values when hinting is disabled.
- if (blueArray.length > 0 && blueArray.length % 2 === 0 && HINTING_ENABLED) {
- program.properties.privateData[token] = blueArray;
- }
- break;
- case 'StemSnapH':
- case 'StemSnapV':
- program.properties.privateData[token] = this.readNumberArray();
- break;
- case 'StdHW':
- case 'StdVW':
- program.properties.privateData[token] = this.readNumberArray()[0];
- break;
- case 'BlueShift':
- case 'lenIV':
- case 'BlueFuzz':
- case 'BlueScale':
- case 'LanguageGroup':
- case 'ExpansionFactor':
- program.properties.privateData[token] = this.readNumber();
- break;
- case 'ForceBold':
- program.properties.privateData[token] = this.readBoolean();
- break;
- }
- }
- for (var i = 0; i < charstrings.length; i++) {
- glyph = charstrings[i].glyph;
- encoded = charstrings[i].encoded;
- var charString = new Type1CharString();
- var error = charString.convert(encoded, subrs, this.seacAnalysisEnabled);
- var output = charString.output;
- if (error) {
- // It seems when FreeType encounters an error while evaluating a glyph
- // that it completely ignores the glyph so we'll mimic that behaviour
- // here and put an endchar to make the validator happy.
- output = [14];
- }
- program.charstrings.push({
- glyphName: glyph,
- charstring: output,
- width: charString.width,
- lsb: charString.lsb,
- seac: charString.seac
- });
- }
- return program;
- },
- extractFontHeader: function Type1Parser_extractFontHeader(properties) {
- var token;
- while ((token = this.getToken()) !== null) {
- if (token !== '/') {
- continue;
- }
- token = this.getToken();
- switch (token) {
- case 'FontMatrix':
- var matrix = this.readNumberArray();
- properties.fontMatrix = matrix;
- break;
- case 'Encoding':
- var encodingArg = this.getToken();
- var encoding;
- if (!/^\d+$/.test(encodingArg)) {
- // encoding name is specified
- encoding = getEncoding(encodingArg);
- } else {
- encoding = [];
- var size = parseInt(encodingArg, 10) | 0;
- this.getToken();
- // read in 'array'
- for (var j = 0; j < size; j++) {
- token = this.getToken();
- // skipping till first dup or def (e.g. ignoring for statement)
- while (token !== 'dup' && token !== 'def') {
- token = this.getToken();
- if (token === null) {
- return;
- }
- }
- // invalid header
- if (token === 'def') {
- break;
- }
- // read all array data
- var index = this.readInt();
- this.getToken();
- // read in '/'
- var glyph = this.getToken();
- encoding[index] = glyph;
- this.getToken();
- }
- }
- // read the in 'put'
- properties.builtInEncoding = encoding;
- break;
- case 'FontBBox':
- var fontBBox = this.readNumberArray();
- // adjusting ascent/descent
- properties.ascent = fontBBox[3];
- properties.descent = fontBBox[1];
- properties.ascentScaled = true;
- break;
- }
- }
- }
- };
- return Type1Parser;
- }();
- exports.Type1Parser = Type1Parser;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreCMap = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreStream, root.pdfjsCoreParser);
- }(this, function (exports, sharedUtil, corePrimitives, coreStream, coreParser) {
- var Util = sharedUtil.Util;
- var assert = sharedUtil.assert;
- var warn = sharedUtil.warn;
- var error = sharedUtil.error;
- var isInt = sharedUtil.isInt;
- var isString = sharedUtil.isString;
- var MissingDataException = sharedUtil.MissingDataException;
- var isName = corePrimitives.isName;
- var isCmd = corePrimitives.isCmd;
- var isStream = corePrimitives.isStream;
- var StringStream = coreStream.StringStream;
- var Lexer = coreParser.Lexer;
- var isEOF = coreParser.isEOF;
- var BUILT_IN_CMAPS = [
- // << Start unicode maps.
- 'Adobe-GB1-UCS2',
- 'Adobe-CNS1-UCS2',
- 'Adobe-Japan1-UCS2',
- 'Adobe-Korea1-UCS2',
- // >> End unicode maps.
- '78-EUC-H',
- '78-EUC-V',
- '78-H',
- '78-RKSJ-H',
- '78-RKSJ-V',
- '78-V',
- '78ms-RKSJ-H',
- '78ms-RKSJ-V',
- '83pv-RKSJ-H',
- '90ms-RKSJ-H',
- '90ms-RKSJ-V',
- '90msp-RKSJ-H',
- '90msp-RKSJ-V',
- '90pv-RKSJ-H',
- '90pv-RKSJ-V',
- 'Add-H',
- 'Add-RKSJ-H',
- 'Add-RKSJ-V',
- 'Add-V',
- 'Adobe-CNS1-0',
- 'Adobe-CNS1-1',
- 'Adobe-CNS1-2',
- 'Adobe-CNS1-3',
- 'Adobe-CNS1-4',
- 'Adobe-CNS1-5',
- 'Adobe-CNS1-6',
- 'Adobe-GB1-0',
- 'Adobe-GB1-1',
- 'Adobe-GB1-2',
- 'Adobe-GB1-3',
- 'Adobe-GB1-4',
- 'Adobe-GB1-5',
- 'Adobe-Japan1-0',
- 'Adobe-Japan1-1',
- 'Adobe-Japan1-2',
- 'Adobe-Japan1-3',
- 'Adobe-Japan1-4',
- 'Adobe-Japan1-5',
- 'Adobe-Japan1-6',
- 'Adobe-Korea1-0',
- 'Adobe-Korea1-1',
- 'Adobe-Korea1-2',
- 'B5-H',
- 'B5-V',
- 'B5pc-H',
- 'B5pc-V',
- 'CNS-EUC-H',
- 'CNS-EUC-V',
- 'CNS1-H',
- 'CNS1-V',
- 'CNS2-H',
- 'CNS2-V',
- 'ETHK-B5-H',
- 'ETHK-B5-V',
- 'ETen-B5-H',
- 'ETen-B5-V',
- 'ETenms-B5-H',
- 'ETenms-B5-V',
- 'EUC-H',
- 'EUC-V',
- 'Ext-H',
- 'Ext-RKSJ-H',
- 'Ext-RKSJ-V',
- 'Ext-V',
- 'GB-EUC-H',
- 'GB-EUC-V',
- 'GB-H',
- 'GB-V',
- 'GBK-EUC-H',
- 'GBK-EUC-V',
- 'GBK2K-H',
- 'GBK2K-V',
- 'GBKp-EUC-H',
- 'GBKp-EUC-V',
- 'GBT-EUC-H',
- 'GBT-EUC-V',
- 'GBT-H',
- 'GBT-V',
- 'GBTpc-EUC-H',
- 'GBTpc-EUC-V',
- 'GBpc-EUC-H',
- 'GBpc-EUC-V',
- 'H',
- 'HKdla-B5-H',
- 'HKdla-B5-V',
- 'HKdlb-B5-H',
- 'HKdlb-B5-V',
- 'HKgccs-B5-H',
- 'HKgccs-B5-V',
- 'HKm314-B5-H',
- 'HKm314-B5-V',
- 'HKm471-B5-H',
- 'HKm471-B5-V',
- 'HKscs-B5-H',
- 'HKscs-B5-V',
- 'Hankaku',
- 'Hiragana',
- 'KSC-EUC-H',
- 'KSC-EUC-V',
- 'KSC-H',
- 'KSC-Johab-H',
- 'KSC-Johab-V',
- 'KSC-V',
- 'KSCms-UHC-H',
- 'KSCms-UHC-HW-H',
- 'KSCms-UHC-HW-V',
- 'KSCms-UHC-V',
- 'KSCpc-EUC-H',
- 'KSCpc-EUC-V',
- 'Katakana',
- 'NWP-H',
- 'NWP-V',
- 'RKSJ-H',
- 'RKSJ-V',
- 'Roman',
- 'UniCNS-UCS2-H',
- 'UniCNS-UCS2-V',
- 'UniCNS-UTF16-H',
- 'UniCNS-UTF16-V',
- 'UniCNS-UTF32-H',
- 'UniCNS-UTF32-V',
- 'UniCNS-UTF8-H',
- 'UniCNS-UTF8-V',
- 'UniGB-UCS2-H',
- 'UniGB-UCS2-V',
- 'UniGB-UTF16-H',
- 'UniGB-UTF16-V',
- 'UniGB-UTF32-H',
- 'UniGB-UTF32-V',
- 'UniGB-UTF8-H',
- 'UniGB-UTF8-V',
- 'UniJIS-UCS2-H',
- 'UniJIS-UCS2-HW-H',
- 'UniJIS-UCS2-HW-V',
- 'UniJIS-UCS2-V',
- 'UniJIS-UTF16-H',
- 'UniJIS-UTF16-V',
- 'UniJIS-UTF32-H',
- 'UniJIS-UTF32-V',
- 'UniJIS-UTF8-H',
- 'UniJIS-UTF8-V',
- 'UniJIS2004-UTF16-H',
- 'UniJIS2004-UTF16-V',
- 'UniJIS2004-UTF32-H',
- 'UniJIS2004-UTF32-V',
- 'UniJIS2004-UTF8-H',
- 'UniJIS2004-UTF8-V',
- 'UniJISPro-UCS2-HW-V',
- 'UniJISPro-UCS2-V',
- 'UniJISPro-UTF8-V',
- 'UniJISX0213-UTF32-H',
- 'UniJISX0213-UTF32-V',
- 'UniJISX02132004-UTF32-H',
- 'UniJISX02132004-UTF32-V',
- 'UniKS-UCS2-H',
- 'UniKS-UCS2-V',
- 'UniKS-UTF16-H',
- 'UniKS-UTF16-V',
- 'UniKS-UTF32-H',
- 'UniKS-UTF32-V',
- 'UniKS-UTF8-H',
- 'UniKS-UTF8-V',
- 'V',
- 'WP-Symbol'
- ];
- // CMap, not to be confused with TrueType's cmap.
- var CMap = function CMapClosure() {
- function CMap(builtInCMap) {
- // Codespace ranges are stored as follows:
- // [[1BytePairs], [2BytePairs], [3BytePairs], [4BytePairs]]
- // where nBytePairs are ranges e.g. [low1, high1, low2, high2, ...]
- this.codespaceRanges = [
- [],
- [],
- [],
- []
- ];
- this.numCodespaceRanges = 0;
- // Map entries have one of two forms.
- // - cid chars are 16-bit unsigned integers, stored as integers.
- // - bf chars are variable-length byte sequences, stored as strings, with
- // one byte per character.
- this._map = [];
- this.name = '';
- this.vertical = false;
- this.useCMap = null;
- this.builtInCMap = builtInCMap;
- }
- CMap.prototype = {
- addCodespaceRange: function (n, low, high) {
- this.codespaceRanges[n - 1].push(low, high);
- this.numCodespaceRanges++;
- },
- mapCidRange: function (low, high, dstLow) {
- while (low <= high) {
- this._map[low++] = dstLow++;
- }
- },
- mapBfRange: function (low, high, dstLow) {
- var lastByte = dstLow.length - 1;
- while (low <= high) {
- this._map[low++] = dstLow;
- // Only the last byte has to be incremented.
- dstLow = dstLow.substr(0, lastByte) + String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
- }
- },
- mapBfRangeToArray: function (low, high, array) {
- var i = 0, ii = array.length;
- while (low <= high && i < ii) {
- this._map[low] = array[i++];
- ++low;
- }
- },
- // This is used for both bf and cid chars.
- mapOne: function (src, dst) {
- this._map[src] = dst;
- },
- lookup: function (code) {
- return this._map[code];
- },
- contains: function (code) {
- return this._map[code] !== undefined;
- },
- forEach: function (callback) {
- // Most maps have fewer than 65536 entries, and for those we use normal
- // array iteration. But really sparse tables are possible -- e.g. with
- // indices in the *billions*. For such tables we use for..in, which isn't
- // ideal because it stringifies the indices for all present elements, but
- // it does avoid iterating over every undefined entry.
- var map = this._map;
- var length = map.length;
- var i;
- if (length <= 0x10000) {
- for (i = 0; i < length; i++) {
- if (map[i] !== undefined) {
- callback(i, map[i]);
- }
- }
- } else {
- for (i in this._map) {
- callback(i, map[i]);
- }
- }
- },
- charCodeOf: function (value) {
- return this._map.indexOf(value);
- },
- getMap: function () {
- return this._map;
- },
- readCharCode: function (str, offset, out) {
- var c = 0;
- var codespaceRanges = this.codespaceRanges;
- var codespaceRangesLen = this.codespaceRanges.length;
- // 9.7.6.2 CMap Mapping
- // The code length is at most 4.
- for (var n = 0; n < codespaceRangesLen; n++) {
- c = (c << 8 | str.charCodeAt(offset + n)) >>> 0;
- // Check each codespace range to see if it falls within.
- var codespaceRange = codespaceRanges[n];
- for (var k = 0, kk = codespaceRange.length; k < kk;) {
- var low = codespaceRange[k++];
- var high = codespaceRange[k++];
- if (c >= low && c <= high) {
- out.charcode = c;
- out.length = n + 1;
- return;
- }
- }
- }
- out.charcode = 0;
- out.length = 1;
- },
- get length() {
- return this._map.length;
- },
- get isIdentityCMap() {
- if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) {
- return false;
- }
- if (this._map.length !== 0x10000) {
- return false;
- }
- for (var i = 0; i < 0x10000; i++) {
- if (this._map[i] !== i) {
- return false;
- }
- }
- return true;
- }
- };
- return CMap;
- }();
- // A special case of CMap, where the _map array implicitly has a length of
- // 65536 and each element is equal to its index.
- var IdentityCMap = function IdentityCMapClosure() {
- function IdentityCMap(vertical, n) {
- CMap.call(this);
- this.vertical = vertical;
- this.addCodespaceRange(n, 0, 0xffff);
- }
- Util.inherit(IdentityCMap, CMap, {});
- IdentityCMap.prototype = {
- addCodespaceRange: CMap.prototype.addCodespaceRange,
- mapCidRange: function (low, high, dstLow) {
- error('should not call mapCidRange');
- },
- mapBfRange: function (low, high, dstLow) {
- error('should not call mapBfRange');
- },
- mapBfRangeToArray: function (low, high, array) {
- error('should not call mapBfRangeToArray');
- },
- mapOne: function (src, dst) {
- error('should not call mapCidOne');
- },
- lookup: function (code) {
- return isInt(code) && code <= 0xffff ? code : undefined;
- },
- contains: function (code) {
- return isInt(code) && code <= 0xffff;
- },
- forEach: function (callback) {
- for (var i = 0; i <= 0xffff; i++) {
- callback(i, i);
- }
- },
- charCodeOf: function (value) {
- return isInt(value) && value <= 0xffff ? value : -1;
- },
- getMap: function () {
- // Sometimes identity maps must be instantiated, but it's rare.
- var map = new Array(0x10000);
- for (var i = 0; i <= 0xffff; i++) {
- map[i] = i;
- }
- return map;
- },
- readCharCode: CMap.prototype.readCharCode,
- get length() {
- return 0x10000;
- },
- get isIdentityCMap() {
- error('should not access .isIdentityCMap');
- }
- };
- return IdentityCMap;
- }();
- var BinaryCMapReader = function BinaryCMapReaderClosure() {
- function fetchBinaryData(url) {
- return new Promise(function (resolve, reject) {
- var request = new XMLHttpRequest();
- request.open('GET', url, true);
- request.responseType = 'arraybuffer';
- request.onreadystatechange = function () {
- if (request.readyState === XMLHttpRequest.DONE) {
- if (!request.response || request.status !== 200 && request.status !== 0) {
- reject(new Error('Unable to get binary cMap at: ' + url));
- } else {
- resolve(new Uint8Array(request.response));
- }
- }
- };
- request.send(null);
- });
- }
- function hexToInt(a, size) {
- var n = 0;
- for (var i = 0; i <= size; i++) {
- n = n << 8 | a[i];
- }
- return n >>> 0;
- }
- function hexToStr(a, size) {
- // This code is hot. Special-case some common values to avoid creating an
- // object with subarray().
- if (size === 1) {
- return String.fromCharCode(a[0], a[1]);
- }
- if (size === 3) {
- return String.fromCharCode(a[0], a[1], a[2], a[3]);
- }
- return String.fromCharCode.apply(null, a.subarray(0, size + 1));
- }
- function addHex(a, b, size) {
- var c = 0;
- for (var i = size; i >= 0; i--) {
- c += a[i] + b[i];
- a[i] = c & 255;
- c >>= 8;
- }
- }
- function incHex(a, size) {
- var c = 1;
- for (var i = size; i >= 0 && c > 0; i--) {
- c += a[i];
- a[i] = c & 255;
- c >>= 8;
- }
- }
- var MAX_NUM_SIZE = 16;
- var MAX_ENCODED_NUM_SIZE = 19;
- // ceil(MAX_NUM_SIZE * 7 / 8)
- function BinaryCMapStream(data) {
- this.buffer = data;
- this.pos = 0;
- this.end = data.length;
- this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE);
- }
- BinaryCMapStream.prototype = {
- readByte: function () {
- if (this.pos >= this.end) {
- return -1;
- }
- return this.buffer[this.pos++];
- },
- readNumber: function () {
- var n = 0;
- var last;
- do {
- var b = this.readByte();
- if (b < 0) {
- error('unexpected EOF in bcmap');
- }
- last = !(b & 0x80);
- n = n << 7 | b & 0x7F;
- } while (!last);
- return n;
- },
- readSigned: function () {
- var n = this.readNumber();
- return n & 1 ? ~(n >>> 1) : n >>> 1;
- },
- readHex: function (num, size) {
- num.set(this.buffer.subarray(this.pos, this.pos + size + 1));
- this.pos += size + 1;
- },
- readHexNumber: function (num, size) {
- var last;
- var stack = this.tmpBuf, sp = 0;
- do {
- var b = this.readByte();
- if (b < 0) {
- error('unexpected EOF in bcmap');
- }
- last = !(b & 0x80);
- stack[sp++] = b & 0x7F;
- } while (!last);
- var i = size, buffer = 0, bufferSize = 0;
- while (i >= 0) {
- while (bufferSize < 8 && stack.length > 0) {
- buffer = stack[--sp] << bufferSize | buffer;
- bufferSize += 7;
- }
- num[i] = buffer & 255;
- i--;
- buffer >>= 8;
- bufferSize -= 8;
- }
- },
- readHexSigned: function (num, size) {
- this.readHexNumber(num, size);
- var sign = num[size] & 1 ? 255 : 0;
- var c = 0;
- for (var i = 0; i <= size; i++) {
- c = (c & 1) << 8 | num[i];
- num[i] = c >> 1 ^ sign;
- }
- },
- readString: function () {
- var len = this.readNumber();
- var s = '';
- for (var i = 0; i < len; i++) {
- s += String.fromCharCode(this.readNumber());
- }
- return s;
- }
- };
- function processBinaryCMap(url, cMap, extend) {
- return fetchBinaryData(url).then(function (data) {
- var stream = new BinaryCMapStream(data);
- var header = stream.readByte();
- cMap.vertical = !!(header & 1);
- var useCMap = null;
- var start = new Uint8Array(MAX_NUM_SIZE);
- var end = new Uint8Array(MAX_NUM_SIZE);
- var char = new Uint8Array(MAX_NUM_SIZE);
- var charCode = new Uint8Array(MAX_NUM_SIZE);
- var tmp = new Uint8Array(MAX_NUM_SIZE);
- var code;
- var b;
- while ((b = stream.readByte()) >= 0) {
- var type = b >> 5;
- if (type === 7) {
- // metadata, e.g. comment or usecmap
- switch (b & 0x1F) {
- case 0:
- stream.readString();
- // skipping comment
- break;
- case 1:
- useCMap = stream.readString();
- break;
- }
- continue;
- }
- var sequence = !!(b & 0x10);
- var dataSize = b & 15;
- assert(dataSize + 1 <= MAX_NUM_SIZE);
- var ucs2DataSize = 1;
- var subitemsCount = stream.readNumber();
- var i;
- switch (type) {
- case 0:
- // codespacerange
- stream.readHex(start, dataSize);
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize));
- for (i = 1; i < subitemsCount; i++) {
- incHex(end, dataSize);
- stream.readHexNumber(start, dataSize);
- addHex(start, end, dataSize);
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize));
- }
- break;
- case 1:
- // notdefrange
- stream.readHex(start, dataSize);
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- code = stream.readNumber();
- // undefined range, skipping
- for (i = 1; i < subitemsCount; i++) {
- incHex(end, dataSize);
- stream.readHexNumber(start, dataSize);
- addHex(start, end, dataSize);
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- code = stream.readNumber();
- }
- // nop
- break;
- case 2:
- // cidchar
- stream.readHex(char, dataSize);
- code = stream.readNumber();
- cMap.mapOne(hexToInt(char, dataSize), code);
- for (i = 1; i < subitemsCount; i++) {
- incHex(char, dataSize);
- if (!sequence) {
- stream.readHexNumber(tmp, dataSize);
- addHex(char, tmp, dataSize);
- }
- code = stream.readSigned() + (code + 1);
- cMap.mapOne(hexToInt(char, dataSize), code);
- }
- break;
- case 3:
- // cidrange
- stream.readHex(start, dataSize);
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- code = stream.readNumber();
- cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code);
- for (i = 1; i < subitemsCount; i++) {
- incHex(end, dataSize);
- if (!sequence) {
- stream.readHexNumber(start, dataSize);
- addHex(start, end, dataSize);
- } else {
- start.set(end);
- }
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- code = stream.readNumber();
- cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code);
- }
- break;
- case 4:
- // bfchar
- stream.readHex(char, ucs2DataSize);
- stream.readHex(charCode, dataSize);
- cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize));
- for (i = 1; i < subitemsCount; i++) {
- incHex(char, ucs2DataSize);
- if (!sequence) {
- stream.readHexNumber(tmp, ucs2DataSize);
- addHex(char, tmp, ucs2DataSize);
- }
- incHex(charCode, dataSize);
- stream.readHexSigned(tmp, dataSize);
- addHex(charCode, tmp, dataSize);
- cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize));
- }
- break;
- case 5:
- // bfrange
- stream.readHex(start, ucs2DataSize);
- stream.readHexNumber(end, ucs2DataSize);
- addHex(end, start, ucs2DataSize);
- stream.readHex(charCode, dataSize);
- cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize));
- for (i = 1; i < subitemsCount; i++) {
- incHex(end, ucs2DataSize);
- if (!sequence) {
- stream.readHexNumber(start, ucs2DataSize);
- addHex(start, end, ucs2DataSize);
- } else {
- start.set(end);
- }
- stream.readHexNumber(end, ucs2DataSize);
- addHex(end, start, ucs2DataSize);
- stream.readHex(charCode, dataSize);
- cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize));
- }
- break;
- default:
- error('Unknown type: ' + type);
- break;
- }
- }
- if (useCMap) {
- return extend(useCMap);
- }
- return cMap;
- });
- }
- function BinaryCMapReader() {
- }
- BinaryCMapReader.prototype = { read: processBinaryCMap };
- return BinaryCMapReader;
- }();
- var CMapFactory = function CMapFactoryClosure() {
- function strToInt(str) {
- var a = 0;
- for (var i = 0; i < str.length; i++) {
- a = a << 8 | str.charCodeAt(i);
- }
- return a >>> 0;
- }
- function expectString(obj) {
- if (!isString(obj)) {
- error('Malformed CMap: expected string.');
- }
- }
- function expectInt(obj) {
- if (!isInt(obj)) {
- error('Malformed CMap: expected int.');
- }
- }
- function parseBfChar(cMap, lexer) {
- while (true) {
- var obj = lexer.getObj();
- if (isEOF(obj)) {
- break;
- }
- if (isCmd(obj, 'endbfchar')) {
- return;
- }
- expectString(obj);
- var src = strToInt(obj);
- obj = lexer.getObj();
- // TODO are /dstName used?
- expectString(obj);
- var dst = obj;
- cMap.mapOne(src, dst);
- }
- }
- function parseBfRange(cMap, lexer) {
- while (true) {
- var obj = lexer.getObj();
- if (isEOF(obj)) {
- break;
- }
- if (isCmd(obj, 'endbfrange')) {
- return;
- }
- expectString(obj);
- var low = strToInt(obj);
- obj = lexer.getObj();
- expectString(obj);
- var high = strToInt(obj);
- obj = lexer.getObj();
- if (isInt(obj) || isString(obj)) {
- var dstLow = isInt(obj) ? String.fromCharCode(obj) : obj;
- cMap.mapBfRange(low, high, dstLow);
- } else if (isCmd(obj, '[')) {
- obj = lexer.getObj();
- var array = [];
- while (!isCmd(obj, ']') && !isEOF(obj)) {
- array.push(obj);
- obj = lexer.getObj();
- }
- cMap.mapBfRangeToArray(low, high, array);
- } else {
- break;
- }
- }
- error('Invalid bf range.');
- }
- function parseCidChar(cMap, lexer) {
- while (true) {
- var obj = lexer.getObj();
- if (isEOF(obj)) {
- break;
- }
- if (isCmd(obj, 'endcidchar')) {
- return;
- }
- expectString(obj);
- var src = strToInt(obj);
- obj = lexer.getObj();
- expectInt(obj);
- var dst = obj;
- cMap.mapOne(src, dst);
- }
- }
- function parseCidRange(cMap, lexer) {
- while (true) {
- var obj = lexer.getObj();
- if (isEOF(obj)) {
- break;
- }
- if (isCmd(obj, 'endcidrange')) {
- return;
- }
- expectString(obj);
- var low = strToInt(obj);
- obj = lexer.getObj();
- expectString(obj);
- var high = strToInt(obj);
- obj = lexer.getObj();
- expectInt(obj);
- var dstLow = obj;
- cMap.mapCidRange(low, high, dstLow);
- }
- }
- function parseCodespaceRange(cMap, lexer) {
- while (true) {
- var obj = lexer.getObj();
- if (isEOF(obj)) {
- break;
- }
- if (isCmd(obj, 'endcodespacerange')) {
- return;
- }
- if (!isString(obj)) {
- break;
- }
- var low = strToInt(obj);
- obj = lexer.getObj();
- if (!isString(obj)) {
- break;
- }
- var high = strToInt(obj);
- cMap.addCodespaceRange(obj.length, low, high);
- }
- error('Invalid codespace range.');
- }
- function parseWMode(cMap, lexer) {
- var obj = lexer.getObj();
- if (isInt(obj)) {
- cMap.vertical = !!obj;
- }
- }
- function parseCMapName(cMap, lexer) {
- var obj = lexer.getObj();
- if (isName(obj) && isString(obj.name)) {
- cMap.name = obj.name;
- }
- }
- function parseCMap(cMap, lexer, builtInCMapParams, useCMap) {
- var previous;
- var embededUseCMap;
- objLoop:
- while (true) {
- try {
- var obj = lexer.getObj();
- if (isEOF(obj)) {
- break;
- } else if (isName(obj)) {
- if (obj.name === 'WMode') {
- parseWMode(cMap, lexer);
- } else if (obj.name === 'CMapName') {
- parseCMapName(cMap, lexer);
- }
- previous = obj;
- } else if (isCmd(obj)) {
- switch (obj.cmd) {
- case 'endcmap':
- break objLoop;
- case 'usecmap':
- if (isName(previous)) {
- embededUseCMap = previous.name;
- }
- break;
- case 'begincodespacerange':
- parseCodespaceRange(cMap, lexer);
- break;
- case 'beginbfchar':
- parseBfChar(cMap, lexer);
- break;
- case 'begincidchar':
- parseCidChar(cMap, lexer);
- break;
- case 'beginbfrange':
- parseBfRange(cMap, lexer);
- break;
- case 'begincidrange':
- parseCidRange(cMap, lexer);
- break;
- }
- }
- } catch (ex) {
- if (ex instanceof MissingDataException) {
- throw ex;
- }
- warn('Invalid cMap data: ' + ex);
- continue;
- }
- }
- if (!useCMap && embededUseCMap) {
- // Load the usecmap definition from the file only if there wasn't one
- // specified.
- useCMap = embededUseCMap;
- }
- if (useCMap) {
- return extendCMap(cMap, builtInCMapParams, useCMap);
- }
- return Promise.resolve(cMap);
- }
- function extendCMap(cMap, builtInCMapParams, useCMap) {
- return createBuiltInCMap(useCMap, builtInCMapParams).then(function (newCMap) {
- cMap.useCMap = newCMap;
- // If there aren't any code space ranges defined clone all the parent ones
- // into this cMap.
- if (cMap.numCodespaceRanges === 0) {
- var useCodespaceRanges = cMap.useCMap.codespaceRanges;
- for (var i = 0; i < useCodespaceRanges.length; i++) {
- cMap.codespaceRanges[i] = useCodespaceRanges[i].slice();
- }
- cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges;
- }
- // Merge the map into the current one, making sure not to override
- // any previously defined entries.
- cMap.useCMap.forEach(function (key, value) {
- if (!cMap.contains(key)) {
- cMap.mapOne(key, cMap.useCMap.lookup(key));
- }
- });
- return cMap;
- });
- }
- function parseBinaryCMap(name, builtInCMapParams) {
- var url = builtInCMapParams.url + name + '.bcmap';
- var cMap = new CMap(true);
- return new BinaryCMapReader().read(url, cMap, function (useCMap) {
- return extendCMap(cMap, builtInCMapParams, useCMap);
- });
- }
- function createBuiltInCMap(name, builtInCMapParams) {
- if (name === 'Identity-H') {
- return Promise.resolve(new IdentityCMap(false, 2));
- } else if (name === 'Identity-V') {
- return Promise.resolve(new IdentityCMap(true, 2));
- }
- if (BUILT_IN_CMAPS.indexOf(name) === -1) {
- return Promise.reject(new Error('Unknown cMap name: ' + name));
- }
- assert(builtInCMapParams, 'built-in cMap parameters are not provided');
- if (builtInCMapParams.packed) {
- return parseBinaryCMap(name, builtInCMapParams);
- }
- return new Promise(function (resolve, reject) {
- var url = builtInCMapParams.url + name;
- var request = new XMLHttpRequest();
- request.onreadystatechange = function () {
- if (request.readyState === XMLHttpRequest.DONE) {
- if (request.status === 200 || request.status === 0) {
- var cMap = new CMap(true);
- var lexer = new Lexer(new StringStream(request.responseText));
- parseCMap(cMap, lexer, builtInCMapParams, null).then(function (parsedCMap) {
- resolve(parsedCMap);
- });
- } else {
- reject(new Error('Unable to get cMap at: ' + url));
- }
- }
- };
- request.open('GET', url, true);
- request.send(null);
- });
- }
- return {
- create: function (encoding, builtInCMapParams, useCMap) {
- if (isName(encoding)) {
- return createBuiltInCMap(encoding.name, builtInCMapParams);
- } else if (isStream(encoding)) {
- var cMap = new CMap();
- var lexer = new Lexer(encoding);
- return parseCMap(cMap, lexer, builtInCMapParams, useCMap).then(function (parsedCMap) {
- if (parsedCMap.isIdentityCMap) {
- return createBuiltInCMap(parsedCMap.name, builtInCMapParams);
- }
- return parsedCMap;
- });
- }
- return Promise.reject(new Error('Encoding required.'));
- }
- };
- }();
- exports.CMap = CMap;
- exports.CMapFactory = CMapFactory;
- exports.IdentityCMap = IdentityCMap;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreFonts = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreStream, root.pdfjsCoreGlyphList, root.pdfjsCoreFontRenderer, root.pdfjsCoreEncodings, root.pdfjsCoreStandardFonts, root.pdfjsCoreUnicode, root.pdfjsCoreType1Parser, root.pdfjsCoreCFFParser);
- }(this, function (exports, sharedUtil, corePrimitives, coreStream, coreGlyphList, coreFontRenderer, coreEncodings, coreStandardFonts, coreUnicode, coreType1Parser, coreCFFParser) {
- var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX;
- var FontType = sharedUtil.FontType;
- var assert = sharedUtil.assert;
- var bytesToString = sharedUtil.bytesToString;
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var isArray = sharedUtil.isArray;
- var isInt = sharedUtil.isInt;
- var isNum = sharedUtil.isNum;
- var readUint32 = sharedUtil.readUint32;
- var shadow = sharedUtil.shadow;
- var string32 = sharedUtil.string32;
- var warn = sharedUtil.warn;
- var MissingDataException = sharedUtil.MissingDataException;
- var isSpace = sharedUtil.isSpace;
- var Stream = coreStream.Stream;
- var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode;
- var getDingbatsGlyphsUnicode = coreGlyphList.getDingbatsGlyphsUnicode;
- var FontRendererFactory = coreFontRenderer.FontRendererFactory;
- var StandardEncoding = coreEncodings.StandardEncoding;
- var MacRomanEncoding = coreEncodings.MacRomanEncoding;
- var SymbolSetEncoding = coreEncodings.SymbolSetEncoding;
- var ZapfDingbatsEncoding = coreEncodings.ZapfDingbatsEncoding;
- var getEncoding = coreEncodings.getEncoding;
- var getStdFontMap = coreStandardFonts.getStdFontMap;
- var getNonStdFontMap = coreStandardFonts.getNonStdFontMap;
- var getGlyphMapForStandardFonts = coreStandardFonts.getGlyphMapForStandardFonts;
- var getSupplementalGlyphMapForArialBlack = coreStandardFonts.getSupplementalGlyphMapForArialBlack;
- var getUnicodeRangeFor = coreUnicode.getUnicodeRangeFor;
- var mapSpecialUnicodeValues = coreUnicode.mapSpecialUnicodeValues;
- var getUnicodeForGlyph = coreUnicode.getUnicodeForGlyph;
- var Type1Parser = coreType1Parser.Type1Parser;
- var CFFStandardStrings = coreCFFParser.CFFStandardStrings;
- var CFFParser = coreCFFParser.CFFParser;
- var CFFCompiler = coreCFFParser.CFFCompiler;
- var CFF = coreCFFParser.CFF;
- var CFFHeader = coreCFFParser.CFFHeader;
- var CFFTopDict = coreCFFParser.CFFTopDict;
- var CFFPrivateDict = coreCFFParser.CFFPrivateDict;
- var CFFStrings = coreCFFParser.CFFStrings;
- var CFFIndex = coreCFFParser.CFFIndex;
- var CFFCharset = coreCFFParser.CFFCharset;
- // Unicode Private Use Area
- var PRIVATE_USE_OFFSET_START = 0xE000;
- var PRIVATE_USE_OFFSET_END = 0xF8FF;
- var SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = false;
- // PDF Glyph Space Units are one Thousandth of a TextSpace Unit
- // except for Type 3 fonts
- var PDF_GLYPH_SPACE_UNITS = 1000;
- // Accented charactars are not displayed properly on Windows, using this flag
- // to control analysis of seac charstrings.
- var SEAC_ANALYSIS_ENABLED = false;
- var FontFlags = {
- FixedPitch: 1,
- Serif: 2,
- Symbolic: 4,
- Script: 8,
- Nonsymbolic: 32,
- Italic: 64,
- AllCap: 65536,
- SmallCap: 131072,
- ForceBold: 262144
- };
- var MacStandardGlyphOrdering = [
- '.notdef',
- '.null',
- 'nonmarkingreturn',
- 'space',
- 'exclam',
- 'quotedbl',
- 'numbersign',
- 'dollar',
- 'percent',
- 'ampersand',
- 'quotesingle',
- 'parenleft',
- 'parenright',
- 'asterisk',
- 'plus',
- 'comma',
- 'hyphen',
- 'period',
- 'slash',
- 'zero',
- 'one',
- 'two',
- 'three',
- 'four',
- 'five',
- 'six',
- 'seven',
- 'eight',
- 'nine',
- 'colon',
- 'semicolon',
- 'less',
- 'equal',
- 'greater',
- 'question',
- 'at',
- 'A',
- 'B',
- 'C',
- 'D',
- 'E',
- 'F',
- 'G',
- 'H',
- 'I',
- 'J',
- 'K',
- 'L',
- 'M',
- 'N',
- 'O',
- 'P',
- 'Q',
- 'R',
- 'S',
- 'T',
- 'U',
- 'V',
- 'W',
- 'X',
- 'Y',
- 'Z',
- 'bracketleft',
- 'backslash',
- 'bracketright',
- 'asciicircum',
- 'underscore',
- 'grave',
- 'a',
- 'b',
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i',
- 'j',
- 'k',
- 'l',
- 'm',
- 'n',
- 'o',
- 'p',
- 'q',
- 'r',
- 's',
- 't',
- 'u',
- 'v',
- 'w',
- 'x',
- 'y',
- 'z',
- 'braceleft',
- 'bar',
- 'braceright',
- 'asciitilde',
- 'Adieresis',
- 'Aring',
- 'Ccedilla',
- 'Eacute',
- 'Ntilde',
- 'Odieresis',
- 'Udieresis',
- 'aacute',
- 'agrave',
- 'acircumflex',
- 'adieresis',
- 'atilde',
- 'aring',
- 'ccedilla',
- 'eacute',
- 'egrave',
- 'ecircumflex',
- 'edieresis',
- 'iacute',
- 'igrave',
- 'icircumflex',
- 'idieresis',
- 'ntilde',
- 'oacute',
- 'ograve',
- 'ocircumflex',
- 'odieresis',
- 'otilde',
- 'uacute',
- 'ugrave',
- 'ucircumflex',
- 'udieresis',
- 'dagger',
- 'degree',
- 'cent',
- 'sterling',
- 'section',
- 'bullet',
- 'paragraph',
- 'germandbls',
- 'registered',
- 'copyright',
- 'trademark',
- 'acute',
- 'dieresis',
- 'notequal',
- 'AE',
- 'Oslash',
- 'infinity',
- 'plusminus',
- 'lessequal',
- 'greaterequal',
- 'yen',
- 'mu',
- 'partialdiff',
- 'summation',
- 'product',
- 'pi',
- 'integral',
- 'ordfeminine',
- 'ordmasculine',
- 'Omega',
- 'ae',
- 'oslash',
- 'questiondown',
- 'exclamdown',
- 'logicalnot',
- 'radical',
- 'florin',
- 'approxequal',
- 'Delta',
- 'guillemotleft',
- 'guillemotright',
- 'ellipsis',
- 'nonbreakingspace',
- 'Agrave',
- 'Atilde',
- 'Otilde',
- 'OE',
- 'oe',
- 'endash',
- 'emdash',
- 'quotedblleft',
- 'quotedblright',
- 'quoteleft',
- 'quoteright',
- 'divide',
- 'lozenge',
- 'ydieresis',
- 'Ydieresis',
- 'fraction',
- 'currency',
- 'guilsinglleft',
- 'guilsinglright',
- 'fi',
- 'fl',
- 'daggerdbl',
- 'periodcentered',
- 'quotesinglbase',
- 'quotedblbase',
- 'perthousand',
- 'Acircumflex',
- 'Ecircumflex',
- 'Aacute',
- 'Edieresis',
- 'Egrave',
- 'Iacute',
- 'Icircumflex',
- 'Idieresis',
- 'Igrave',
- 'Oacute',
- 'Ocircumflex',
- 'apple',
- 'Ograve',
- 'Uacute',
- 'Ucircumflex',
- 'Ugrave',
- 'dotlessi',
- 'circumflex',
- 'tilde',
- 'macron',
- 'breve',
- 'dotaccent',
- 'ring',
- 'cedilla',
- 'hungarumlaut',
- 'ogonek',
- 'caron',
- 'Lslash',
- 'lslash',
- 'Scaron',
- 'scaron',
- 'Zcaron',
- 'zcaron',
- 'brokenbar',
- 'Eth',
- 'eth',
- 'Yacute',
- 'yacute',
- 'Thorn',
- 'thorn',
- 'minus',
- 'multiply',
- 'onesuperior',
- 'twosuperior',
- 'threesuperior',
- 'onehalf',
- 'onequarter',
- 'threequarters',
- 'franc',
- 'Gbreve',
- 'gbreve',
- 'Idotaccent',
- 'Scedilla',
- 'scedilla',
- 'Cacute',
- 'cacute',
- 'Ccaron',
- 'ccaron',
- 'dcroat'
- ];
- function adjustWidths(properties) {
- if (!properties.fontMatrix) {
- return;
- }
- if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) {
- return;
- }
- // adjusting width to fontMatrix scale
- var scale = 0.001 / properties.fontMatrix[0];
- var glyphsWidths = properties.widths;
- for (var glyph in glyphsWidths) {
- glyphsWidths[glyph] *= scale;
- }
- properties.defaultWidth *= scale;
- }
- function adjustToUnicode(properties, builtInEncoding) {
- if (properties.hasIncludedToUnicodeMap) {
- return;
- }
- // The font dictionary has a `ToUnicode` entry.
- if (properties.hasEncoding) {
- return;
- }
- // The font dictionary has an `Encoding` entry.
- if (builtInEncoding === properties.defaultEncoding) {
- return;
- }
- // No point in trying to adjust `toUnicode` if the encodings match.
- if (properties.toUnicode instanceof IdentityToUnicodeMap) {
- return;
- }
- var toUnicode = [], glyphsUnicodeMap = getGlyphsUnicode();
- for (var charCode in builtInEncoding) {
- var glyphName = builtInEncoding[charCode];
- var unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);
- if (unicode !== -1) {
- toUnicode[charCode] = String.fromCharCode(unicode);
- }
- }
- properties.toUnicode.amend(toUnicode);
- }
- function getFontType(type, subtype) {
- switch (type) {
- case 'Type1':
- return subtype === 'Type1C' ? FontType.TYPE1C : FontType.TYPE1;
- case 'CIDFontType0':
- return subtype === 'CIDFontType0C' ? FontType.CIDFONTTYPE0C : FontType.CIDFONTTYPE0;
- case 'OpenType':
- return FontType.OPENTYPE;
- case 'TrueType':
- return FontType.TRUETYPE;
- case 'CIDFontType2':
- return FontType.CIDFONTTYPE2;
- case 'MMType1':
- return FontType.MMTYPE1;
- case 'Type0':
- return FontType.TYPE0;
- default:
- return FontType.UNKNOWN;
- }
- }
- // Some bad PDF generators, e.g. Scribus PDF, include glyph names
- // in a 'uniXXXX' format -- attempting to recover proper ones.
- function recoverGlyphName(name, glyphsUnicodeMap) {
- if (glyphsUnicodeMap[name] !== undefined) {
- return name;
- }
- // The glyph name is non-standard, trying to recover.
- var unicode = getUnicodeForGlyph(name, glyphsUnicodeMap);
- if (unicode !== -1) {
- for (var key in glyphsUnicodeMap) {
- if (glyphsUnicodeMap[key] === unicode) {
- return key;
- }
- }
- }
- info('Unable to recover a standard glyph name for: ' + name);
- return name;
- }
- var Glyph = function GlyphClosure() {
- function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) {
- this.fontChar = fontChar;
- this.unicode = unicode;
- this.accent = accent;
- this.width = width;
- this.vmetric = vmetric;
- this.operatorListId = operatorListId;
- this.isSpace = isSpace;
- this.isInFont = isInFont;
- }
- Glyph.prototype.matchesForCache = function (fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) {
- return this.fontChar === fontChar && this.unicode === unicode && this.accent === accent && this.width === width && this.vmetric === vmetric && this.operatorListId === operatorListId && this.isSpace === isSpace && this.isInFont === isInFont;
- };
- return Glyph;
- }();
- var ToUnicodeMap = function ToUnicodeMapClosure() {
- function ToUnicodeMap(cmap) {
- // The elements of this._map can be integers or strings, depending on how
- // |cmap| was created.
- this._map = cmap;
- }
- ToUnicodeMap.prototype = {
- get length() {
- return this._map.length;
- },
- forEach: function (callback) {
- for (var charCode in this._map) {
- callback(charCode, this._map[charCode].charCodeAt(0));
- }
- },
- has: function (i) {
- return this._map[i] !== undefined;
- },
- get: function (i) {
- return this._map[i];
- },
- charCodeOf: function (v) {
- return this._map.indexOf(v);
- },
- amend: function (map) {
- for (var charCode in map) {
- this._map[charCode] = map[charCode];
- }
- }
- };
- return ToUnicodeMap;
- }();
- var IdentityToUnicodeMap = function IdentityToUnicodeMapClosure() {
- function IdentityToUnicodeMap(firstChar, lastChar) {
- this.firstChar = firstChar;
- this.lastChar = lastChar;
- }
- IdentityToUnicodeMap.prototype = {
- get length() {
- return this.lastChar + 1 - this.firstChar;
- },
- forEach: function (callback) {
- for (var i = this.firstChar, ii = this.lastChar; i <= ii; i++) {
- callback(i, i);
- }
- },
- has: function (i) {
- return this.firstChar <= i && i <= this.lastChar;
- },
- get: function (i) {
- if (this.firstChar <= i && i <= this.lastChar) {
- return String.fromCharCode(i);
- }
- return undefined;
- },
- charCodeOf: function (v) {
- return isInt(v) && v >= this.firstChar && v <= this.lastChar ? v : -1;
- },
- amend: function (map) {
- error('Should not call amend()');
- }
- };
- return IdentityToUnicodeMap;
- }();
- var OpenTypeFileBuilder = function OpenTypeFileBuilderClosure() {
- function writeInt16(dest, offset, num) {
- dest[offset] = num >> 8 & 0xFF;
- dest[offset + 1] = num & 0xFF;
- }
- function writeInt32(dest, offset, num) {
- dest[offset] = num >> 24 & 0xFF;
- dest[offset + 1] = num >> 16 & 0xFF;
- dest[offset + 2] = num >> 8 & 0xFF;
- dest[offset + 3] = num & 0xFF;
- }
- function writeData(dest, offset, data) {
- var i, ii;
- if (data instanceof Uint8Array) {
- dest.set(data, offset);
- } else if (typeof data === 'string') {
- for (i = 0, ii = data.length; i < ii; i++) {
- dest[offset++] = data.charCodeAt(i) & 0xFF;
- }
- } else {
- // treating everything else as array
- for (i = 0, ii = data.length; i < ii; i++) {
- dest[offset++] = data[i] & 0xFF;
- }
- }
- }
- function OpenTypeFileBuilder(sfnt) {
- this.sfnt = sfnt;
- this.tables = Object.create(null);
- }
- OpenTypeFileBuilder.getSearchParams = function OpenTypeFileBuilder_getSearchParams(entriesCount, entrySize) {
- var maxPower2 = 1, log2 = 0;
- while ((maxPower2 ^ entriesCount) > maxPower2) {
- maxPower2 <<= 1;
- log2++;
- }
- var searchRange = maxPower2 * entrySize;
- return {
- range: searchRange,
- entry: log2,
- rangeShift: entrySize * entriesCount - searchRange
- };
- };
- var OTF_HEADER_SIZE = 12;
- var OTF_TABLE_ENTRY_SIZE = 16;
- OpenTypeFileBuilder.prototype = {
- toArray: function OpenTypeFileBuilder_toArray() {
- var sfnt = this.sfnt;
- // Tables needs to be written by ascendant alphabetic order
- var tables = this.tables;
- var tablesNames = Object.keys(tables);
- tablesNames.sort();
- var numTables = tablesNames.length;
- var i, j, jj, table, tableName;
- // layout the tables data
- var offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE;
- var tableOffsets = [offset];
- for (i = 0; i < numTables; i++) {
- table = tables[tablesNames[i]];
- var paddedLength = (table.length + 3 & ~3) >>> 0;
- offset += paddedLength;
- tableOffsets.push(offset);
- }
- var file = new Uint8Array(offset);
- // write the table data first (mostly for checksum)
- for (i = 0; i < numTables; i++) {
- table = tables[tablesNames[i]];
- writeData(file, tableOffsets[i], table);
- }
- // sfnt version (4 bytes)
- if (sfnt === 'true') {
- // Windows hates the Mac TrueType sfnt version number
- sfnt = string32(0x00010000);
- }
- file[0] = sfnt.charCodeAt(0) & 0xFF;
- file[1] = sfnt.charCodeAt(1) & 0xFF;
- file[2] = sfnt.charCodeAt(2) & 0xFF;
- file[3] = sfnt.charCodeAt(3) & 0xFF;
- // numTables (2 bytes)
- writeInt16(file, 4, numTables);
- var searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16);
- // searchRange (2 bytes)
- writeInt16(file, 6, searchParams.range);
- // entrySelector (2 bytes)
- writeInt16(file, 8, searchParams.entry);
- // rangeShift (2 bytes)
- writeInt16(file, 10, searchParams.rangeShift);
- offset = OTF_HEADER_SIZE;
- // writing table entries
- for (i = 0; i < numTables; i++) {
- tableName = tablesNames[i];
- file[offset] = tableName.charCodeAt(0) & 0xFF;
- file[offset + 1] = tableName.charCodeAt(1) & 0xFF;
- file[offset + 2] = tableName.charCodeAt(2) & 0xFF;
- file[offset + 3] = tableName.charCodeAt(3) & 0xFF;
- // checksum
- var checksum = 0;
- for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) {
- var quad = readUint32(file, j);
- checksum = checksum + quad >>> 0;
- }
- writeInt32(file, offset + 4, checksum);
- // offset
- writeInt32(file, offset + 8, tableOffsets[i]);
- // length
- writeInt32(file, offset + 12, tables[tableName].length);
- offset += OTF_TABLE_ENTRY_SIZE;
- }
- return file;
- },
- addTable: function OpenTypeFileBuilder_addTable(tag, data) {
- if (tag in this.tables) {
- throw new Error('Table ' + tag + ' already exists');
- }
- this.tables[tag] = data;
- }
- };
- return OpenTypeFileBuilder;
- }();
- // Problematic Unicode characters in the fonts that needs to be moved to avoid
- // issues when they are painted on the canvas, e.g. complex-script shaping or
- // control/whitespace characters. The ranges are listed in pairs: the first item
- // is a code of the first problematic code, the second one is the next
- // non-problematic code. The ranges must be in sorted order.
- var ProblematicCharRanges = new Int32Array([
- // Control characters.
- 0x0000,
- 0x0020,
- 0x007F,
- 0x00A1,
- 0x00AD,
- 0x00AE,
- // Chars that is used in complex-script shaping.
- 0x0600,
- 0x0780,
- 0x08A0,
- 0x10A0,
- 0x1780,
- 0x1800,
- 0x1C00,
- 0x1C50,
- // General punctuation chars.
- 0x2000,
- 0x2010,
- 0x2011,
- 0x2012,
- 0x2028,
- 0x2030,
- 0x205F,
- 0x2070,
- 0x25CC,
- 0x25CD,
- 0x3000,
- 0x3001,
- // Chars that is used in complex-script shaping.
- 0xAA60,
- 0xAA80,
- // Specials Unicode block.
- 0xFFF0,
- 0x10000
- ]);
- /**
- * 'Font' is the class the outside world should use, it encapsulate all the font
- * decoding logics whatever type it is (assuming the font type is supported).
- *
- * For example to read a Type1 font and to attach it to the document:
- * var type1Font = new Font("MyFontName", binaryFile, propertiesObject);
- * type1Font.bind();
- */
- var Font = function FontClosure() {
- function Font(name, file, properties) {
- var charCode, glyphName, unicode;
- this.name = name;
- this.loadedName = properties.loadedName;
- this.isType3Font = properties.isType3Font;
- this.sizes = [];
- this.missingFile = false;
- this.glyphCache = Object.create(null);
- var names = name.split('+');
- names = names.length > 1 ? names[1] : names[0];
- names = names.split(/[-,_]/g)[0];
- this.isSerifFont = !!(properties.flags & FontFlags.Serif);
- this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
- this.isMonospace = !!(properties.flags & FontFlags.FixedPitch);
- var type = properties.type;
- var subtype = properties.subtype;
- this.type = type;
- this.fallbackName = this.isMonospace ? 'monospace' : this.isSerifFont ? 'serif' : 'sans-serif';
- this.differences = properties.differences;
- this.widths = properties.widths;
- this.defaultWidth = properties.defaultWidth;
- this.composite = properties.composite;
- this.wideChars = properties.wideChars;
- this.cMap = properties.cMap;
- this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS;
- this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS;
- this.fontMatrix = properties.fontMatrix;
- this.bbox = properties.bbox;
- this.toUnicode = properties.toUnicode;
- this.toFontChar = [];
- if (properties.type === 'Type3') {
- for (charCode = 0; charCode < 256; charCode++) {
- this.toFontChar[charCode] = this.differences[charCode] || properties.defaultEncoding[charCode];
- }
- this.fontType = FontType.TYPE3;
- return;
- }
- this.cidEncoding = properties.cidEncoding;
- this.vertical = properties.vertical;
- if (this.vertical) {
- this.vmetrics = properties.vmetrics;
- this.defaultVMetrics = properties.defaultVMetrics;
- }
- var glyphsUnicodeMap;
- if (!file || file.isEmpty) {
- if (file) {
- // Some bad PDF generators will include empty font files,
- // attempting to recover by assuming that no file exists.
- warn('Font file is empty in "' + name + '" (' + this.loadedName + ')');
- }
- this.missingFile = true;
- // The file data is not specified. Trying to fix the font name
- // to be used with the canvas.font.
- var fontName = name.replace(/[,_]/g, '-');
- var stdFontMap = getStdFontMap(), nonStdFontMap = getNonStdFontMap();
- var isStandardFont = !!stdFontMap[fontName] || !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]);
- fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;
- this.bold = fontName.search(/bold/gi) !== -1;
- this.italic = fontName.search(/oblique/gi) !== -1 || fontName.search(/italic/gi) !== -1;
- // Use 'name' instead of 'fontName' here because the original
- // name ArialBlack for example will be replaced by Helvetica.
- this.black = name.search(/Black/g) !== -1;
- // if at least one width is present, remeasure all chars when exists
- this.remeasure = Object.keys(this.widths).length > 0;
- if (isStandardFont && type === 'CIDFontType2' && properties.cidEncoding.indexOf('Identity-') === 0) {
- var GlyphMapForStandardFonts = getGlyphMapForStandardFonts();
- // Standard fonts might be embedded as CID font without glyph mapping.
- // Building one based on GlyphMapForStandardFonts.
- var map = [];
- for (charCode in GlyphMapForStandardFonts) {
- map[+charCode] = GlyphMapForStandardFonts[charCode];
- }
- if (/ArialBlack/i.test(name)) {
- var SupplementalGlyphMapForArialBlack = getSupplementalGlyphMapForArialBlack();
- for (charCode in SupplementalGlyphMapForArialBlack) {
- map[+charCode] = SupplementalGlyphMapForArialBlack[charCode];
- }
- }
- var isIdentityUnicode = this.toUnicode instanceof IdentityToUnicodeMap;
- if (!isIdentityUnicode) {
- this.toUnicode.forEach(function (charCode, unicodeCharCode) {
- map[+charCode] = unicodeCharCode;
- });
- }
- this.toFontChar = map;
- this.toUnicode = new ToUnicodeMap(map);
- } else if (/Symbol/i.test(fontName)) {
- this.toFontChar = buildToFontChar(SymbolSetEncoding, getGlyphsUnicode(), properties.differences);
- } else if (/Dingbats/i.test(fontName)) {
- if (/Wingdings/i.test(name)) {
- warn('Non-embedded Wingdings font, falling back to ZapfDingbats.');
- }
- this.toFontChar = buildToFontChar(ZapfDingbatsEncoding, getDingbatsGlyphsUnicode(), properties.differences);
- } else if (isStandardFont) {
- this.toFontChar = buildToFontChar(properties.defaultEncoding, getGlyphsUnicode(), properties.differences);
- } else {
- glyphsUnicodeMap = getGlyphsUnicode();
- this.toUnicode.forEach(function (charCode, unicodeCharCode) {
- if (!this.composite) {
- glyphName = properties.differences[charCode] || properties.defaultEncoding[charCode];
- unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);
- if (unicode !== -1) {
- unicodeCharCode = unicode;
- }
- }
- this.toFontChar[charCode] = unicodeCharCode;
- }.bind(this));
- }
- this.loadedName = fontName.split('-')[0];
- this.loading = false;
- this.fontType = getFontType(type, subtype);
- return;
- }
- // Some fonts might use wrong font types for Type1C or CIDFontType0C
- if (subtype === 'Type1C') {
- if (type !== 'Type1' && type !== 'MMType1') {
- // Some TrueType fonts by mistake claim Type1C
- if (isTrueTypeFile(file)) {
- subtype = 'TrueType';
- } else {
- type = 'Type1';
- }
- } else if (isOpenTypeFile(file)) {
- // Sometimes the type/subtype can be a complete lie (see issue7598.pdf).
- type = subtype = 'OpenType';
- }
- }
- if (subtype === 'CIDFontType0C' && type !== 'CIDFontType0') {
- type = 'CIDFontType0';
- }
- if (subtype === 'OpenType') {
- type = 'OpenType';
- }
- // Some CIDFontType0C fonts by mistake claim CIDFontType0.
- if (type === 'CIDFontType0') {
- if (isType1File(file)) {
- subtype = 'CIDFontType0';
- } else if (isOpenTypeFile(file)) {
- // Sometimes the type/subtype can be a complete lie (see issue6782.pdf).
- type = subtype = 'OpenType';
- } else {
- subtype = 'CIDFontType0C';
- }
- }
- var data;
- switch (type) {
- case 'MMType1':
- info('MMType1 font (' + name + '), falling back to Type1.');
- case 'Type1':
- case 'CIDFontType0':
- this.mimetype = 'font/opentype';
- var cff = subtype === 'Type1C' || subtype === 'CIDFontType0C' ? new CFFFont(file, properties) : new Type1Font(name, file, properties);
- adjustWidths(properties);
- // Wrap the CFF data inside an OTF font file
- data = this.convert(name, cff, properties);
- break;
- case 'OpenType':
- case 'TrueType':
- case 'CIDFontType2':
- this.mimetype = 'font/opentype';
- // Repair the TrueType file. It is can be damaged in the point of
- // view of the sanitizer
- data = this.checkAndRepair(name, file, properties);
- if (this.isOpenType) {
- adjustWidths(properties);
- type = 'OpenType';
- }
- break;
- default:
- error('Font ' + type + ' is not supported');
- break;
- }
- this.data = data;
- this.fontType = getFontType(type, subtype);
- // Transfer some properties again that could change during font conversion
- this.fontMatrix = properties.fontMatrix;
- this.widths = properties.widths;
- this.defaultWidth = properties.defaultWidth;
- this.toUnicode = properties.toUnicode;
- this.encoding = properties.baseEncoding;
- this.seacMap = properties.seacMap;
- this.loading = true;
- }
- Font.getFontID = function () {
- var ID = 1;
- return function Font_getFontID() {
- return String(ID++);
- };
- }();
- function int16(b0, b1) {
- return (b0 << 8) + b1;
- }
- function signedInt16(b0, b1) {
- var value = (b0 << 8) + b1;
- return value & 1 << 15 ? value - 0x10000 : value;
- }
- function int32(b0, b1, b2, b3) {
- return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
- }
- function string16(value) {
- return String.fromCharCode(value >> 8 & 0xff, value & 0xff);
- }
- function safeString16(value) {
- // clamp value to the 16-bit int range
- value = value > 0x7FFF ? 0x7FFF : value < -0x8000 ? -0x8000 : value;
- return String.fromCharCode(value >> 8 & 0xff, value & 0xff);
- }
- function isTrueTypeFile(file) {
- var header = file.peekBytes(4);
- return readUint32(header, 0) === 0x00010000;
- }
- function isOpenTypeFile(file) {
- var header = file.peekBytes(4);
- return bytesToString(header) === 'OTTO';
- }
- function isType1File(file) {
- var header = file.peekBytes(2);
- // All Type1 font programs must begin with the comment '%!' (0x25 + 0x21).
- if (header[0] === 0x25 && header[1] === 0x21) {
- return true;
- }
- // ... obviously some fonts violate that part of the specification,
- // please refer to the comment in |Type1Font| below.
- if (header[0] === 0x80 && header[1] === 0x01) {
- // pfb file header.
- return true;
- }
- return false;
- }
- function buildToFontChar(encoding, glyphsUnicodeMap, differences) {
- var toFontChar = [], unicode;
- for (var i = 0, ii = encoding.length; i < ii; i++) {
- unicode = getUnicodeForGlyph(encoding[i], glyphsUnicodeMap);
- if (unicode !== -1) {
- toFontChar[i] = unicode;
- }
- }
- for (var charCode in differences) {
- unicode = getUnicodeForGlyph(differences[charCode], glyphsUnicodeMap);
- if (unicode !== -1) {
- toFontChar[+charCode] = unicode;
- }
- }
- return toFontChar;
- }
- /**
- * Helper function for |adjustMapping|.
- * @return {boolean}
- */
- function isProblematicUnicodeLocation(code) {
- // Using binary search to find a range start.
- var i = 0, j = ProblematicCharRanges.length - 1;
- while (i < j) {
- var c = i + j + 1 >> 1;
- if (code < ProblematicCharRanges[c]) {
- j = c - 1;
- } else {
- i = c;
- }
- }
- // Even index means code in problematic range.
- return !(i & 1);
- }
- /**
- * Rebuilds the char code to glyph ID map by trying to replace the char codes
- * with their unicode value. It also moves char codes that are in known
- * problematic locations.
- * @return {Object} Two properties:
- * 'toFontChar' - maps original char codes(the value that will be read
- * from commands such as show text) to the char codes that will be used in the
- * font that we build
- * 'charCodeToGlyphId' - maps the new font char codes to glyph ids
- */
- function adjustMapping(charCodeToGlyphId, properties) {
- var toUnicode = properties.toUnicode;
- var isSymbolic = !!(properties.flags & FontFlags.Symbolic);
- var isIdentityUnicode = properties.toUnicode instanceof IdentityToUnicodeMap;
- var newMap = Object.create(null);
- var toFontChar = [];
- var usedFontCharCodes = [];
- var nextAvailableFontCharCode = PRIVATE_USE_OFFSET_START;
- for (var originalCharCode in charCodeToGlyphId) {
- originalCharCode |= 0;
- var glyphId = charCodeToGlyphId[originalCharCode];
- var fontCharCode = originalCharCode;
- // First try to map the value to a unicode position if a non identity map
- // was created.
- if (!isIdentityUnicode && toUnicode.has(originalCharCode)) {
- var unicode = toUnicode.get(fontCharCode);
- // TODO: Try to map ligatures to the correct spot.
- if (unicode.length === 1) {
- fontCharCode = unicode.charCodeAt(0);
- }
- }
- // Try to move control characters, special characters and already mapped
- // characters to the private use area since they will not be drawn by
- // canvas if left in their current position. Also, move characters if the
- // font was symbolic and there is only an identity unicode map since the
- // characters probably aren't in the correct position (fixes an issue
- // with firefox and thuluthfont).
- if ((usedFontCharCodes[fontCharCode] !== undefined || isProblematicUnicodeLocation(fontCharCode) || isSymbolic && isIdentityUnicode) && nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END) {
- // Room left.
- // Loop to try and find a free spot in the private use area.
- do {
- fontCharCode = nextAvailableFontCharCode++;
- if (SKIP_PRIVATE_USE_RANGE_F000_TO_F01F && fontCharCode === 0xF000) {
- fontCharCode = 0xF020;
- nextAvailableFontCharCode = fontCharCode + 1;
- }
- } while (usedFontCharCodes[fontCharCode] !== undefined && nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END);
- }
- newMap[fontCharCode] = glyphId;
- toFontChar[originalCharCode] = fontCharCode;
- usedFontCharCodes[fontCharCode] = true;
- }
- return {
- toFontChar: toFontChar,
- charCodeToGlyphId: newMap,
- nextAvailableFontCharCode: nextAvailableFontCharCode
- };
- }
- function getRanges(glyphs, numGlyphs) {
- // Array.sort() sorts by characters, not numerically, so convert to an
- // array of characters.
- var codes = [];
- for (var charCode in glyphs) {
- // Remove an invalid glyph ID mappings to make OTS happy.
- if (glyphs[charCode] >= numGlyphs) {
- continue;
- }
- codes.push({
- fontCharCode: charCode | 0,
- glyphId: glyphs[charCode]
- });
- }
- codes.sort(function fontGetRangesSort(a, b) {
- return a.fontCharCode - b.fontCharCode;
- });
- // Split the sorted codes into ranges.
- var ranges = [];
- var length = codes.length;
- for (var n = 0; n < length;) {
- var start = codes[n].fontCharCode;
- var codeIndices = [codes[n].glyphId];
- ++n;
- var end = start;
- while (n < length && end + 1 === codes[n].fontCharCode) {
- codeIndices.push(codes[n].glyphId);
- ++end;
- ++n;
- if (end === 0xFFFF) {
- break;
- }
- }
- ranges.push([
- start,
- end,
- codeIndices
- ]);
- }
- return ranges;
- }
- function createCmapTable(glyphs, numGlyphs) {
- var ranges = getRanges(glyphs, numGlyphs);
- var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1;
- var cmap = '\x00\x00' + // version
- string16(numTables) + // numTables
- '\x00\x03' + // platformID
- '\x00\x01' + // encodingID
- string32(4 + numTables * 8);
- // start of the table record
- var i, ii, j, jj;
- for (i = ranges.length - 1; i >= 0; --i) {
- if (ranges[i][0] <= 0xFFFF) {
- break;
- }
- }
- var bmpLength = i + 1;
- if (ranges[i][0] < 0xFFFF && ranges[i][1] === 0xFFFF) {
- ranges[i][1] = 0xFFFE;
- }
- var trailingRangesCount = ranges[i][1] < 0xFFFF ? 1 : 0;
- var segCount = bmpLength + trailingRangesCount;
- var searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2);
- // Fill up the 4 parallel arrays describing the segments.
- var startCount = '';
- var endCount = '';
- var idDeltas = '';
- var idRangeOffsets = '';
- var glyphsIds = '';
- var bias = 0;
- var range, start, end, codes;
- for (i = 0, ii = bmpLength; i < ii; i++) {
- range = ranges[i];
- start = range[0];
- end = range[1];
- startCount += string16(start);
- endCount += string16(end);
- codes = range[2];
- var contiguous = true;
- for (j = 1, jj = codes.length; j < jj; ++j) {
- if (codes[j] !== codes[j - 1] + 1) {
- contiguous = false;
- break;
- }
- }
- if (!contiguous) {
- var offset = (segCount - i) * 2 + bias * 2;
- bias += end - start + 1;
- idDeltas += string16(0);
- idRangeOffsets += string16(offset);
- for (j = 0, jj = codes.length; j < jj; ++j) {
- glyphsIds += string16(codes[j]);
- }
- } else {
- var startCode = codes[0];
- idDeltas += string16(startCode - start & 0xFFFF);
- idRangeOffsets += string16(0);
- }
- }
- if (trailingRangesCount > 0) {
- endCount += '\xFF\xFF';
- startCount += '\xFF\xFF';
- idDeltas += '\x00\x01';
- idRangeOffsets += '\x00\x00';
- }
- var format314 = '\x00\x00' + // language
- string16(2 * segCount) + string16(searchParams.range) + string16(searchParams.entry) + string16(searchParams.rangeShift) + endCount + '\x00\x00' + startCount + idDeltas + idRangeOffsets + glyphsIds;
- var format31012 = '';
- var header31012 = '';
- if (numTables > 1) {
- cmap += '\x00\x03' + // platformID
- '\x00\x0A' + // encodingID
- string32(4 + numTables * 8 + 4 + format314.length);
- // start of the table record
- format31012 = '';
- for (i = 0, ii = ranges.length; i < ii; i++) {
- range = ranges[i];
- start = range[0];
- codes = range[2];
- var code = codes[0];
- for (j = 1, jj = codes.length; j < jj; ++j) {
- if (codes[j] !== codes[j - 1] + 1) {
- end = range[0] + j - 1;
- format31012 += string32(start) + // startCharCode
- string32(end) + // endCharCode
- string32(code);
- // startGlyphID
- start = end + 1;
- code = codes[j];
- }
- }
- format31012 += string32(start) + // startCharCode
- string32(range[1]) + // endCharCode
- string32(code);
- }
- // startGlyphID
- header31012 = '\x00\x0C' + // format
- '\x00\x00' + // reserved
- string32(format31012.length + 16) + // length
- '\x00\x00\x00\x00' + // language
- string32(format31012.length / 12);
- }
- // nGroups
- return cmap + '\x00\x04' + // format
- string16(format314.length + 4) + // length
- format314 + header31012 + format31012;
- }
- function validateOS2Table(os2) {
- var stream = new Stream(os2.data);
- var version = stream.getUint16();
- // TODO verify all OS/2 tables fields, but currently we validate only those
- // that give us issues
- stream.getBytes(60);
- // skipping type, misc sizes, panose, unicode ranges
- var selection = stream.getUint16();
- if (version < 4 && selection & 0x0300) {
- return false;
- }
- var firstChar = stream.getUint16();
- var lastChar = stream.getUint16();
- if (firstChar > lastChar) {
- return false;
- }
- stream.getBytes(6);
- // skipping sTypoAscender/Descender/LineGap
- var usWinAscent = stream.getUint16();
- if (usWinAscent === 0) {
- // makes font unreadable by windows
- return false;
- }
- // OS/2 appears to be valid, resetting some fields
- os2.data[8] = os2.data[9] = 0;
- // IE rejects fonts if fsType != 0
- return true;
- }
- function createOS2Table(properties, charstrings, override) {
- override = override || {
- unitsPerEm: 0,
- yMax: 0,
- yMin: 0,
- ascent: 0,
- descent: 0
- };
- var ulUnicodeRange1 = 0;
- var ulUnicodeRange2 = 0;
- var ulUnicodeRange3 = 0;
- var ulUnicodeRange4 = 0;
- var firstCharIndex = null;
- var lastCharIndex = 0;
- if (charstrings) {
- for (var code in charstrings) {
- code |= 0;
- if (firstCharIndex > code || !firstCharIndex) {
- firstCharIndex = code;
- }
- if (lastCharIndex < code) {
- lastCharIndex = code;
- }
- var position = getUnicodeRangeFor(code);
- if (position < 32) {
- ulUnicodeRange1 |= 1 << position;
- } else if (position < 64) {
- ulUnicodeRange2 |= 1 << position - 32;
- } else if (position < 96) {
- ulUnicodeRange3 |= 1 << position - 64;
- } else if (position < 123) {
- ulUnicodeRange4 |= 1 << position - 96;
- } else {
- error('Unicode ranges Bits > 123 are reserved for internal usage');
- }
- }
- } else {
- // TODO
- firstCharIndex = 0;
- lastCharIndex = 255;
- }
- var bbox = properties.bbox || [
- 0,
- 0,
- 0,
- 0
- ];
- var unitsPerEm = override.unitsPerEm || 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0];
- // if the font units differ to the PDF glyph space units
- // then scale up the values
- var scale = properties.ascentScaled ? 1.0 : unitsPerEm / PDF_GLYPH_SPACE_UNITS;
- var typoAscent = override.ascent || Math.round(scale * (properties.ascent || bbox[3]));
- var typoDescent = override.descent || Math.round(scale * (properties.descent || bbox[1]));
- if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) {
- typoDescent = -typoDescent;
- }
- // fixing incorrect descent
- var winAscent = override.yMax || typoAscent;
- var winDescent = -override.yMin || -typoDescent;
- return '\x00\x03' + // version
- '\x02\x24' + // xAvgCharWidth
- '\x01\xF4' + // usWeightClass
- '\x00\x05' + // usWidthClass
- '\x00\x00' + // fstype (0 to let the font loads via font-face on IE)
- '\x02\x8A' + // ySubscriptXSize
- '\x02\xBB' + // ySubscriptYSize
- '\x00\x00' + // ySubscriptXOffset
- '\x00\x8C' + // ySubscriptYOffset
- '\x02\x8A' + // ySuperScriptXSize
- '\x02\xBB' + // ySuperScriptYSize
- '\x00\x00' + // ySuperScriptXOffset
- '\x01\xDF' + // ySuperScriptYOffset
- '\x00\x31' + // yStrikeOutSize
- '\x01\x02' + // yStrikeOutPosition
- '\x00\x00' + // sFamilyClass
- '\x00\x00\x06' + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + '\x00\x00\x00\x00\x00\x00' + // Panose
- string32(ulUnicodeRange1) + // ulUnicodeRange1 (Bits 0-31)
- string32(ulUnicodeRange2) + // ulUnicodeRange2 (Bits 32-63)
- string32(ulUnicodeRange3) + // ulUnicodeRange3 (Bits 64-95)
- string32(ulUnicodeRange4) + // ulUnicodeRange4 (Bits 96-127)
- '\x2A\x32\x31\x2A' + // achVendID
- string16(properties.italicAngle ? 1 : 0) + // fsSelection
- string16(firstCharIndex || properties.firstChar) + // usFirstCharIndex
- string16(lastCharIndex || properties.lastChar) + // usLastCharIndex
- string16(typoAscent) + // sTypoAscender
- string16(typoDescent) + // sTypoDescender
- '\x00\x64' + // sTypoLineGap (7%-10% of the unitsPerEM value)
- string16(winAscent) + // usWinAscent
- string16(winDescent) + // usWinDescent
- '\x00\x00\x00\x00' + // ulCodePageRange1 (Bits 0-31)
- '\x00\x00\x00\x00' + // ulCodePageRange2 (Bits 32-63)
- string16(properties.xHeight) + // sxHeight
- string16(properties.capHeight) + // sCapHeight
- string16(0) + // usDefaultChar
- string16(firstCharIndex || properties.firstChar) + // usBreakChar
- '\x00\x03';
- }
- // usMaxContext
- function createPostTable(properties) {
- var angle = Math.floor(properties.italicAngle * Math.pow(2, 16));
- return '\x00\x03\x00\x00' + // Version number
- string32(angle) + // italicAngle
- '\x00\x00' + // underlinePosition
- '\x00\x00' + // underlineThickness
- string32(properties.fixedPitch) + // isFixedPitch
- '\x00\x00\x00\x00' + // minMemType42
- '\x00\x00\x00\x00' + // maxMemType42
- '\x00\x00\x00\x00' + // minMemType1
- '\x00\x00\x00\x00';
- }
- // maxMemType1
- function createNameTable(name, proto) {
- if (!proto) {
- proto = [
- [],
- []
- ];
- }
- // no strings and unicode strings
- var strings = [
- proto[0][0] || 'Original licence',
- // 0.Copyright
- proto[0][1] || name,
- // 1.Font family
- proto[0][2] || 'Unknown',
- // 2.Font subfamily (font weight)
- proto[0][3] || 'uniqueID',
- // 3.Unique ID
- proto[0][4] || name,
- // 4.Full font name
- proto[0][5] || 'Version 0.11',
- // 5.Version
- proto[0][6] || '',
- // 6.Postscript name
- proto[0][7] || 'Unknown',
- // 7.Trademark
- proto[0][8] || 'Unknown',
- // 8.Manufacturer
- proto[0][9] || 'Unknown'
- ];
- // 9.Designer
- // Mac want 1-byte per character strings while Windows want
- // 2-bytes per character, so duplicate the names table
- var stringsUnicode = [];
- var i, ii, j, jj, str;
- for (i = 0, ii = strings.length; i < ii; i++) {
- str = proto[1][i] || strings[i];
- var strBufUnicode = [];
- for (j = 0, jj = str.length; j < jj; j++) {
- strBufUnicode.push(string16(str.charCodeAt(j)));
- }
- stringsUnicode.push(strBufUnicode.join(''));
- }
- var names = [
- strings,
- stringsUnicode
- ];
- var platforms = [
- '\x00\x01',
- '\x00\x03'
- ];
- var encodings = [
- '\x00\x00',
- '\x00\x01'
- ];
- var languages = [
- '\x00\x00',
- '\x04\x09'
- ];
- var namesRecordCount = strings.length * platforms.length;
- var nameTable = '\x00\x00' + // format
- string16(namesRecordCount) + // Number of names Record
- string16(namesRecordCount * 12 + 6);
- // Storage
- // Build the name records field
- var strOffset = 0;
- for (i = 0, ii = platforms.length; i < ii; i++) {
- var strs = names[i];
- for (j = 0, jj = strs.length; j < jj; j++) {
- str = strs[j];
- var nameRecord = platforms[i] + // platform ID
- encodings[i] + // encoding ID
- languages[i] + // language ID
- string16(j) + // name ID
- string16(str.length) + string16(strOffset);
- nameTable += nameRecord;
- strOffset += str.length;
- }
- }
- nameTable += strings.join('') + stringsUnicode.join('');
- return nameTable;
- }
- Font.prototype = {
- name: null,
- font: null,
- mimetype: null,
- encoding: null,
- get renderer() {
- var renderer = FontRendererFactory.create(this, SEAC_ANALYSIS_ENABLED);
- return shadow(this, 'renderer', renderer);
- },
- exportData: function Font_exportData() {
- // TODO remove enumerating of the properties, e.g. hardcode exact names.
- var data = {};
- for (var i in this) {
- if (this.hasOwnProperty(i)) {
- data[i] = this[i];
- }
- }
- return data;
- },
- checkAndRepair: function Font_checkAndRepair(name, font, properties) {
- function readTableEntry(file) {
- var tag = bytesToString(file.getBytes(4));
- var checksum = file.getInt32() >>> 0;
- var offset = file.getInt32() >>> 0;
- var length = file.getInt32() >>> 0;
- // Read the table associated data
- var previousPosition = file.pos;
- file.pos = file.start ? file.start : 0;
- file.skip(offset);
- var data = file.getBytes(length);
- file.pos = previousPosition;
- if (tag === 'head') {
- // clearing checksum adjustment
- data[8] = data[9] = data[10] = data[11] = 0;
- data[17] |= 0x20;
- }
- //Set font optimized for cleartype flag
- return {
- tag: tag,
- checksum: checksum,
- length: length,
- offset: offset,
- data: data
- };
- }
- function readOpenTypeHeader(ttf) {
- return {
- version: bytesToString(ttf.getBytes(4)),
- numTables: ttf.getUint16(),
- searchRange: ttf.getUint16(),
- entrySelector: ttf.getUint16(),
- rangeShift: ttf.getUint16()
- };
- }
- /**
- * Read the appropriate subtable from the cmap according to 9.6.6.4 from
- * PDF spec
- */
- function readCmapTable(cmap, font, isSymbolicFont, hasEncoding) {
- if (!cmap) {
- warn('No cmap table available.');
- return {
- platformId: -1,
- encodingId: -1,
- mappings: [],
- hasShortCmap: false
- };
- }
- var segment;
- var start = (font.start ? font.start : 0) + cmap.offset;
- font.pos = start;
- var version = font.getUint16();
- var numTables = font.getUint16();
- var potentialTable;
- var canBreak = false;
- // There's an order of preference in terms of which cmap subtable to
- // use:
- // - non-symbolic fonts the preference is a 3,1 table then a 1,0 table
- // - symbolic fonts the preference is a 3,0 table then a 1,0 table
- // The following takes advantage of the fact that the tables are sorted
- // to work.
- for (var i = 0; i < numTables; i++) {
- var platformId = font.getUint16();
- var encodingId = font.getUint16();
- var offset = font.getInt32() >>> 0;
- var useTable = false;
- if (platformId === 0 && encodingId === 0) {
- useTable = true;
- } else // Continue the loop since there still may be a higher priority
- // table.
- if (platformId === 1 && encodingId === 0) {
- useTable = true;
- } else // Continue the loop since there still may be a higher priority
- // table.
- if (platformId === 3 && encodingId === 1 && (!isSymbolicFont && hasEncoding || !potentialTable)) {
- useTable = true;
- if (!isSymbolicFont) {
- canBreak = true;
- }
- } else if (isSymbolicFont && platformId === 3 && encodingId === 0) {
- useTable = true;
- canBreak = true;
- }
- if (useTable) {
- potentialTable = {
- platformId: platformId,
- encodingId: encodingId,
- offset: offset
- };
- }
- if (canBreak) {
- break;
- }
- }
- if (potentialTable) {
- font.pos = start + potentialTable.offset;
- }
- if (!potentialTable || font.peekByte() === -1) {
- warn('Could not find a preferred cmap table.');
- return {
- platformId: -1,
- encodingId: -1,
- mappings: [],
- hasShortCmap: false
- };
- }
- var format = font.getUint16();
- var length = font.getUint16();
- var language = font.getUint16();
- var hasShortCmap = false;
- var mappings = [];
- var j, glyphId;
- // TODO(mack): refactor this cmap subtable reading logic out
- if (format === 0) {
- for (j = 0; j < 256; j++) {
- var index = font.getByte();
- if (!index) {
- continue;
- }
- mappings.push({
- charCode: j,
- glyphId: index
- });
- }
- hasShortCmap = true;
- } else if (format === 4) {
- // re-creating the table in format 4 since the encoding
- // might be changed
- var segCount = font.getUint16() >> 1;
- font.getBytes(6);
- // skipping range fields
- var segIndex, segments = [];
- for (segIndex = 0; segIndex < segCount; segIndex++) {
- segments.push({ end: font.getUint16() });
- }
- font.getUint16();
- for (segIndex = 0; segIndex < segCount; segIndex++) {
- segments[segIndex].start = font.getUint16();
- }
- for (segIndex = 0; segIndex < segCount; segIndex++) {
- segments[segIndex].delta = font.getUint16();
- }
- var offsetsCount = 0;
- for (segIndex = 0; segIndex < segCount; segIndex++) {
- segment = segments[segIndex];
- var rangeOffset = font.getUint16();
- if (!rangeOffset) {
- segment.offsetIndex = -1;
- continue;
- }
- var offsetIndex = (rangeOffset >> 1) - (segCount - segIndex);
- segment.offsetIndex = offsetIndex;
- offsetsCount = Math.max(offsetsCount, offsetIndex + segment.end - segment.start + 1);
- }
- var offsets = [];
- for (j = 0; j < offsetsCount; j++) {
- offsets.push(font.getUint16());
- }
- for (segIndex = 0; segIndex < segCount; segIndex++) {
- segment = segments[segIndex];
- start = segment.start;
- var end = segment.end;
- var delta = segment.delta;
- offsetIndex = segment.offsetIndex;
- for (j = start; j <= end; j++) {
- if (j === 0xFFFF) {
- continue;
- }
- glyphId = offsetIndex < 0 ? j : offsets[offsetIndex + j - start];
- glyphId = glyphId + delta & 0xFFFF;
- if (glyphId === 0) {
- continue;
- }
- mappings.push({
- charCode: j,
- glyphId: glyphId
- });
- }
- }
- } else if (format === 6) {
- // Format 6 is a 2-bytes dense mapping, which means the font data
- // lives glue together even if they are pretty far in the unicode
- // table. (This looks weird, so I can have missed something), this
- // works on Linux but seems to fails on Mac so let's rewrite the
- // cmap table to a 3-1-4 style
- var firstCode = font.getUint16();
- var entryCount = font.getUint16();
- for (j = 0; j < entryCount; j++) {
- glyphId = font.getUint16();
- var charCode = firstCode + j;
- mappings.push({
- charCode: charCode,
- glyphId: glyphId
- });
- }
- } else {
- warn('cmap table has unsupported format: ' + format);
- return {
- platformId: -1,
- encodingId: -1,
- mappings: [],
- hasShortCmap: false
- };
- }
- // removing duplicate entries
- mappings.sort(function (a, b) {
- return a.charCode - b.charCode;
- });
- for (i = 1; i < mappings.length; i++) {
- if (mappings[i - 1].charCode === mappings[i].charCode) {
- mappings.splice(i, 1);
- i--;
- }
- }
- return {
- platformId: potentialTable.platformId,
- encodingId: potentialTable.encodingId,
- mappings: mappings,
- hasShortCmap: hasShortCmap
- };
- }
- function sanitizeMetrics(font, header, metrics, numGlyphs) {
- if (!header) {
- if (metrics) {
- metrics.data = null;
- }
- return;
- }
- font.pos = (font.start ? font.start : 0) + header.offset;
- font.pos += header.length - 2;
- var numOfMetrics = font.getUint16();
- if (numOfMetrics > numGlyphs) {
- info('The numOfMetrics (' + numOfMetrics + ') should not be ' + 'greater than the numGlyphs (' + numGlyphs + ')');
- // Reduce numOfMetrics if it is greater than numGlyphs
- numOfMetrics = numGlyphs;
- header.data[34] = (numOfMetrics & 0xff00) >> 8;
- header.data[35] = numOfMetrics & 0x00ff;
- }
- var numOfSidebearings = numGlyphs - numOfMetrics;
- var numMissing = numOfSidebearings - (metrics.length - numOfMetrics * 4 >> 1);
- if (numMissing > 0) {
- // For each missing glyph, we set both the width and lsb to 0 (zero).
- // Since we need to add two properties for each glyph, this explains
- // the use of |numMissing * 2| when initializing the typed array.
- var entries = new Uint8Array(metrics.length + numMissing * 2);
- entries.set(metrics.data);
- metrics.data = entries;
- }
- }
- function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, hintsValid) {
- if (sourceEnd - sourceStart <= 12) {
- // glyph with data less than 12 is invalid one
- return 0;
- }
- var glyf = source.subarray(sourceStart, sourceEnd);
- var contoursCount = glyf[0] << 8 | glyf[1];
- if (contoursCount & 0x8000) {
- // complex glyph, writing as is
- dest.set(glyf, destStart);
- return glyf.length;
- }
- var i, j = 10, flagsCount = 0;
- for (i = 0; i < contoursCount; i++) {
- var endPoint = glyf[j] << 8 | glyf[j + 1];
- flagsCount = endPoint + 1;
- j += 2;
- }
- // skipping instructions
- var instructionsStart = j;
- var instructionsLength = glyf[j] << 8 | glyf[j + 1];
- j += 2 + instructionsLength;
- var instructionsEnd = j;
- // validating flags
- var coordinatesLength = 0;
- for (i = 0; i < flagsCount; i++) {
- var flag = glyf[j++];
- if (flag & 0xC0) {
- // reserved flags must be zero, cleaning up
- glyf[j - 1] = flag & 0x3F;
- }
- var xyLength = (flag & 2 ? 1 : flag & 16 ? 0 : 2) + (flag & 4 ? 1 : flag & 32 ? 0 : 2);
- coordinatesLength += xyLength;
- if (flag & 8) {
- var repeat = glyf[j++];
- i += repeat;
- coordinatesLength += repeat * xyLength;
- }
- }
- // glyph without coordinates will be rejected
- if (coordinatesLength === 0) {
- return 0;
- }
- var glyphDataLength = j + coordinatesLength;
- if (glyphDataLength > glyf.length) {
- // not enough data for coordinates
- return 0;
- }
- if (!hintsValid && instructionsLength > 0) {
- dest.set(glyf.subarray(0, instructionsStart), destStart);
- dest.set([
- 0,
- 0
- ], destStart + instructionsStart);
- dest.set(glyf.subarray(instructionsEnd, glyphDataLength), destStart + instructionsStart + 2);
- glyphDataLength -= instructionsLength;
- if (glyf.length - glyphDataLength > 3) {
- glyphDataLength = glyphDataLength + 3 & ~3;
- }
- return glyphDataLength;
- }
- if (glyf.length - glyphDataLength > 3) {
- // truncating and aligning to 4 bytes the long glyph data
- glyphDataLength = glyphDataLength + 3 & ~3;
- dest.set(glyf.subarray(0, glyphDataLength), destStart);
- return glyphDataLength;
- }
- // glyph data is fine
- dest.set(glyf, destStart);
- return glyf.length;
- }
- function sanitizeHead(head, numGlyphs, locaLength) {
- var data = head.data;
- // Validate version:
- // Should always be 0x00010000
- var version = int32(data[0], data[1], data[2], data[3]);
- if (version >> 16 !== 1) {
- info('Attempting to fix invalid version in head table: ' + version);
- data[0] = 0;
- data[1] = 1;
- data[2] = 0;
- data[3] = 0;
- }
- var indexToLocFormat = int16(data[50], data[51]);
- if (indexToLocFormat < 0 || indexToLocFormat > 1) {
- info('Attempting to fix invalid indexToLocFormat in head table: ' + indexToLocFormat);
- // The value of indexToLocFormat should be 0 if the loca table
- // consists of short offsets, and should be 1 if the loca table
- // consists of long offsets.
- //
- // The number of entries in the loca table should be numGlyphs + 1.
- //
- // Using this information, we can work backwards to deduce if the
- // size of each offset in the loca table, and thus figure out the
- // appropriate value for indexToLocFormat.
- var numGlyphsPlusOne = numGlyphs + 1;
- if (locaLength === numGlyphsPlusOne << 1) {
- // 0x0000 indicates the loca table consists of short offsets
- data[50] = 0;
- data[51] = 0;
- } else if (locaLength === numGlyphsPlusOne << 2) {
- // 0x0001 indicates the loca table consists of long offsets
- data[50] = 0;
- data[51] = 1;
- } else {
- warn('Could not fix indexToLocFormat: ' + indexToLocFormat);
- }
- }
- }
- function sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry) {
- var itemSize, itemDecode, itemEncode;
- if (isGlyphLocationsLong) {
- itemSize = 4;
- itemDecode = function fontItemDecodeLong(data, offset) {
- return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
- };
- itemEncode = function fontItemEncodeLong(data, offset, value) {
- data[offset] = value >>> 24 & 0xFF;
- data[offset + 1] = value >> 16 & 0xFF;
- data[offset + 2] = value >> 8 & 0xFF;
- data[offset + 3] = value & 0xFF;
- };
- } else {
- itemSize = 2;
- itemDecode = function fontItemDecode(data, offset) {
- return data[offset] << 9 | data[offset + 1] << 1;
- };
- itemEncode = function fontItemEncode(data, offset, value) {
- data[offset] = value >> 9 & 0xFF;
- data[offset + 1] = value >> 1 & 0xFF;
- };
- }
- var locaData = loca.data;
- var locaDataSize = itemSize * (1 + numGlyphs);
- // is loca.data too short or long?
- if (locaData.length !== locaDataSize) {
- locaData = new Uint8Array(locaDataSize);
- locaData.set(loca.data.subarray(0, locaDataSize));
- loca.data = locaData;
- }
- // removing the invalid glyphs
- var oldGlyfData = glyf.data;
- var oldGlyfDataLength = oldGlyfData.length;
- var newGlyfData = new Uint8Array(oldGlyfDataLength);
- var startOffset = itemDecode(locaData, 0);
- var writeOffset = 0;
- var missingGlyphData = Object.create(null);
- itemEncode(locaData, 0, writeOffset);
- var i, j;
- for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
- var endOffset = itemDecode(locaData, j);
- if (endOffset > oldGlyfDataLength && (oldGlyfDataLength + 3 & ~3) === endOffset) {
- // Aspose breaks fonts by aligning the glyphs to the qword, but not
- // the glyf table size, which makes last glyph out of range.
- endOffset = oldGlyfDataLength;
- }
- if (endOffset > oldGlyfDataLength) {
- // glyph end offset points outside glyf data, rejecting the glyph
- itemEncode(locaData, j, writeOffset);
- startOffset = endOffset;
- continue;
- }
- if (startOffset === endOffset) {
- missingGlyphData[i] = true;
- }
- var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset, newGlyfData, writeOffset, hintsValid);
- writeOffset += newLength;
- itemEncode(locaData, j, writeOffset);
- startOffset = endOffset;
- }
- if (writeOffset === 0) {
- // glyf table cannot be empty -- redoing the glyf and loca tables
- // to have single glyph with one point
- var simpleGlyph = new Uint8Array([
- 0,
- 1,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 49,
- 0
- ]);
- for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
- itemEncode(locaData, j, simpleGlyph.length);
- }
- glyf.data = simpleGlyph;
- return missingGlyphData;
- }
- if (dupFirstEntry) {
- var firstEntryLength = itemDecode(locaData, itemSize);
- if (newGlyfData.length > firstEntryLength + writeOffset) {
- glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);
- } else {
- glyf.data = new Uint8Array(firstEntryLength + writeOffset);
- glyf.data.set(newGlyfData.subarray(0, writeOffset));
- }
- glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset);
- itemEncode(loca.data, locaData.length - itemSize, writeOffset + firstEntryLength);
- } else {
- glyf.data = newGlyfData.subarray(0, writeOffset);
- }
- return missingGlyphData;
- }
- function readPostScriptTable(post, properties, maxpNumGlyphs) {
- var start = (font.start ? font.start : 0) + post.offset;
- font.pos = start;
- var length = post.length, end = start + length;
- var version = font.getInt32();
- // skip rest to the tables
- font.getBytes(28);
- var glyphNames;
- var valid = true;
- var i;
- switch (version) {
- case 0x00010000:
- glyphNames = MacStandardGlyphOrdering;
- break;
- case 0x00020000:
- var numGlyphs = font.getUint16();
- if (numGlyphs !== maxpNumGlyphs) {
- valid = false;
- break;
- }
- var glyphNameIndexes = [];
- for (i = 0; i < numGlyphs; ++i) {
- var index = font.getUint16();
- if (index >= 32768) {
- valid = false;
- break;
- }
- glyphNameIndexes.push(index);
- }
- if (!valid) {
- break;
- }
- var customNames = [];
- var strBuf = [];
- while (font.pos < end) {
- var stringLength = font.getByte();
- strBuf.length = stringLength;
- for (i = 0; i < stringLength; ++i) {
- strBuf[i] = String.fromCharCode(font.getByte());
- }
- customNames.push(strBuf.join(''));
- }
- glyphNames = [];
- for (i = 0; i < numGlyphs; ++i) {
- var j = glyphNameIndexes[i];
- if (j < 258) {
- glyphNames.push(MacStandardGlyphOrdering[j]);
- continue;
- }
- glyphNames.push(customNames[j - 258]);
- }
- break;
- case 0x00030000:
- break;
- default:
- warn('Unknown/unsupported post table version ' + version);
- valid = false;
- if (properties.defaultEncoding) {
- glyphNames = properties.defaultEncoding;
- }
- break;
- }
- properties.glyphNames = glyphNames;
- return valid;
- }
- function readNameTable(nameTable) {
- var start = (font.start ? font.start : 0) + nameTable.offset;
- font.pos = start;
- var names = [
- [],
- []
- ];
- var length = nameTable.length, end = start + length;
- var format = font.getUint16();
- var FORMAT_0_HEADER_LENGTH = 6;
- if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) {
- // unsupported name table format or table "too" small
- return names;
- }
- var numRecords = font.getUint16();
- var stringsStart = font.getUint16();
- var records = [];
- var NAME_RECORD_LENGTH = 12;
- var i, ii;
- for (i = 0; i < numRecords && font.pos + NAME_RECORD_LENGTH <= end; i++) {
- var r = {
- platform: font.getUint16(),
- encoding: font.getUint16(),
- language: font.getUint16(),
- name: font.getUint16(),
- length: font.getUint16(),
- offset: font.getUint16()
- };
- // using only Macintosh and Windows platform/encoding names
- if (r.platform === 1 && r.encoding === 0 && r.language === 0 || r.platform === 3 && r.encoding === 1 && r.language === 0x409) {
- records.push(r);
- }
- }
- for (i = 0, ii = records.length; i < ii; i++) {
- var record = records[i];
- if (record.length <= 0) {
- continue;
- }
- // Nothing to process, ignoring.
- var pos = start + stringsStart + record.offset;
- if (pos + record.length > end) {
- continue;
- }
- // outside of name table, ignoring
- font.pos = pos;
- var nameIndex = record.name;
- if (record.encoding) {
- // unicode
- var str = '';
- for (var j = 0, jj = record.length; j < jj; j += 2) {
- str += String.fromCharCode(font.getUint16());
- }
- names[1][nameIndex] = str;
- } else {
- names[0][nameIndex] = bytesToString(font.getBytes(record.length));
- }
- }
- return names;
- }
- var TTOpsStackDeltas = [
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- -2,
- -2,
- -2,
- -2,
- 0,
- 0,
- -2,
- -5,
- -1,
- -1,
- -1,
- -1,
- -1,
- -1,
- -1,
- -1,
- 0,
- 0,
- -1,
- 0,
- -1,
- -1,
- -1,
- -1,
- 1,
- -1,
- -999,
- 0,
- 1,
- 0,
- -1,
- -2,
- 0,
- -1,
- -2,
- -1,
- -1,
- 0,
- -1,
- -1,
- 0,
- 0,
- -999,
- -999,
- -1,
- -1,
- -1,
- -1,
- -2,
- -999,
- -2,
- -2,
- -999,
- 0,
- -2,
- -2,
- 0,
- 0,
- -2,
- 0,
- -2,
- 0,
- 0,
- 0,
- -2,
- -1,
- -1,
- 1,
- 1,
- 0,
- 0,
- -1,
- -1,
- -1,
- -1,
- -1,
- -1,
- -1,
- 0,
- 0,
- -1,
- 0,
- -1,
- -1,
- 0,
- -999,
- -1,
- -1,
- -1,
- -1,
- -1,
- -1,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- -2,
- -999,
- -999,
- -999,
- -999,
- -999,
- -1,
- -1,
- -2,
- -2,
- 0,
- 0,
- 0,
- 0,
- -1,
- -1,
- -999,
- -2,
- -2,
- 0,
- 0,
- -1,
- -2,
- -2,
- 0,
- 0,
- 0,
- -1,
- -1,
- -1,
- -2
- ];
- // 0xC0-DF == -1 and 0xE0-FF == -2
- function sanitizeTTProgram(table, ttContext) {
- var data = table.data;
- var i = 0, j, n, b, funcId, pc, lastEndf = 0, lastDeff = 0;
- var stack = [];
- var callstack = [];
- var functionsCalled = [];
- var tooComplexToFollowFunctions = ttContext.tooComplexToFollowFunctions;
- var inFDEF = false, ifLevel = 0, inELSE = 0;
- for (var ii = data.length; i < ii;) {
- var op = data[i++];
- // The TrueType instruction set docs can be found at
- // https://developer.apple.com/fonts/TTRefMan/RM05/Chap5.html
- if (op === 0x40) {
- // NPUSHB - pushes n bytes
- n = data[i++];
- if (inFDEF || inELSE) {
- i += n;
- } else {
- for (j = 0; j < n; j++) {
- stack.push(data[i++]);
- }
- }
- } else if (op === 0x41) {
- // NPUSHW - pushes n words
- n = data[i++];
- if (inFDEF || inELSE) {
- i += n * 2;
- } else {
- for (j = 0; j < n; j++) {
- b = data[i++];
- stack.push(b << 8 | data[i++]);
- }
- }
- } else if ((op & 0xF8) === 0xB0) {
- // PUSHB - pushes bytes
- n = op - 0xB0 + 1;
- if (inFDEF || inELSE) {
- i += n;
- } else {
- for (j = 0; j < n; j++) {
- stack.push(data[i++]);
- }
- }
- } else if ((op & 0xF8) === 0xB8) {
- // PUSHW - pushes words
- n = op - 0xB8 + 1;
- if (inFDEF || inELSE) {
- i += n * 2;
- } else {
- for (j = 0; j < n; j++) {
- b = data[i++];
- stack.push(b << 8 | data[i++]);
- }
- }
- } else if (op === 0x2B && !tooComplexToFollowFunctions) {
- // CALL
- if (!inFDEF && !inELSE) {
- // collecting inforamtion about which functions are used
- funcId = stack[stack.length - 1];
- ttContext.functionsUsed[funcId] = true;
- if (funcId in ttContext.functionsStackDeltas) {
- stack.length += ttContext.functionsStackDeltas[funcId];
- } else if (funcId in ttContext.functionsDefined && functionsCalled.indexOf(funcId) < 0) {
- callstack.push({
- data: data,
- i: i,
- stackTop: stack.length - 1
- });
- functionsCalled.push(funcId);
- pc = ttContext.functionsDefined[funcId];
- if (!pc) {
- warn('TT: CALL non-existent function');
- ttContext.hintsValid = false;
- return;
- }
- data = pc.data;
- i = pc.i;
- }
- }
- } else if (op === 0x2C && !tooComplexToFollowFunctions) {
- // FDEF
- if (inFDEF || inELSE) {
- warn('TT: nested FDEFs not allowed');
- tooComplexToFollowFunctions = true;
- }
- inFDEF = true;
- // collecting inforamtion about which functions are defined
- lastDeff = i;
- funcId = stack.pop();
- ttContext.functionsDefined[funcId] = {
- data: data,
- i: i
- };
- } else if (op === 0x2D) {
- // ENDF - end of function
- if (inFDEF) {
- inFDEF = false;
- lastEndf = i;
- } else {
- pc = callstack.pop();
- if (!pc) {
- warn('TT: ENDF bad stack');
- ttContext.hintsValid = false;
- return;
- }
- funcId = functionsCalled.pop();
- data = pc.data;
- i = pc.i;
- ttContext.functionsStackDeltas[funcId] = stack.length - pc.stackTop;
- }
- } else if (op === 0x89) {
- // IDEF - instruction definition
- if (inFDEF || inELSE) {
- warn('TT: nested IDEFs not allowed');
- tooComplexToFollowFunctions = true;
- }
- inFDEF = true;
- // recording it as a function to track ENDF
- lastDeff = i;
- } else if (op === 0x58) {
- // IF
- ++ifLevel;
- } else if (op === 0x1B) {
- // ELSE
- inELSE = ifLevel;
- } else if (op === 0x59) {
- // EIF
- if (inELSE === ifLevel) {
- inELSE = 0;
- }
- --ifLevel;
- } else if (op === 0x1C) {
- // JMPR
- if (!inFDEF && !inELSE) {
- var offset = stack[stack.length - 1];
- // only jumping forward to prevent infinite loop
- if (offset > 0) {
- i += offset - 1;
- }
- }
- }
- // Adjusting stack not extactly, but just enough to get function id
- if (!inFDEF && !inELSE) {
- var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] : op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0;
- if (op >= 0x71 && op <= 0x75) {
- n = stack.pop();
- if (n === n) {
- stackDelta = -n * 2;
- }
- }
- while (stackDelta < 0 && stack.length > 0) {
- stack.pop();
- stackDelta++;
- }
- while (stackDelta > 0) {
- stack.push(NaN);
- // pushing any number into stack
- stackDelta--;
- }
- }
- }
- ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions;
- var content = [data];
- if (i > data.length) {
- content.push(new Uint8Array(i - data.length));
- }
- if (lastDeff > lastEndf) {
- warn('TT: complementing a missing function tail');
- // new function definition started, but not finished
- // complete function by [CLEAR, ENDF]
- content.push(new Uint8Array([
- 0x22,
- 0x2D
- ]));
- }
- foldTTTable(table, content);
- }
- function checkInvalidFunctions(ttContext, maxFunctionDefs) {
- if (ttContext.tooComplexToFollowFunctions) {
- return;
- }
- if (ttContext.functionsDefined.length > maxFunctionDefs) {
- warn('TT: more functions defined than expected');
- ttContext.hintsValid = false;
- return;
- }
- for (var j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) {
- if (j > maxFunctionDefs) {
- warn('TT: invalid function id: ' + j);
- ttContext.hintsValid = false;
- return;
- }
- if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) {
- warn('TT: undefined function: ' + j);
- ttContext.hintsValid = false;
- return;
- }
- }
- }
- function foldTTTable(table, content) {
- if (content.length > 1) {
- // concatenating the content items
- var newLength = 0;
- var j, jj;
- for (j = 0, jj = content.length; j < jj; j++) {
- newLength += content[j].length;
- }
- newLength = newLength + 3 & ~3;
- var result = new Uint8Array(newLength);
- var pos = 0;
- for (j = 0, jj = content.length; j < jj; j++) {
- result.set(content[j], pos);
- pos += content[j].length;
- }
- table.data = result;
- table.length = newLength;
- }
- }
- function sanitizeTTPrograms(fpgm, prep, cvt, maxFunctionDefs) {
- var ttContext = {
- functionsDefined: [],
- functionsUsed: [],
- functionsStackDeltas: [],
- tooComplexToFollowFunctions: false,
- hintsValid: true
- };
- if (fpgm) {
- sanitizeTTProgram(fpgm, ttContext);
- }
- if (prep) {
- sanitizeTTProgram(prep, ttContext);
- }
- if (fpgm) {
- checkInvalidFunctions(ttContext, maxFunctionDefs);
- }
- if (cvt && cvt.length & 1) {
- var cvtData = new Uint8Array(cvt.length + 1);
- cvtData.set(cvt.data);
- cvt.data = cvtData;
- }
- return ttContext.hintsValid;
- }
- // The following steps modify the original font data, making copy
- font = new Stream(new Uint8Array(font.getBytes()));
- var VALID_TABLES = [
- 'OS/2',
- 'cmap',
- 'head',
- 'hhea',
- 'hmtx',
- 'maxp',
- 'name',
- 'post',
- 'loca',
- 'glyf',
- 'fpgm',
- 'prep',
- 'cvt ',
- 'CFF '
- ];
- var header = readOpenTypeHeader(font);
- var numTables = header.numTables;
- var cff, cffFile;
- var tables = Object.create(null);
- tables['OS/2'] = null;
- tables['cmap'] = null;
- tables['head'] = null;
- tables['hhea'] = null;
- tables['hmtx'] = null;
- tables['maxp'] = null;
- tables['name'] = null;
- tables['post'] = null;
- var table;
- for (var i = 0; i < numTables; i++) {
- table = readTableEntry(font);
- if (VALID_TABLES.indexOf(table.tag) < 0) {
- continue;
- }
- // skipping table if it's not a required or optional table
- if (table.length === 0) {
- continue;
- }
- // skipping empty tables
- tables[table.tag] = table;
- }
- var isTrueType = !tables['CFF '];
- if (!isTrueType) {
- // OpenType font
- if (header.version === 'OTTO' && properties.type !== 'CIDFontType2' || !tables['head'] || !tables['hhea'] || !tables['maxp'] || !tables['post']) {
- // no major tables: throwing everything at CFFFont
- cffFile = new Stream(tables['CFF '].data);
- cff = new CFFFont(cffFile, properties);
- adjustWidths(properties);
- return this.convert(name, cff, properties);
- }
- delete tables['glyf'];
- delete tables['loca'];
- delete tables['fpgm'];
- delete tables['prep'];
- delete tables['cvt '];
- this.isOpenType = true;
- } else {
- if (!tables['loca']) {
- error('Required "loca" table is not found');
- }
- if (!tables['glyf']) {
- warn('Required "glyf" table is not found -- trying to recover.');
- // Note: We use `sanitizeGlyphLocations` to add dummy glyf data below.
- tables['glyf'] = {
- tag: 'glyf',
- data: new Uint8Array(0)
- };
- }
- this.isOpenType = false;
- }
- if (!tables['maxp']) {
- error('Required "maxp" table is not found');
- }
- font.pos = (font.start || 0) + tables['maxp'].offset;
- var version = font.getInt32();
- var numGlyphs = font.getUint16();
- var maxFunctionDefs = 0;
- if (version >= 0x00010000 && tables['maxp'].length >= 22) {
- // maxZones can be invalid
- font.pos += 8;
- var maxZones = font.getUint16();
- if (maxZones > 2) {
- // reset to 2 if font has invalid maxZones
- tables['maxp'].data[14] = 0;
- tables['maxp'].data[15] = 2;
- }
- font.pos += 4;
- maxFunctionDefs = font.getUint16();
- }
- var dupFirstEntry = false;
- if (properties.type === 'CIDFontType2' && properties.toUnicode && properties.toUnicode.get(0) > '\u0000') {
- // oracle's defect (see 3427), duplicating first entry
- dupFirstEntry = true;
- numGlyphs++;
- tables['maxp'].data[4] = numGlyphs >> 8;
- tables['maxp'].data[5] = numGlyphs & 255;
- }
- var hintsValid = sanitizeTTPrograms(tables['fpgm'], tables['prep'], tables['cvt '], maxFunctionDefs);
- if (!hintsValid) {
- delete tables['fpgm'];
- delete tables['prep'];
- delete tables['cvt '];
- }
- // Ensure the hmtx table contains the advance width and
- // sidebearings information for numGlyphs in the maxp table
- sanitizeMetrics(font, tables['hhea'], tables['hmtx'], numGlyphs);
- if (!tables['head']) {
- error('Required "head" table is not found');
- }
- sanitizeHead(tables['head'], numGlyphs, isTrueType ? tables['loca'].length : 0);
- var missingGlyphs = Object.create(null);
- if (isTrueType) {
- var isGlyphLocationsLong = int16(tables['head'].data[50], tables['head'].data[51]);
- missingGlyphs = sanitizeGlyphLocations(tables['loca'], tables['glyf'], numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry);
- }
- if (!tables['hhea']) {
- error('Required "hhea" table is not found');
- }
- // Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth
- // Sometimes it's 0. That needs to be fixed
- if (tables['hhea'].data[10] === 0 && tables['hhea'].data[11] === 0) {
- tables['hhea'].data[10] = 0xFF;
- tables['hhea'].data[11] = 0xFF;
- }
- // Extract some more font properties from the OpenType head and
- // hhea tables; yMin and descent value are always negative.
- var metricsOverride = {
- unitsPerEm: int16(tables['head'].data[18], tables['head'].data[19]),
- yMax: int16(tables['head'].data[42], tables['head'].data[43]),
- yMin: signedInt16(tables['head'].data[38], tables['head'].data[39]),
- ascent: int16(tables['hhea'].data[4], tables['hhea'].data[5]),
- descent: signedInt16(tables['hhea'].data[6], tables['hhea'].data[7])
- };
- // PDF FontDescriptor metrics lie -- using data from actual font.
- this.ascent = metricsOverride.ascent / metricsOverride.unitsPerEm;
- this.descent = metricsOverride.descent / metricsOverride.unitsPerEm;
- // The 'post' table has glyphs names.
- if (tables['post']) {
- var valid = readPostScriptTable(tables['post'], properties, numGlyphs);
- if (!valid) {
- tables['post'] = null;
- }
- }
- var charCodeToGlyphId = [], charCode;
- var toUnicode = properties.toUnicode, widths = properties.widths;
- var skipToUnicode = toUnicode instanceof IdentityToUnicodeMap || toUnicode.length === 0x10000;
- // Helper function to try to skip mapping of empty glyphs.
- // Note: In some cases, just relying on the glyph data doesn't work,
- // hence we also use a few heuristics to fix various PDF files.
- function hasGlyph(glyphId, charCode, widthCode) {
- if (!missingGlyphs[glyphId]) {
- return true;
- }
- if (!skipToUnicode && charCode >= 0 && toUnicode.has(charCode)) {
- return true;
- }
- if (widths && widthCode >= 0 && isNum(widths[widthCode])) {
- return true;
- }
- return false;
- }
- if (properties.type === 'CIDFontType2') {
- var cidToGidMap = properties.cidToGidMap || [];
- var isCidToGidMapEmpty = cidToGidMap.length === 0;
- properties.cMap.forEach(function (charCode, cid) {
- assert(cid <= 0xffff, 'Max size of CID is 65,535');
- var glyphId = -1;
- if (isCidToGidMapEmpty) {
- glyphId = cid;
- } else if (cidToGidMap[cid] !== undefined) {
- glyphId = cidToGidMap[cid];
- }
- if (glyphId >= 0 && glyphId < numGlyphs && hasGlyph(glyphId, charCode, cid)) {
- charCodeToGlyphId[charCode] = glyphId;
- }
- });
- if (dupFirstEntry && (isCidToGidMapEmpty || !charCodeToGlyphId[0])) {
- // We don't duplicate the first entry in the `charCodeToGlyphId` map
- // if the font has a `CIDToGIDMap` which has already mapped the first
- // entry to a non-zero `glyphId` (fixes issue7544.pdf).
- charCodeToGlyphId[0] = numGlyphs - 1;
- }
- } else {
- // Most of the following logic in this code branch is based on the
- // 9.6.6.4 of the PDF spec.
- var cmapTable = readCmapTable(tables['cmap'], font, this.isSymbolicFont, properties.hasEncoding);
- var cmapPlatformId = cmapTable.platformId;
- var cmapEncodingId = cmapTable.encodingId;
- var cmapMappings = cmapTable.mappings;
- var cmapMappingsLength = cmapMappings.length;
- // The spec seems to imply that if the font is symbolic the encoding
- // should be ignored, this doesn't appear to work for 'preistabelle.pdf'
- // where the the font is symbolic and it has an encoding.
- if (properties.hasEncoding && (cmapPlatformId === 3 && cmapEncodingId === 1 || cmapPlatformId === 1 && cmapEncodingId === 0) || cmapPlatformId === -1 && cmapEncodingId === -1 && // Temporary hack
- !!getEncoding(properties.baseEncodingName)) {
- // Temporary hack
- // When no preferred cmap table was found and |baseEncodingName| is
- // one of the predefined encodings, we seem to obtain a better
- // |charCodeToGlyphId| map from the code below (fixes bug 1057544).
- // TODO: Note that this is a hack which should be removed as soon as
- // we have proper support for more exotic cmap tables.
- var baseEncoding = [];
- if (properties.baseEncodingName === 'MacRomanEncoding' || properties.baseEncodingName === 'WinAnsiEncoding') {
- baseEncoding = getEncoding(properties.baseEncodingName);
- }
- var glyphsUnicodeMap = getGlyphsUnicode();
- for (charCode = 0; charCode < 256; charCode++) {
- var glyphName, standardGlyphName;
- if (this.differences && charCode in this.differences) {
- glyphName = this.differences[charCode];
- } else if (charCode in baseEncoding && baseEncoding[charCode] !== '') {
- glyphName = baseEncoding[charCode];
- } else {
- glyphName = StandardEncoding[charCode];
- }
- if (!glyphName) {
- continue;
- }
- // Ensure that non-standard glyph names are resolved to valid ones.
- standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);
- var unicodeOrCharCode, isUnicode = false;
- if (cmapPlatformId === 3 && cmapEncodingId === 1) {
- unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName];
- isUnicode = true;
- } else if (cmapPlatformId === 1 && cmapEncodingId === 0) {
- // TODO: the encoding needs to be updated with mac os table.
- unicodeOrCharCode = MacRomanEncoding.indexOf(standardGlyphName);
- }
- var found = false;
- for (i = 0; i < cmapMappingsLength; ++i) {
- if (cmapMappings[i].charCode !== unicodeOrCharCode) {
- continue;
- }
- var code = isUnicode ? charCode : unicodeOrCharCode;
- if (hasGlyph(cmapMappings[i].glyphId, code, -1)) {
- charCodeToGlyphId[charCode] = cmapMappings[i].glyphId;
- found = true;
- break;
- }
- }
- if (!found && properties.glyphNames) {
- // Try to map using the post table.
- var glyphId = properties.glyphNames.indexOf(glyphName);
- // The post table ought to use the same kind of glyph names as the
- // `differences` array, but check the standard ones as a fallback.
- if (glyphId === -1 && standardGlyphName !== glyphName) {
- glyphId = properties.glyphNames.indexOf(standardGlyphName);
- }
- if (glyphId > 0 && hasGlyph(glyphId, -1, -1)) {
- charCodeToGlyphId[charCode] = glyphId;
- found = true;
- }
- }
- if (!found) {
- charCodeToGlyphId[charCode] = 0;
- }
- }
- } else // notdef
- if (cmapPlatformId === 0 && cmapEncodingId === 0) {
- // Default Unicode semantics, use the charcodes as is.
- for (i = 0; i < cmapMappingsLength; ++i) {
- charCodeToGlyphId[cmapMappings[i].charCode] = cmapMappings[i].glyphId;
- }
- } else {
- // For (3, 0) cmap tables:
- // The charcode key being stored in charCodeToGlyphId is the lower
- // byte of the two-byte charcodes of the cmap table since according to
- // the spec: 'each byte from the string shall be prepended with the
- // high byte of the range [of charcodes in the cmap table], to form
- // a two-byte character, which shall be used to select the
- // associated glyph description from the subtable'.
- //
- // For (1, 0) cmap tables:
- // 'single bytes from the string shall be used to look up the
- // associated glyph descriptions from the subtable'. This means
- // charcodes in the cmap will be single bytes, so no-op since
- // glyph.charCode & 0xFF === glyph.charCode
- for (i = 0; i < cmapMappingsLength; ++i) {
- charCode = cmapMappings[i].charCode & 0xFF;
- charCodeToGlyphId[charCode] = cmapMappings[i].glyphId;
- }
- }
- }
- if (charCodeToGlyphId.length === 0) {
- // defines at least one glyph
- charCodeToGlyphId[0] = 0;
- }
- // Converting glyphs and ids into font's cmap table
- var newMapping = adjustMapping(charCodeToGlyphId, properties);
- this.toFontChar = newMapping.toFontChar;
- tables['cmap'] = {
- tag: 'cmap',
- data: createCmapTable(newMapping.charCodeToGlyphId, numGlyphs)
- };
- if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) {
- tables['OS/2'] = {
- tag: 'OS/2',
- data: createOS2Table(properties, newMapping.charCodeToGlyphId, metricsOverride)
- };
- }
- // Rewrite the 'post' table if needed
- if (!tables['post']) {
- tables['post'] = {
- tag: 'post',
- data: createPostTable(properties)
- };
- }
- if (!isTrueType) {
- try {
- // Trying to repair CFF file
- cffFile = new Stream(tables['CFF '].data);
- var parser = new CFFParser(cffFile, properties, SEAC_ANALYSIS_ENABLED);
- cff = parser.parse();
- var compiler = new CFFCompiler(cff);
- tables['CFF '].data = compiler.compile();
- } catch (e) {
- warn('Failed to compile font ' + properties.loadedName);
- }
- }
- // Re-creating 'name' table
- if (!tables['name']) {
- tables['name'] = {
- tag: 'name',
- data: createNameTable(this.name)
- };
- } else {
- // ... using existing 'name' table as prototype
- var namePrototype = readNameTable(tables['name']);
- tables['name'].data = createNameTable(name, namePrototype);
- }
- var builder = new OpenTypeFileBuilder(header.version);
- for (var tableTag in tables) {
- builder.addTable(tableTag, tables[tableTag].data);
- }
- return builder.toArray();
- },
- convert: function Font_convert(fontName, font, properties) {
- // TODO: Check the charstring widths to determine this.
- properties.fixedPitch = false;
- if (properties.builtInEncoding) {
- // For Type1 fonts that do not include either `ToUnicode` or `Encoding`
- // data, attempt to use the `builtInEncoding` to improve text selection.
- adjustToUnicode(properties, properties.builtInEncoding);
- }
- var mapping = font.getGlyphMapping(properties);
- var newMapping = adjustMapping(mapping, properties);
- this.toFontChar = newMapping.toFontChar;
- var numGlyphs = font.numGlyphs;
- function getCharCodes(charCodeToGlyphId, glyphId) {
- var charCodes = null;
- for (var charCode in charCodeToGlyphId) {
- if (glyphId === charCodeToGlyphId[charCode]) {
- if (!charCodes) {
- charCodes = [];
- }
- charCodes.push(charCode | 0);
- }
- }
- return charCodes;
- }
- function createCharCode(charCodeToGlyphId, glyphId) {
- for (var charCode in charCodeToGlyphId) {
- if (glyphId === charCodeToGlyphId[charCode]) {
- return charCode | 0;
- }
- }
- newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = glyphId;
- return newMapping.nextAvailableFontCharCode++;
- }
- var seacs = font.seacs;
- if (SEAC_ANALYSIS_ENABLED && seacs && seacs.length) {
- var matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX;
- var charset = font.getCharset();
- var seacMap = Object.create(null);
- for (var glyphId in seacs) {
- glyphId |= 0;
- var seac = seacs[glyphId];
- var baseGlyphName = StandardEncoding[seac[2]];
- var accentGlyphName = StandardEncoding[seac[3]];
- var baseGlyphId = charset.indexOf(baseGlyphName);
- var accentGlyphId = charset.indexOf(accentGlyphName);
- if (baseGlyphId < 0 || accentGlyphId < 0) {
- continue;
- }
- var accentOffset = {
- x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4],
- y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5]
- };
- var charCodes = getCharCodes(mapping, glyphId);
- if (!charCodes) {
- // There's no point in mapping it if the char code was never mapped
- // to begin with.
- continue;
- }
- for (var i = 0, ii = charCodes.length; i < ii; i++) {
- var charCode = charCodes[i];
- // Find a fontCharCode that maps to the base and accent glyphs.
- // If one doesn't exists, create it.
- var charCodeToGlyphId = newMapping.charCodeToGlyphId;
- var baseFontCharCode = createCharCode(charCodeToGlyphId, baseGlyphId);
- var accentFontCharCode = createCharCode(charCodeToGlyphId, accentGlyphId);
- seacMap[charCode] = {
- baseFontCharCode: baseFontCharCode,
- accentFontCharCode: accentFontCharCode,
- accentOffset: accentOffset
- };
- }
- }
- properties.seacMap = seacMap;
- }
- var unitsPerEm = 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0];
- var builder = new OpenTypeFileBuilder('\x4F\x54\x54\x4F');
- // PostScript Font Program
- builder.addTable('CFF ', font.data);
- // OS/2 and Windows Specific metrics
- builder.addTable('OS/2', createOS2Table(properties, newMapping.charCodeToGlyphId));
- // Character to glyphs mapping
- builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId, numGlyphs));
- // Font header
- builder.addTable('head', '\x00\x01\x00\x00' + // Version number
- '\x00\x00\x10\x00' + // fontRevision
- '\x00\x00\x00\x00' + // checksumAdjustement
- '\x5F\x0F\x3C\xF5' + // magicNumber
- '\x00\x00' + // Flags
- safeString16(unitsPerEm) + // unitsPerEM
- '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // creation date
- '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // modifification date
- '\x00\x00' + // xMin
- safeString16(properties.descent) + // yMin
- '\x0F\xFF' + // xMax
- safeString16(properties.ascent) + // yMax
- string16(properties.italicAngle ? 2 : 0) + // macStyle
- '\x00\x11' + // lowestRecPPEM
- '\x00\x00' + // fontDirectionHint
- '\x00\x00' + // indexToLocFormat
- '\x00\x00');
- // glyphDataFormat
- // Horizontal header
- builder.addTable('hhea', '\x00\x01\x00\x00' + // Version number
- safeString16(properties.ascent) + // Typographic Ascent
- safeString16(properties.descent) + // Typographic Descent
- '\x00\x00' + // Line Gap
- '\xFF\xFF' + // advanceWidthMax
- '\x00\x00' + // minLeftSidebearing
- '\x00\x00' + // minRightSidebearing
- '\x00\x00' + // xMaxExtent
- safeString16(properties.capHeight) + // caretSlopeRise
- safeString16(Math.tan(properties.italicAngle) * properties.xHeight) + // caretSlopeRun
- '\x00\x00' + // caretOffset
- '\x00\x00' + // -reserved-
- '\x00\x00' + // -reserved-
- '\x00\x00' + // -reserved-
- '\x00\x00' + // -reserved-
- '\x00\x00' + // metricDataFormat
- string16(numGlyphs));
- // Number of HMetrics
- // Horizontal metrics
- builder.addTable('hmtx', function fontFieldsHmtx() {
- var charstrings = font.charstrings;
- var cffWidths = font.cff ? font.cff.widths : null;
- var hmtx = '\x00\x00\x00\x00';
- // Fake .notdef
- for (var i = 1, ii = numGlyphs; i < ii; i++) {
- var width = 0;
- if (charstrings) {
- var charstring = charstrings[i - 1];
- width = 'width' in charstring ? charstring.width : 0;
- } else if (cffWidths) {
- width = Math.ceil(cffWidths[i] || 0);
- }
- hmtx += string16(width) + string16(0);
- }
- return hmtx;
- }());
- // Maximum profile
- builder.addTable('maxp', '\x00\x00\x50\x00' + // Version number
- string16(numGlyphs));
- // Num of glyphs
- // Naming tables
- builder.addTable('name', createNameTable(fontName));
- // PostScript information
- builder.addTable('post', createPostTable(properties));
- return builder.toArray();
- },
- get spaceWidth() {
- if ('_shadowWidth' in this) {
- return this._shadowWidth;
- }
- // trying to estimate space character width
- var possibleSpaceReplacements = [
- 'space',
- 'minus',
- 'one',
- 'i',
- 'I'
- ];
- var width;
- for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) {
- var glyphName = possibleSpaceReplacements[i];
- // if possible, getting width by glyph name
- if (glyphName in this.widths) {
- width = this.widths[glyphName];
- break;
- }
- var glyphsUnicodeMap = getGlyphsUnicode();
- var glyphUnicode = glyphsUnicodeMap[glyphName];
- // finding the charcode via unicodeToCID map
- var charcode = 0;
- if (this.composite) {
- if (this.cMap.contains(glyphUnicode)) {
- charcode = this.cMap.lookup(glyphUnicode);
- }
- }
- // ... via toUnicode map
- if (!charcode && this.toUnicode) {
- charcode = this.toUnicode.charCodeOf(glyphUnicode);
- }
- // setting it to unicode if negative or undefined
- if (charcode <= 0) {
- charcode = glyphUnicode;
- }
- // trying to get width via charcode
- width = this.widths[charcode];
- if (width) {
- break;
- }
- }
- // the non-zero width found
- width = width || this.defaultWidth;
- // Do not shadow the property here. See discussion:
- // https://github.com/mozilla/pdf.js/pull/2127#discussion_r1662280
- this._shadowWidth = width;
- return width;
- },
- charToGlyph: function Font_charToGlyph(charcode, isSpace) {
- var fontCharCode, width, operatorListId;
- var widthCode = charcode;
- if (this.cMap && this.cMap.contains(charcode)) {
- widthCode = this.cMap.lookup(charcode);
- }
- width = this.widths[widthCode];
- width = isNum(width) ? width : this.defaultWidth;
- var vmetric = this.vmetrics && this.vmetrics[widthCode];
- var unicode = this.toUnicode.get(charcode) || charcode;
- if (typeof unicode === 'number') {
- unicode = String.fromCharCode(unicode);
- }
- var isInFont = charcode in this.toFontChar;
- // First try the toFontChar map, if it's not there then try falling
- // back to the char code.
- fontCharCode = this.toFontChar[charcode] || charcode;
- if (this.missingFile) {
- fontCharCode = mapSpecialUnicodeValues(fontCharCode);
- }
- if (this.isType3Font) {
- // Font char code in this case is actually a glyph name.
- operatorListId = fontCharCode;
- }
- var accent = null;
- if (this.seacMap && this.seacMap[charcode]) {
- isInFont = true;
- var seac = this.seacMap[charcode];
- fontCharCode = seac.baseFontCharCode;
- accent = {
- fontChar: String.fromCharCode(seac.accentFontCharCode),
- offset: seac.accentOffset
- };
- }
- var fontChar = String.fromCharCode(fontCharCode);
- var glyph = this.glyphCache[charcode];
- if (!glyph || !glyph.matchesForCache(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont)) {
- glyph = new Glyph(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont);
- this.glyphCache[charcode] = glyph;
- }
- return glyph;
- },
- charsToGlyphs: function Font_charsToGlyphs(chars) {
- var charsCache = this.charsCache;
- var glyphs, glyph, charcode;
- // if we translated this string before, just grab it from the cache
- if (charsCache) {
- glyphs = charsCache[chars];
- if (glyphs) {
- return glyphs;
- }
- }
- // lazily create the translation cache
- if (!charsCache) {
- charsCache = this.charsCache = Object.create(null);
- }
- glyphs = [];
- var charsCacheKey = chars;
- var i = 0, ii;
- if (this.cMap) {
- // composite fonts have multi-byte strings convert the string from
- // single-byte to multi-byte
- var c = Object.create(null);
- while (i < chars.length) {
- this.cMap.readCharCode(chars, i, c);
- charcode = c.charcode;
- var length = c.length;
- i += length;
- // Space is char with code 0x20 and length 1 in multiple-byte codes.
- var isSpace = length === 1 && chars.charCodeAt(i - 1) === 0x20;
- glyph = this.charToGlyph(charcode, isSpace);
- glyphs.push(glyph);
- }
- } else {
- for (i = 0, ii = chars.length; i < ii; ++i) {
- charcode = chars.charCodeAt(i);
- glyph = this.charToGlyph(charcode, charcode === 0x20);
- glyphs.push(glyph);
- }
- }
- // Enter the translated string into the cache
- return charsCache[charsCacheKey] = glyphs;
- }
- };
- return Font;
- }();
- var ErrorFont = function ErrorFontClosure() {
- function ErrorFont(error) {
- this.error = error;
- this.loadedName = 'g_font_error';
- this.loading = false;
- }
- ErrorFont.prototype = {
- charsToGlyphs: function ErrorFont_charsToGlyphs() {
- return [];
- },
- exportData: function ErrorFont_exportData() {
- return { error: this.error };
- }
- };
- return ErrorFont;
- }();
- /**
- * Shared logic for building a char code to glyph id mapping for Type1 and
- * simple CFF fonts. See section 9.6.6.2 of the spec.
- * @param {Object} properties Font properties object.
- * @param {Object} builtInEncoding The encoding contained within the actual font
- * data.
- * @param {Array} glyphNames Array of glyph names where the index is the
- * glyph ID.
- * @returns {Object} A char code to glyph ID map.
- */
- function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) {
- var charCodeToGlyphId = Object.create(null);
- var glyphId, charCode, baseEncoding;
- if (properties.baseEncodingName) {
- // If a valid base encoding name was used, the mapping is initialized with
- // that.
- baseEncoding = getEncoding(properties.baseEncodingName);
- for (charCode = 0; charCode < baseEncoding.length; charCode++) {
- glyphId = glyphNames.indexOf(baseEncoding[charCode]);
- if (glyphId >= 0) {
- charCodeToGlyphId[charCode] = glyphId;
- } else {
- charCodeToGlyphId[charCode] = 0;
- }
- }
- } else // notdef
- if (!!(properties.flags & FontFlags.Symbolic)) {
- // For a symbolic font the encoding should be the fonts built-in
- // encoding.
- for (charCode in builtInEncoding) {
- charCodeToGlyphId[charCode] = builtInEncoding[charCode];
- }
- } else {
- // For non-symbolic fonts that don't have a base encoding the standard
- // encoding should be used.
- baseEncoding = StandardEncoding;
- for (charCode = 0; charCode < baseEncoding.length; charCode++) {
- glyphId = glyphNames.indexOf(baseEncoding[charCode]);
- if (glyphId >= 0) {
- charCodeToGlyphId[charCode] = glyphId;
- } else {
- charCodeToGlyphId[charCode] = 0;
- }
- }
- }
- // notdef
- // Lastly, merge in the differences.
- var differences = properties.differences, glyphsUnicodeMap;
- if (differences) {
- for (charCode in differences) {
- var glyphName = differences[charCode];
- glyphId = glyphNames.indexOf(glyphName);
- if (glyphId === -1) {
- if (!glyphsUnicodeMap) {
- glyphsUnicodeMap = getGlyphsUnicode();
- }
- var standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);
- if (standardGlyphName !== glyphName) {
- glyphId = glyphNames.indexOf(standardGlyphName);
- }
- }
- if (glyphId >= 0) {
- charCodeToGlyphId[charCode] = glyphId;
- } else {
- charCodeToGlyphId[charCode] = 0;
- }
- }
- }
- // notdef
- return charCodeToGlyphId;
- }
- // Type1Font is also a CIDFontType0.
- var Type1Font = function Type1FontClosure() {
- function findBlock(streamBytes, signature, startIndex) {
- var streamBytesLength = streamBytes.length;
- var signatureLength = signature.length;
- var scanLength = streamBytesLength - signatureLength;
- var i = startIndex, j, found = false;
- while (i < scanLength) {
- j = 0;
- while (j < signatureLength && streamBytes[i + j] === signature[j]) {
- j++;
- }
- if (j >= signatureLength) {
- // `signature` found, skip over whitespace.
- i += j;
- while (i < streamBytesLength && isSpace(streamBytes[i])) {
- i++;
- }
- found = true;
- break;
- }
- i++;
- }
- return {
- found: found,
- length: i
- };
- }
- function getHeaderBlock(stream, suggestedLength) {
- var EEXEC_SIGNATURE = [
- 0x65,
- 0x65,
- 0x78,
- 0x65,
- 0x63
- ];
- var streamStartPos = stream.pos;
- // Save the initial stream position.
- var headerBytes, headerBytesLength, block;
- try {
- headerBytes = stream.getBytes(suggestedLength);
- headerBytesLength = headerBytes.length;
- } catch (ex) {
- if (ex instanceof MissingDataException) {
- throw ex;
- }
- }
- // Ignore errors if the `suggestedLength` is huge enough that a Uint8Array
- // cannot hold the result of `getBytes`, and fallback to simply checking
- // the entire stream (fixes issue3928.pdf).
- if (headerBytesLength === suggestedLength) {
- // Most of the time `suggestedLength` is correct, so to speed things up we
- // initially only check the last few bytes to see if the header was found.
- // Otherwise we (potentially) check the entire stream to prevent errors in
- // `Type1Parser` (fixes issue5686.pdf).
- block = findBlock(headerBytes, EEXEC_SIGNATURE, suggestedLength - 2 * EEXEC_SIGNATURE.length);
- if (block.found && block.length === suggestedLength) {
- return {
- stream: new Stream(headerBytes),
- length: suggestedLength
- };
- }
- }
- warn('Invalid "Length1" property in Type1 font -- trying to recover.');
- stream.pos = streamStartPos;
- // Reset the stream position.
- var SCAN_BLOCK_LENGTH = 2048;
- var actualLength;
- while (true) {
- var scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);
- block = findBlock(scanBytes, EEXEC_SIGNATURE, 0);
- if (block.length === 0) {
- break;
- }
- stream.pos += block.length;
- // Update the stream position.
- if (block.found) {
- actualLength = stream.pos - streamStartPos;
- break;
- }
- }
- stream.pos = streamStartPos;
- // Reset the stream position.
- if (actualLength) {
- return {
- stream: new Stream(stream.getBytes(actualLength)),
- length: actualLength
- };
- }
- warn('Unable to recover "Length1" property in Type1 font -- using as is.');
- return {
- stream: new Stream(stream.getBytes(suggestedLength)),
- length: suggestedLength
- };
- }
- function getEexecBlock(stream, suggestedLength) {
- // We should ideally parse the eexec block to ensure that `suggestedLength`
- // is correct, so we don't truncate the block data if it's too small.
- // However, this would also require checking if the fixed-content portion
- // exists (using the 'Length3' property), and ensuring that it's valid.
- //
- // Given that `suggestedLength` almost always is correct, all the validation
- // would require a great deal of unnecessary parsing for most fonts.
- // To save time, we always fetch the entire stream instead, which also avoid
- // issues if `suggestedLength` is huge (see comment in `getHeaderBlock`).
- //
- // NOTE: This means that the function can include the fixed-content portion
- // in the returned eexec block. In practice this does *not* seem to matter,
- // since `Type1Parser_extractFontProgram` will skip over any non-commands.
- var eexecBytes = stream.getBytes();
- return {
- stream: new Stream(eexecBytes),
- length: eexecBytes.length
- };
- }
- function Type1Font(name, file, properties) {
- // Some bad generators embed pfb file as is, we have to strip 6-byte header.
- // Also, length1 and length2 might be off by 6 bytes as well.
- // http://www.math.ubc.ca/~cass/piscript/type1.pdf
- var PFB_HEADER_SIZE = 6;
- var headerBlockLength = properties.length1;
- var eexecBlockLength = properties.length2;
- var pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
- var pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01;
- if (pfbHeaderPresent) {
- file.skip(PFB_HEADER_SIZE);
- headerBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];
- }
- // Get the data block containing glyphs and subrs information
- var headerBlock = getHeaderBlock(file, headerBlockLength);
- headerBlockLength = headerBlock.length;
- var headerBlockParser = new Type1Parser(headerBlock.stream, false, SEAC_ANALYSIS_ENABLED);
- headerBlockParser.extractFontHeader(properties);
- if (pfbHeaderPresent) {
- pfbHeader = file.getBytes(PFB_HEADER_SIZE);
- eexecBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];
- }
- // Decrypt the data blocks and retrieve it's content
- var eexecBlock = getEexecBlock(file, eexecBlockLength);
- eexecBlockLength = eexecBlock.length;
- var eexecBlockParser = new Type1Parser(eexecBlock.stream, true, SEAC_ANALYSIS_ENABLED);
- var data = eexecBlockParser.extractFontProgram();
- for (var info in data.properties) {
- properties[info] = data.properties[info];
- }
- var charstrings = data.charstrings;
- var type2Charstrings = this.getType2Charstrings(charstrings);
- var subrs = this.getType2Subrs(data.subrs);
- this.charstrings = charstrings;
- this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties);
- this.seacs = this.getSeacs(data.charstrings);
- }
- Type1Font.prototype = {
- get numGlyphs() {
- return this.charstrings.length + 1;
- },
- getCharset: function Type1Font_getCharset() {
- var charset = ['.notdef'];
- var charstrings = this.charstrings;
- for (var glyphId = 0; glyphId < charstrings.length; glyphId++) {
- charset.push(charstrings[glyphId].glyphName);
- }
- return charset;
- },
- getGlyphMapping: function Type1Font_getGlyphMapping(properties) {
- var charstrings = this.charstrings;
- var glyphNames = ['.notdef'], glyphId;
- for (glyphId = 0; glyphId < charstrings.length; glyphId++) {
- glyphNames.push(charstrings[glyphId].glyphName);
- }
- var encoding = properties.builtInEncoding;
- if (encoding) {
- var builtInEncoding = Object.create(null);
- for (var charCode in encoding) {
- glyphId = glyphNames.indexOf(encoding[charCode]);
- if (glyphId >= 0) {
- builtInEncoding[charCode] = glyphId;
- }
- }
- }
- return type1FontGlyphMapping(properties, builtInEncoding, glyphNames);
- },
- getSeacs: function Type1Font_getSeacs(charstrings) {
- var i, ii;
- var seacMap = [];
- for (i = 0, ii = charstrings.length; i < ii; i++) {
- var charstring = charstrings[i];
- if (charstring.seac) {
- // Offset by 1 for .notdef
- seacMap[i + 1] = charstring.seac;
- }
- }
- return seacMap;
- },
- getType2Charstrings: function Type1Font_getType2Charstrings(type1Charstrings) {
- var type2Charstrings = [];
- for (var i = 0, ii = type1Charstrings.length; i < ii; i++) {
- type2Charstrings.push(type1Charstrings[i].charstring);
- }
- return type2Charstrings;
- },
- getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) {
- var bias = 0;
- var count = type1Subrs.length;
- if (count < 1133) {
- bias = 107;
- } else if (count < 33769) {
- bias = 1131;
- } else {
- bias = 32768;
- }
- // Add a bunch of empty subrs to deal with the Type2 bias
- var type2Subrs = [];
- var i;
- for (i = 0; i < bias; i++) {
- type2Subrs.push([0x0B]);
- }
- for (i = 0; i < count; i++) {
- type2Subrs.push(type1Subrs[i]);
- }
- return type2Subrs;
- },
- wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) {
- var cff = new CFF();
- cff.header = new CFFHeader(1, 0, 4, 4);
- cff.names = [name];
- var topDict = new CFFTopDict();
- // CFF strings IDs 0...390 are predefined names, so refering
- // to entries in our own String INDEX starts at SID 391.
- topDict.setByName('version', 391);
- topDict.setByName('Notice', 392);
- topDict.setByName('FullName', 393);
- topDict.setByName('FamilyName', 394);
- topDict.setByName('Weight', 395);
- topDict.setByName('Encoding', null);
- // placeholder
- topDict.setByName('FontMatrix', properties.fontMatrix);
- topDict.setByName('FontBBox', properties.bbox);
- topDict.setByName('charset', null);
- // placeholder
- topDict.setByName('CharStrings', null);
- // placeholder
- topDict.setByName('Private', null);
- // placeholder
- cff.topDict = topDict;
- var strings = new CFFStrings();
- strings.add('Version 0.11');
- // Version
- strings.add('See original notice');
- // Notice
- strings.add(name);
- // FullName
- strings.add(name);
- // FamilyName
- strings.add('Medium');
- // Weight
- cff.strings = strings;
- cff.globalSubrIndex = new CFFIndex();
- var count = glyphs.length;
- var charsetArray = [0];
- var i, ii;
- for (i = 0; i < count; i++) {
- var index = CFFStandardStrings.indexOf(charstrings[i].glyphName);
- // TODO: Insert the string and correctly map it. Previously it was
- // thought mapping names that aren't in the standard strings to .notdef
- // was fine, however in issue818 when mapping them all to .notdef the
- // adieresis glyph no longer worked.
- if (index === -1) {
- index = 0;
- }
- charsetArray.push(index >> 8 & 0xff, index & 0xff);
- }
- cff.charset = new CFFCharset(false, 0, [], charsetArray);
- var charStringsIndex = new CFFIndex();
- charStringsIndex.add([
- 0x8B,
- 0x0E
- ]);
- // .notdef
- for (i = 0; i < count; i++) {
- var glyph = glyphs[i];
- // If the CharString outline is empty, replace it with .notdef to
- // prevent OTS from rejecting the font (fixes bug1252420.pdf).
- if (glyph.length === 0) {
- charStringsIndex.add([
- 0x8B,
- 0x0E
- ]);
- // .notdef
- continue;
- }
- charStringsIndex.add(glyph);
- }
- cff.charStrings = charStringsIndex;
- var privateDict = new CFFPrivateDict();
- privateDict.setByName('Subrs', null);
- // placeholder
- var fields = [
- 'BlueValues',
- 'OtherBlues',
- 'FamilyBlues',
- 'FamilyOtherBlues',
- 'StemSnapH',
- 'StemSnapV',
- 'BlueShift',
- 'BlueFuzz',
- 'BlueScale',
- 'LanguageGroup',
- 'ExpansionFactor',
- 'ForceBold',
- 'StdHW',
- 'StdVW'
- ];
- for (i = 0, ii = fields.length; i < ii; i++) {
- var field = fields[i];
- if (!(field in properties.privateData)) {
- continue;
- }
- var value = properties.privateData[field];
- if (isArray(value)) {
- // All of the private dictionary array data in CFF must be stored as
- // "delta-encoded" numbers.
- for (var j = value.length - 1; j > 0; j--) {
- value[j] -= value[j - 1];
- }
- }
- // ... difference from previous value
- privateDict.setByName(field, value);
- }
- cff.topDict.privateDict = privateDict;
- var subrIndex = new CFFIndex();
- for (i = 0, ii = subrs.length; i < ii; i++) {
- subrIndex.add(subrs[i]);
- }
- privateDict.subrsIndex = subrIndex;
- var compiler = new CFFCompiler(cff);
- return compiler.compile();
- }
- };
- return Type1Font;
- }();
- var CFFFont = function CFFFontClosure() {
- function CFFFont(file, properties) {
- this.properties = properties;
- var parser = new CFFParser(file, properties, SEAC_ANALYSIS_ENABLED);
- this.cff = parser.parse();
- var compiler = new CFFCompiler(this.cff);
- this.seacs = this.cff.seacs;
- try {
- this.data = compiler.compile();
- } catch (e) {
- warn('Failed to compile font ' + properties.loadedName);
- // There may have just been an issue with the compiler, set the data
- // anyway and hope the font loaded.
- this.data = file;
- }
- }
- CFFFont.prototype = {
- get numGlyphs() {
- return this.cff.charStrings.count;
- },
- getCharset: function CFFFont_getCharset() {
- return this.cff.charset.charset;
- },
- getGlyphMapping: function CFFFont_getGlyphMapping() {
- var cff = this.cff;
- var properties = this.properties;
- var charsets = cff.charset.charset;
- var charCodeToGlyphId;
- var glyphId;
- if (properties.composite) {
- charCodeToGlyphId = Object.create(null);
- if (cff.isCIDFont) {
- // If the font is actually a CID font then we should use the charset
- // to map CIDs to GIDs.
- for (glyphId = 0; glyphId < charsets.length; glyphId++) {
- var cid = charsets[glyphId];
- var charCode = properties.cMap.charCodeOf(cid);
- charCodeToGlyphId[charCode] = glyphId;
- }
- } else {
- // If it is NOT actually a CID font then CIDs should be mapped
- // directly to GIDs.
- for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) {
- charCodeToGlyphId[glyphId] = glyphId;
- }
- }
- return charCodeToGlyphId;
- }
- var encoding = cff.encoding ? cff.encoding.encoding : null;
- charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets);
- return charCodeToGlyphId;
- }
- };
- return CFFFont;
- }();
- // Workaround for seac on Windows.
- (function checkSeacSupport() {
- if (typeof navigator !== 'undefined' && /Windows/.test(navigator.userAgent)) {
- SEAC_ANALYSIS_ENABLED = true;
- }
- }());
- // Workaround for Private Use Area characters in Chrome on Windows
- // http://code.google.com/p/chromium/issues/detail?id=122465
- // https://github.com/mozilla/pdf.js/issues/1689
- (function checkChromeWindows() {
- if (typeof navigator !== 'undefined' && /Windows.*Chrome/.test(navigator.userAgent)) {
- SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = true;
- }
- }());
- exports.ErrorFont = ErrorFont;
- exports.Font = Font;
- exports.FontFlags = FontFlags;
- exports.IdentityToUnicodeMap = IdentityToUnicodeMap;
- exports.ToUnicodeMap = ToUnicodeMap;
- exports.getFontType = getFontType;
- }));
- (function (root, factory) {
- factory(root.pdfjsCorePsParser = {}, root.pdfjsSharedUtil, root.pdfjsCoreParser);
- }(this, function (exports, sharedUtil, coreParser) {
- var error = sharedUtil.error;
- var isSpace = sharedUtil.isSpace;
- var EOF = coreParser.EOF;
- var PostScriptParser = function PostScriptParserClosure() {
- function PostScriptParser(lexer) {
- this.lexer = lexer;
- this.operators = [];
- this.token = null;
- this.prev = null;
- }
- PostScriptParser.prototype = {
- nextToken: function PostScriptParser_nextToken() {
- this.prev = this.token;
- this.token = this.lexer.getToken();
- },
- accept: function PostScriptParser_accept(type) {
- if (this.token.type === type) {
- this.nextToken();
- return true;
- }
- return false;
- },
- expect: function PostScriptParser_expect(type) {
- if (this.accept(type)) {
- return true;
- }
- error('Unexpected symbol: found ' + this.token.type + ' expected ' + type + '.');
- },
- parse: function PostScriptParser_parse() {
- this.nextToken();
- this.expect(PostScriptTokenTypes.LBRACE);
- this.parseBlock();
- this.expect(PostScriptTokenTypes.RBRACE);
- return this.operators;
- },
- parseBlock: function PostScriptParser_parseBlock() {
- while (true) {
- if (this.accept(PostScriptTokenTypes.NUMBER)) {
- this.operators.push(this.prev.value);
- } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
- this.operators.push(this.prev.value);
- } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
- this.parseCondition();
- } else {
- return;
- }
- }
- },
- parseCondition: function PostScriptParser_parseCondition() {
- // Add two place holders that will be updated later
- var conditionLocation = this.operators.length;
- this.operators.push(null, null);
- this.parseBlock();
- this.expect(PostScriptTokenTypes.RBRACE);
- if (this.accept(PostScriptTokenTypes.IF)) {
- // The true block is right after the 'if' so it just falls through on
- // true else it jumps and skips the true block.
- this.operators[conditionLocation] = this.operators.length;
- this.operators[conditionLocation + 1] = 'jz';
- } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
- var jumpLocation = this.operators.length;
- this.operators.push(null, null);
- var endOfTrue = this.operators.length;
- this.parseBlock();
- this.expect(PostScriptTokenTypes.RBRACE);
- this.expect(PostScriptTokenTypes.IFELSE);
- // The jump is added at the end of the true block to skip the false
- // block.
- this.operators[jumpLocation] = this.operators.length;
- this.operators[jumpLocation + 1] = 'j';
- this.operators[conditionLocation] = endOfTrue;
- this.operators[conditionLocation + 1] = 'jz';
- } else {
- error('PS Function: error parsing conditional.');
- }
- }
- };
- return PostScriptParser;
- }();
- var PostScriptTokenTypes = {
- LBRACE: 0,
- RBRACE: 1,
- NUMBER: 2,
- OPERATOR: 3,
- IF: 4,
- IFELSE: 5
- };
- var PostScriptToken = function PostScriptTokenClosure() {
- function PostScriptToken(type, value) {
- this.type = type;
- this.value = value;
- }
- var opCache = Object.create(null);
- PostScriptToken.getOperator = function PostScriptToken_getOperator(op) {
- var opValue = opCache[op];
- if (opValue) {
- return opValue;
- }
- return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
- };
- PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE, '{');
- PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE, '}');
- PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF');
- PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE, 'IFELSE');
- return PostScriptToken;
- }();
- var PostScriptLexer = function PostScriptLexerClosure() {
- function PostScriptLexer(stream) {
- this.stream = stream;
- this.nextChar();
- this.strBuf = [];
- }
- PostScriptLexer.prototype = {
- nextChar: function PostScriptLexer_nextChar() {
- return this.currentChar = this.stream.getByte();
- },
- getToken: function PostScriptLexer_getToken() {
- var comment = false;
- var ch = this.currentChar;
- // skip comments
- while (true) {
- if (ch < 0) {
- return EOF;
- }
- if (comment) {
- if (ch === 0x0A || ch === 0x0D) {
- comment = false;
- }
- } else if (ch === 0x25) {
- // '%'
- comment = true;
- } else if (!isSpace(ch)) {
- break;
- }
- ch = this.nextChar();
- }
- switch (ch | 0) {
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- case 0x34:
- // '0'-'4'
- case 0x35:
- case 0x36:
- case 0x37:
- case 0x38:
- case 0x39:
- // '5'-'9'
- case 0x2B:
- case 0x2D:
- case 0x2E:
- // '+', '-', '.'
- return new PostScriptToken(PostScriptTokenTypes.NUMBER, this.getNumber());
- case 0x7B:
- // '{'
- this.nextChar();
- return PostScriptToken.LBRACE;
- case 0x7D:
- // '}'
- this.nextChar();
- return PostScriptToken.RBRACE;
- }
- // operator
- var strBuf = this.strBuf;
- strBuf.length = 0;
- strBuf[0] = String.fromCharCode(ch);
- while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
- (ch >= 0x41 && ch <= 0x5A || ch >= 0x61 && ch <= 0x7A)) {
- strBuf.push(String.fromCharCode(ch));
- }
- var str = strBuf.join('');
- switch (str.toLowerCase()) {
- case 'if':
- return PostScriptToken.IF;
- case 'ifelse':
- return PostScriptToken.IFELSE;
- default:
- return PostScriptToken.getOperator(str);
- }
- },
- getNumber: function PostScriptLexer_getNumber() {
- var ch = this.currentChar;
- var strBuf = this.strBuf;
- strBuf.length = 0;
- strBuf[0] = String.fromCharCode(ch);
- while ((ch = this.nextChar()) >= 0) {
- if (ch >= 0x30 && ch <= 0x39 || // '0'-'9'
- ch === 0x2D || ch === 0x2E) {
- // '-', '.'
- strBuf.push(String.fromCharCode(ch));
- } else {
- break;
- }
- }
- var value = parseFloat(strBuf.join(''));
- if (isNaN(value)) {
- error('Invalid floating point number: ' + value);
- }
- return value;
- }
- };
- return PostScriptLexer;
- }();
- exports.PostScriptLexer = PostScriptLexer;
- exports.PostScriptParser = PostScriptParser;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreFunction = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCorePsParser);
- }(this, function (exports, sharedUtil, corePrimitives, corePsParser) {
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var isArray = sharedUtil.isArray;
- var isBool = sharedUtil.isBool;
- var isDict = corePrimitives.isDict;
- var isStream = corePrimitives.isStream;
- var PostScriptLexer = corePsParser.PostScriptLexer;
- var PostScriptParser = corePsParser.PostScriptParser;
- function toNumberArray(arr) {
- if (!Array.isArray(arr)) {
- return null;
- }
- var length = arr.length;
- for (var i = 0; i < length; i++) {
- if (typeof arr[i] !== 'number') {
- var result = new Array(length);
- for (var j = 0; j < length; j++) {
- result[j] = +arr[j];
- }
- return result;
- }
- }
- return arr;
- }
- var PDFFunction = function PDFFunctionClosure() {
- var CONSTRUCT_SAMPLED = 0;
- var CONSTRUCT_INTERPOLATED = 2;
- var CONSTRUCT_STICHED = 3;
- var CONSTRUCT_POSTSCRIPT = 4;
- return {
- getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps, str) {
- var i, ii;
- var length = 1;
- for (i = 0, ii = size.length; i < ii; i++) {
- length *= size[i];
- }
- length *= outputSize;
- var array = new Array(length);
- var codeSize = 0;
- var codeBuf = 0;
- // 32 is a valid bps so shifting won't work
- var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1);
- var strBytes = str.getBytes((length * bps + 7) / 8);
- var strIdx = 0;
- for (i = 0; i < length; i++) {
- while (codeSize < bps) {
- codeBuf <<= 8;
- codeBuf |= strBytes[strIdx++];
- codeSize += 8;
- }
- codeSize -= bps;
- array[i] = (codeBuf >> codeSize) * sampleMul;
- codeBuf &= (1 << codeSize) - 1;
- }
- return array;
- },
- getIR: function PDFFunction_getIR(xref, fn) {
- var dict = fn.dict;
- if (!dict) {
- dict = fn;
- }
- var types = [
- this.constructSampled,
- null,
- this.constructInterpolated,
- this.constructStiched,
- this.constructPostScript
- ];
- var typeNum = dict.get('FunctionType');
- var typeFn = types[typeNum];
- if (!typeFn) {
- error('Unknown type of function');
- }
- return typeFn.call(this, fn, dict, xref);
- },
- fromIR: function PDFFunction_fromIR(IR) {
- var type = IR[0];
- switch (type) {
- case CONSTRUCT_SAMPLED:
- return this.constructSampledFromIR(IR);
- case CONSTRUCT_INTERPOLATED:
- return this.constructInterpolatedFromIR(IR);
- case CONSTRUCT_STICHED:
- return this.constructStichedFromIR(IR);
- //case CONSTRUCT_POSTSCRIPT:
- default:
- return this.constructPostScriptFromIR(IR);
- }
- },
- parse: function PDFFunction_parse(xref, fn) {
- var IR = this.getIR(xref, fn);
- return this.fromIR(IR);
- },
- parseArray: function PDFFunction_parseArray(xref, fnObj) {
- if (!isArray(fnObj)) {
- // not an array -- parsing as regular function
- return this.parse(xref, fnObj);
- }
- var fnArray = [];
- for (var j = 0, jj = fnObj.length; j < jj; j++) {
- var obj = xref.fetchIfRef(fnObj[j]);
- fnArray.push(PDFFunction.parse(xref, obj));
- }
- return function (src, srcOffset, dest, destOffset) {
- for (var i = 0, ii = fnArray.length; i < ii; i++) {
- fnArray[i](src, srcOffset, dest, destOffset + i);
- }
- };
- },
- constructSampled: function PDFFunction_constructSampled(str, dict) {
- function toMultiArray(arr) {
- var inputLength = arr.length;
- var out = [];
- var index = 0;
- for (var i = 0; i < inputLength; i += 2) {
- out[index] = [
- arr[i],
- arr[i + 1]
- ];
- ++index;
- }
- return out;
- }
- var domain = toNumberArray(dict.getArray('Domain'));
- var range = toNumberArray(dict.getArray('Range'));
- if (!domain || !range) {
- error('No domain or range');
- }
- var inputSize = domain.length / 2;
- var outputSize = range.length / 2;
- domain = toMultiArray(domain);
- range = toMultiArray(range);
- var size = toNumberArray(dict.get('Size'));
- var bps = dict.get('BitsPerSample');
- var order = dict.get('Order') || 1;
- if (order !== 1) {
- // No description how cubic spline interpolation works in PDF32000:2008
- // As in poppler, ignoring order, linear interpolation may work as good
- info('No support for cubic spline interpolation: ' + order);
- }
- var encode = toNumberArray(dict.getArray('Encode'));
- if (!encode) {
- encode = [];
- for (var i = 0; i < inputSize; ++i) {
- encode.push([0, size[i] - 1]);
- }
- } else {
- encode = toMultiArray(encode);
- }
- var decode = toNumberArray(dict.getArray('Decode'));
- if (!decode) {
- decode = range;
- } else {
- decode = toMultiArray(decode);
- }
- var samples = this.getSampleArray(size, outputSize, bps, str);
- return [
- CONSTRUCT_SAMPLED,
- inputSize,
- domain,
- encode,
- decode,
- samples,
- size,
- outputSize,
- Math.pow(2, bps) - 1,
- range
- ];
- },
- constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) {
- // See chapter 3, page 109 of the PDF reference
- function interpolate(x, xmin, xmax, ymin, ymax) {
- return ymin + (x - xmin) * ((ymax - ymin) / (xmax - xmin));
- }
- return function constructSampledFromIRResult(src, srcOffset, dest, destOffset) {
- // See chapter 3, page 110 of the PDF reference.
- var m = IR[1];
- var domain = IR[2];
- var encode = IR[3];
- var decode = IR[4];
- var samples = IR[5];
- var size = IR[6];
- var n = IR[7];
- //var mask = IR[8];
- var range = IR[9];
- // Building the cube vertices: its part and sample index
- // http://rjwagner49.com/Mathematics/Interpolation.pdf
- var cubeVertices = 1 << m;
- var cubeN = new Float64Array(cubeVertices);
- var cubeVertex = new Uint32Array(cubeVertices);
- var i, j;
- for (j = 0; j < cubeVertices; j++) {
- cubeN[j] = 1;
- }
- var k = n, pos = 1;
- // Map x_i to y_j for 0 <= i < m using the sampled function.
- for (i = 0; i < m; ++i) {
- // x_i' = min(max(x_i, Domain_2i), Domain_2i+1)
- var domain_2i = domain[i][0];
- var domain_2i_1 = domain[i][1];
- var xi = Math.min(Math.max(src[srcOffset + i], domain_2i), domain_2i_1);
- // e_i = Interpolate(x_i', Domain_2i, Domain_2i+1,
- // Encode_2i, Encode_2i+1)
- var e = interpolate(xi, domain_2i, domain_2i_1, encode[i][0], encode[i][1]);
- // e_i' = min(max(e_i, 0), Size_i - 1)
- var size_i = size[i];
- e = Math.min(Math.max(e, 0), size_i - 1);
- // Adjusting the cube: N and vertex sample index
- var e0 = e < size_i - 1 ? Math.floor(e) : e - 1;
- // e1 = e0 + 1;
- var n0 = e0 + 1 - e;
- // (e1 - e) / (e1 - e0);
- var n1 = e - e0;
- // (e - e0) / (e1 - e0);
- var offset0 = e0 * k;
- var offset1 = offset0 + k;
- // e1 * k
- for (j = 0; j < cubeVertices; j++) {
- if (j & pos) {
- cubeN[j] *= n1;
- cubeVertex[j] += offset1;
- } else {
- cubeN[j] *= n0;
- cubeVertex[j] += offset0;
- }
- }
- k *= size_i;
- pos <<= 1;
- }
- for (j = 0; j < n; ++j) {
- // Sum all cube vertices' samples portions
- var rj = 0;
- for (i = 0; i < cubeVertices; i++) {
- rj += samples[cubeVertex[i] + j] * cubeN[i];
- }
- // r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1,
- // Decode_2j, Decode_2j+1)
- rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
- // y_j = min(max(r_j, range_2j), range_2j+1)
- dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
- }
- };
- },
- constructInterpolated: function PDFFunction_constructInterpolated(str, dict) {
- var c0 = toNumberArray(dict.getArray('C0')) || [0];
- var c1 = toNumberArray(dict.getArray('C1')) || [1];
- var n = dict.get('N');
- var length = c0.length;
- var diff = [];
- for (var i = 0; i < length; ++i) {
- diff.push(c1[i] - c0[i]);
- }
- return [
- CONSTRUCT_INTERPOLATED,
- c0,
- diff,
- n
- ];
- },
- constructInterpolatedFromIR: function PDFFunction_constructInterpolatedFromIR(IR) {
- var c0 = IR[1];
- var diff = IR[2];
- var n = IR[3];
- var length = diff.length;
- return function constructInterpolatedFromIRResult(src, srcOffset, dest, destOffset) {
- var x = n === 1 ? src[srcOffset] : Math.pow(src[srcOffset], n);
- for (var j = 0; j < length; ++j) {
- dest[destOffset + j] = c0[j] + x * diff[j];
- }
- };
- },
- constructStiched: function PDFFunction_constructStiched(fn, dict, xref) {
- var domain = toNumberArray(dict.getArray('Domain'));
- if (!domain) {
- error('No domain');
- }
- var inputSize = domain.length / 2;
- if (inputSize !== 1) {
- error('Bad domain for stiched function');
- }
- var fnRefs = dict.get('Functions');
- var fns = [];
- for (var i = 0, ii = fnRefs.length; i < ii; ++i) {
- fns.push(PDFFunction.parse(xref, xref.fetchIfRef(fnRefs[i])));
- }
- var bounds = toNumberArray(dict.getArray('Bounds'));
- var encode = toNumberArray(dict.getArray('Encode'));
- return [
- CONSTRUCT_STICHED,
- domain,
- bounds,
- encode,
- fns
- ];
- },
- constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) {
- var domain = IR[1];
- var bounds = IR[2];
- var encode = IR[3];
- var fns = IR[4];
- var tmpBuf = new Float32Array(1);
- return function constructStichedFromIRResult(src, srcOffset, dest, destOffset) {
- var clip = function constructStichedFromIRClip(v, min, max) {
- if (v > max) {
- v = max;
- } else if (v < min) {
- v = min;
- }
- return v;
- };
- // clip to domain
- var v = clip(src[srcOffset], domain[0], domain[1]);
- // calculate which bound the value is in
- for (var i = 0, ii = bounds.length; i < ii; ++i) {
- if (v < bounds[i]) {
- break;
- }
- }
- // encode value into domain of function
- var dmin = domain[0];
- if (i > 0) {
- dmin = bounds[i - 1];
- }
- var dmax = domain[1];
- if (i < bounds.length) {
- dmax = bounds[i];
- }
- var rmin = encode[2 * i];
- var rmax = encode[2 * i + 1];
- // Prevent the value from becoming NaN as a result
- // of division by zero (fixes issue6113.pdf).
- tmpBuf[0] = dmin === dmax ? rmin : rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
- // call the appropriate function
- fns[i](tmpBuf, 0, dest, destOffset);
- };
- },
- constructPostScript: function PDFFunction_constructPostScript(fn, dict, xref) {
- var domain = toNumberArray(dict.getArray('Domain'));
- var range = toNumberArray(dict.getArray('Range'));
- if (!domain) {
- error('No domain.');
- }
- if (!range) {
- error('No range.');
- }
- var lexer = new PostScriptLexer(fn);
- var parser = new PostScriptParser(lexer);
- var code = parser.parse();
- return [
- CONSTRUCT_POSTSCRIPT,
- domain,
- range,
- code
- ];
- },
- constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR(IR) {
- var domain = IR[1];
- var range = IR[2];
- var code = IR[3];
- var compiled = new PostScriptCompiler().compile(code, domain, range);
- if (compiled) {
- // Compiled function consists of simple expressions such as addition,
- // subtraction, Math.max, and also contains 'var' and 'return'
- // statements. See the generation in the PostScriptCompiler below.
- return new Function('src', 'srcOffset', 'dest', 'destOffset', compiled);
- }
- info('Unable to compile PS function');
- var numOutputs = range.length >> 1;
- var numInputs = domain.length >> 1;
- var evaluator = new PostScriptEvaluator(code);
- // Cache the values for a big speed up, the cache size is limited though
- // since the number of possible values can be huge from a PS function.
- var cache = Object.create(null);
- // The MAX_CACHE_SIZE is set to ~4x the maximum number of distinct values
- // seen in our tests.
- var MAX_CACHE_SIZE = 2048 * 4;
- var cache_available = MAX_CACHE_SIZE;
- var tmpBuf = new Float32Array(numInputs);
- return function constructPostScriptFromIRResult(src, srcOffset, dest, destOffset) {
- var i, value;
- var key = '';
- var input = tmpBuf;
- for (i = 0; i < numInputs; i++) {
- value = src[srcOffset + i];
- input[i] = value;
- key += value + '_';
- }
- var cachedValue = cache[key];
- if (cachedValue !== undefined) {
- dest.set(cachedValue, destOffset);
- return;
- }
- var output = new Float32Array(numOutputs);
- var stack = evaluator.execute(input);
- var stackIndex = stack.length - numOutputs;
- for (i = 0; i < numOutputs; i++) {
- value = stack[stackIndex + i];
- var bound = range[i * 2];
- if (value < bound) {
- value = bound;
- } else {
- bound = range[i * 2 + 1];
- if (value > bound) {
- value = bound;
- }
- }
- output[i] = value;
- }
- if (cache_available > 0) {
- cache_available--;
- cache[key] = output;
- }
- dest.set(output, destOffset);
- };
- }
- };
- }();
- function isPDFFunction(v) {
- var fnDict;
- if (typeof v !== 'object') {
- return false;
- } else if (isDict(v)) {
- fnDict = v;
- } else if (isStream(v)) {
- fnDict = v.dict;
- } else {
- return false;
- }
- return fnDict.has('FunctionType');
- }
- var PostScriptStack = function PostScriptStackClosure() {
- var MAX_STACK_SIZE = 100;
- function PostScriptStack(initialStack) {
- this.stack = !initialStack ? [] : Array.prototype.slice.call(initialStack, 0);
- }
- PostScriptStack.prototype = {
- push: function PostScriptStack_push(value) {
- if (this.stack.length >= MAX_STACK_SIZE) {
- error('PostScript function stack overflow.');
- }
- this.stack.push(value);
- },
- pop: function PostScriptStack_pop() {
- if (this.stack.length <= 0) {
- error('PostScript function stack underflow.');
- }
- return this.stack.pop();
- },
- copy: function PostScriptStack_copy(n) {
- if (this.stack.length + n >= MAX_STACK_SIZE) {
- error('PostScript function stack overflow.');
- }
- var stack = this.stack;
- for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) {
- stack.push(stack[i]);
- }
- },
- index: function PostScriptStack_index(n) {
- this.push(this.stack[this.stack.length - n - 1]);
- },
- // rotate the last n stack elements p times
- roll: function PostScriptStack_roll(n, p) {
- var stack = this.stack;
- var l = stack.length - n;
- var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t;
- for (i = l, j = r; i < j; i++, j--) {
- t = stack[i];
- stack[i] = stack[j];
- stack[j] = t;
- }
- for (i = l, j = c - 1; i < j; i++, j--) {
- t = stack[i];
- stack[i] = stack[j];
- stack[j] = t;
- }
- for (i = c, j = r; i < j; i++, j--) {
- t = stack[i];
- stack[i] = stack[j];
- stack[j] = t;
- }
- }
- };
- return PostScriptStack;
- }();
- var PostScriptEvaluator = function PostScriptEvaluatorClosure() {
- function PostScriptEvaluator(operators) {
- this.operators = operators;
- }
- PostScriptEvaluator.prototype = {
- execute: function PostScriptEvaluator_execute(initialStack) {
- var stack = new PostScriptStack(initialStack);
- var counter = 0;
- var operators = this.operators;
- var length = operators.length;
- var operator, a, b;
- while (counter < length) {
- operator = operators[counter++];
- if (typeof operator === 'number') {
- // Operator is really an operand and should be pushed to the stack.
- stack.push(operator);
- continue;
- }
- switch (operator) {
- // non standard ps operators
- case 'jz':
- // jump if false
- b = stack.pop();
- a = stack.pop();
- if (!a) {
- counter = b;
- }
- break;
- case 'j':
- // jump
- a = stack.pop();
- counter = a;
- break;
- // all ps operators in alphabetical order (excluding if/ifelse)
- case 'abs':
- a = stack.pop();
- stack.push(Math.abs(a));
- break;
- case 'add':
- b = stack.pop();
- a = stack.pop();
- stack.push(a + b);
- break;
- case 'and':
- b = stack.pop();
- a = stack.pop();
- if (isBool(a) && isBool(b)) {
- stack.push(a && b);
- } else {
- stack.push(a & b);
- }
- break;
- case 'atan':
- a = stack.pop();
- stack.push(Math.atan(a));
- break;
- case 'bitshift':
- b = stack.pop();
- a = stack.pop();
- if (a > 0) {
- stack.push(a << b);
- } else {
- stack.push(a >> b);
- }
- break;
- case 'ceiling':
- a = stack.pop();
- stack.push(Math.ceil(a));
- break;
- case 'copy':
- a = stack.pop();
- stack.copy(a);
- break;
- case 'cos':
- a = stack.pop();
- stack.push(Math.cos(a));
- break;
- case 'cvi':
- a = stack.pop() | 0;
- stack.push(a);
- break;
- case 'cvr':
- // noop
- break;
- case 'div':
- b = stack.pop();
- a = stack.pop();
- stack.push(a / b);
- break;
- case 'dup':
- stack.copy(1);
- break;
- case 'eq':
- b = stack.pop();
- a = stack.pop();
- stack.push(a === b);
- break;
- case 'exch':
- stack.roll(2, 1);
- break;
- case 'exp':
- b = stack.pop();
- a = stack.pop();
- stack.push(Math.pow(a, b));
- break;
- case 'false':
- stack.push(false);
- break;
- case 'floor':
- a = stack.pop();
- stack.push(Math.floor(a));
- break;
- case 'ge':
- b = stack.pop();
- a = stack.pop();
- stack.push(a >= b);
- break;
- case 'gt':
- b = stack.pop();
- a = stack.pop();
- stack.push(a > b);
- break;
- case 'idiv':
- b = stack.pop();
- a = stack.pop();
- stack.push(a / b | 0);
- break;
- case 'index':
- a = stack.pop();
- stack.index(a);
- break;
- case 'le':
- b = stack.pop();
- a = stack.pop();
- stack.push(a <= b);
- break;
- case 'ln':
- a = stack.pop();
- stack.push(Math.log(a));
- break;
- case 'log':
- a = stack.pop();
- stack.push(Math.log(a) / Math.LN10);
- break;
- case 'lt':
- b = stack.pop();
- a = stack.pop();
- stack.push(a < b);
- break;
- case 'mod':
- b = stack.pop();
- a = stack.pop();
- stack.push(a % b);
- break;
- case 'mul':
- b = stack.pop();
- a = stack.pop();
- stack.push(a * b);
- break;
- case 'ne':
- b = stack.pop();
- a = stack.pop();
- stack.push(a !== b);
- break;
- case 'neg':
- a = stack.pop();
- stack.push(-a);
- break;
- case 'not':
- a = stack.pop();
- if (isBool(a)) {
- stack.push(!a);
- } else {
- stack.push(~a);
- }
- break;
- case 'or':
- b = stack.pop();
- a = stack.pop();
- if (isBool(a) && isBool(b)) {
- stack.push(a || b);
- } else {
- stack.push(a | b);
- }
- break;
- case 'pop':
- stack.pop();
- break;
- case 'roll':
- b = stack.pop();
- a = stack.pop();
- stack.roll(a, b);
- break;
- case 'round':
- a = stack.pop();
- stack.push(Math.round(a));
- break;
- case 'sin':
- a = stack.pop();
- stack.push(Math.sin(a));
- break;
- case 'sqrt':
- a = stack.pop();
- stack.push(Math.sqrt(a));
- break;
- case 'sub':
- b = stack.pop();
- a = stack.pop();
- stack.push(a - b);
- break;
- case 'true':
- stack.push(true);
- break;
- case 'truncate':
- a = stack.pop();
- a = a < 0 ? Math.ceil(a) : Math.floor(a);
- stack.push(a);
- break;
- case 'xor':
- b = stack.pop();
- a = stack.pop();
- if (isBool(a) && isBool(b)) {
- stack.push(a !== b);
- } else {
- stack.push(a ^ b);
- }
- break;
- default:
- error('Unknown operator ' + operator);
- break;
- }
- }
- return stack.stack;
- }
- };
- return PostScriptEvaluator;
- }();
- // Most of the PDFs functions consist of simple operations such as:
- // roll, exch, sub, cvr, pop, index, dup, mul, if, gt, add.
- //
- // We can compile most of such programs, and at the same moment, we can
- // optimize some expressions using basic math properties. Keeping track of
- // min/max values will allow us to avoid extra Math.min/Math.max calls.
- var PostScriptCompiler = function PostScriptCompilerClosure() {
- function AstNode(type) {
- this.type = type;
- }
- AstNode.prototype.visit = function (visitor) {
- throw new Error('abstract method');
- };
- function AstArgument(index, min, max) {
- AstNode.call(this, 'args');
- this.index = index;
- this.min = min;
- this.max = max;
- }
- AstArgument.prototype = Object.create(AstNode.prototype);
- AstArgument.prototype.visit = function (visitor) {
- visitor.visitArgument(this);
- };
- function AstLiteral(number) {
- AstNode.call(this, 'literal');
- this.number = number;
- this.min = number;
- this.max = number;
- }
- AstLiteral.prototype = Object.create(AstNode.prototype);
- AstLiteral.prototype.visit = function (visitor) {
- visitor.visitLiteral(this);
- };
- function AstBinaryOperation(op, arg1, arg2, min, max) {
- AstNode.call(this, 'binary');
- this.op = op;
- this.arg1 = arg1;
- this.arg2 = arg2;
- this.min = min;
- this.max = max;
- }
- AstBinaryOperation.prototype = Object.create(AstNode.prototype);
- AstBinaryOperation.prototype.visit = function (visitor) {
- visitor.visitBinaryOperation(this);
- };
- function AstMin(arg, max) {
- AstNode.call(this, 'max');
- this.arg = arg;
- this.min = arg.min;
- this.max = max;
- }
- AstMin.prototype = Object.create(AstNode.prototype);
- AstMin.prototype.visit = function (visitor) {
- visitor.visitMin(this);
- };
- function AstVariable(index, min, max) {
- AstNode.call(this, 'var');
- this.index = index;
- this.min = min;
- this.max = max;
- }
- AstVariable.prototype = Object.create(AstNode.prototype);
- AstVariable.prototype.visit = function (visitor) {
- visitor.visitVariable(this);
- };
- function AstVariableDefinition(variable, arg) {
- AstNode.call(this, 'definition');
- this.variable = variable;
- this.arg = arg;
- }
- AstVariableDefinition.prototype = Object.create(AstNode.prototype);
- AstVariableDefinition.prototype.visit = function (visitor) {
- visitor.visitVariableDefinition(this);
- };
- function ExpressionBuilderVisitor() {
- this.parts = [];
- }
- ExpressionBuilderVisitor.prototype = {
- visitArgument: function (arg) {
- this.parts.push('Math.max(', arg.min, ', Math.min(', arg.max, ', src[srcOffset + ', arg.index, ']))');
- },
- visitVariable: function (variable) {
- this.parts.push('v', variable.index);
- },
- visitLiteral: function (literal) {
- this.parts.push(literal.number);
- },
- visitBinaryOperation: function (operation) {
- this.parts.push('(');
- operation.arg1.visit(this);
- this.parts.push(' ', operation.op, ' ');
- operation.arg2.visit(this);
- this.parts.push(')');
- },
- visitVariableDefinition: function (definition) {
- this.parts.push('var ');
- definition.variable.visit(this);
- this.parts.push(' = ');
- definition.arg.visit(this);
- this.parts.push(';');
- },
- visitMin: function (max) {
- this.parts.push('Math.min(');
- max.arg.visit(this);
- this.parts.push(', ', max.max, ')');
- },
- toString: function () {
- return this.parts.join('');
- }
- };
- function buildAddOperation(num1, num2) {
- if (num2.type === 'literal' && num2.number === 0) {
- // optimization: second operand is 0
- return num1;
- }
- if (num1.type === 'literal' && num1.number === 0) {
- // optimization: first operand is 0
- return num2;
- }
- if (num2.type === 'literal' && num1.type === 'literal') {
- // optimization: operands operand are literals
- return new AstLiteral(num1.number + num2.number);
- }
- return new AstBinaryOperation('+', num1, num2, num1.min + num2.min, num1.max + num2.max);
- }
- function buildMulOperation(num1, num2) {
- if (num2.type === 'literal') {
- // optimization: second operands is a literal...
- if (num2.number === 0) {
- return new AstLiteral(0);
- } else // and it's 0
- if (num2.number === 1) {
- return num1;
- } else // and it's 1
- if (num1.type === 'literal') {
- // ... and first operands is a literal too
- return new AstLiteral(num1.number * num2.number);
- }
- }
- if (num1.type === 'literal') {
- // optimization: first operands is a literal...
- if (num1.number === 0) {
- return new AstLiteral(0);
- } else // and it's 0
- if (num1.number === 1) {
- return num2;
- }
- }
- // and it's 1
- var min = Math.min(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);
- var max = Math.max(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);
- return new AstBinaryOperation('*', num1, num2, min, max);
- }
- function buildSubOperation(num1, num2) {
- if (num2.type === 'literal') {
- // optimization: second operands is a literal...
- if (num2.number === 0) {
- return num1;
- } else // ... and it's 0
- if (num1.type === 'literal') {
- // ... and first operands is a literal too
- return new AstLiteral(num1.number - num2.number);
- }
- }
- if (num2.type === 'binary' && num2.op === '-' && num1.type === 'literal' && num1.number === 1 && num2.arg1.type === 'literal' && num2.arg1.number === 1) {
- // optimization for case: 1 - (1 - x)
- return num2.arg2;
- }
- return new AstBinaryOperation('-', num1, num2, num1.min - num2.max, num1.max - num2.min);
- }
- function buildMinOperation(num1, max) {
- if (num1.min >= max) {
- // optimization: num1 min value is not less than required max
- return new AstLiteral(max);
- } else // just returning max
- if (num1.max <= max) {
- // optimization: num1 max value is not greater than required max
- return num1;
- }
- // just returning an argument
- return new AstMin(num1, max);
- }
- function PostScriptCompiler() {
- }
- PostScriptCompiler.prototype = {
- compile: function PostScriptCompiler_compile(code, domain, range) {
- var stack = [];
- var i, ii;
- var instructions = [];
- var inputSize = domain.length >> 1, outputSize = range.length >> 1;
- var lastRegister = 0;
- var n, j;
- var num1, num2, ast1, ast2, tmpVar, item;
- for (i = 0; i < inputSize; i++) {
- stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1]));
- }
- for (i = 0, ii = code.length; i < ii; i++) {
- item = code[i];
- if (typeof item === 'number') {
- stack.push(new AstLiteral(item));
- continue;
- }
- switch (item) {
- case 'add':
- if (stack.length < 2) {
- return null;
- }
- num2 = stack.pop();
- num1 = stack.pop();
- stack.push(buildAddOperation(num1, num2));
- break;
- case 'cvr':
- if (stack.length < 1) {
- return null;
- }
- break;
- case 'mul':
- if (stack.length < 2) {
- return null;
- }
- num2 = stack.pop();
- num1 = stack.pop();
- stack.push(buildMulOperation(num1, num2));
- break;
- case 'sub':
- if (stack.length < 2) {
- return null;
- }
- num2 = stack.pop();
- num1 = stack.pop();
- stack.push(buildSubOperation(num1, num2));
- break;
- case 'exch':
- if (stack.length < 2) {
- return null;
- }
- ast1 = stack.pop();
- ast2 = stack.pop();
- stack.push(ast1, ast2);
- break;
- case 'pop':
- if (stack.length < 1) {
- return null;
- }
- stack.pop();
- break;
- case 'index':
- if (stack.length < 1) {
- return null;
- }
- num1 = stack.pop();
- if (num1.type !== 'literal') {
- return null;
- }
- n = num1.number;
- if (n < 0 || (n | 0) !== n || stack.length < n) {
- return null;
- }
- ast1 = stack[stack.length - n - 1];
- if (ast1.type === 'literal' || ast1.type === 'var') {
- stack.push(ast1);
- break;
- }
- tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
- stack[stack.length - n - 1] = tmpVar;
- stack.push(tmpVar);
- instructions.push(new AstVariableDefinition(tmpVar, ast1));
- break;
- case 'dup':
- if (stack.length < 1) {
- return null;
- }
- if (typeof code[i + 1] === 'number' && code[i + 2] === 'gt' && code[i + 3] === i + 7 && code[i + 4] === 'jz' && code[i + 5] === 'pop' && code[i + 6] === code[i + 1]) {
- // special case of the commands sequence for the min operation
- num1 = stack.pop();
- stack.push(buildMinOperation(num1, code[i + 1]));
- i += 6;
- break;
- }
- ast1 = stack[stack.length - 1];
- if (ast1.type === 'literal' || ast1.type === 'var') {
- // we don't have to save into intermediate variable a literal or
- // variable.
- stack.push(ast1);
- break;
- }
- tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
- stack[stack.length - 1] = tmpVar;
- stack.push(tmpVar);
- instructions.push(new AstVariableDefinition(tmpVar, ast1));
- break;
- case 'roll':
- if (stack.length < 2) {
- return null;
- }
- num2 = stack.pop();
- num1 = stack.pop();
- if (num2.type !== 'literal' || num1.type !== 'literal') {
- // both roll operands must be numbers
- return null;
- }
- j = num2.number;
- n = num1.number;
- if (n <= 0 || (n | 0) !== n || (j | 0) !== j || stack.length < n) {
- // ... and integers
- return null;
- }
- j = (j % n + n) % n;
- if (j === 0) {
- break;
- }
- // just skipping -- there are nothing to rotate
- Array.prototype.push.apply(stack, stack.splice(stack.length - n, n - j));
- break;
- default:
- return null;
- }
- }
- // unsupported operator
- if (stack.length !== outputSize) {
- return null;
- }
- var result = [];
- instructions.forEach(function (instruction) {
- var statementBuilder = new ExpressionBuilderVisitor();
- instruction.visit(statementBuilder);
- result.push(statementBuilder.toString());
- });
- stack.forEach(function (expr, i) {
- var statementBuilder = new ExpressionBuilderVisitor();
- expr.visit(statementBuilder);
- var min = range[i * 2], max = range[i * 2 + 1];
- var out = [statementBuilder.toString()];
- if (min > expr.min) {
- out.unshift('Math.max(', min, ', ');
- out.push(')');
- }
- if (max < expr.max) {
- out.unshift('Math.min(', max, ', ');
- out.push(')');
- }
- out.unshift('dest[destOffset + ', i, '] = ');
- out.push(';');
- result.push(out.join(''));
- });
- return result.join('\n');
- }
- };
- return PostScriptCompiler;
- }();
- exports.isPDFFunction = isPDFFunction;
- exports.PDFFunction = PDFFunction;
- exports.PostScriptEvaluator = PostScriptEvaluator;
- exports.PostScriptCompiler = PostScriptCompiler;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreColorSpace = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreFunction);
- }(this, function (exports, sharedUtil, corePrimitives, coreFunction) {
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var isArray = sharedUtil.isArray;
- var isString = sharedUtil.isString;
- var shadow = sharedUtil.shadow;
- var warn = sharedUtil.warn;
- var isDict = corePrimitives.isDict;
- var isName = corePrimitives.isName;
- var isStream = corePrimitives.isStream;
- var PDFFunction = coreFunction.PDFFunction;
- var ColorSpace = function ColorSpaceClosure() {
- /**
- * Resizes an RGB image with 3 components.
- * @param {TypedArray} src - The source buffer.
- * @param {Number} bpc - Number of bits per component.
- * @param {Number} w1 - Original width.
- * @param {Number} h1 - Original height.
- * @param {Number} w2 - New width.
- * @param {Number} h2 - New height.
- * @param {Number} alpha01 - Size reserved for the alpha channel.
- * @param {TypedArray} dest - The destination buffer.
- */
- function resizeRgbImage(src, bpc, w1, h1, w2, h2, alpha01, dest) {
- var COMPONENTS = 3;
- alpha01 = alpha01 !== 1 ? 0 : alpha01;
- var xRatio = w1 / w2;
- var yRatio = h1 / h2;
- var i, j, py, newIndex = 0, oldIndex;
- var xScaled = new Uint16Array(w2);
- var w1Scanline = w1 * COMPONENTS;
- for (i = 0; i < w2; i++) {
- xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
- }
- for (i = 0; i < h2; i++) {
- py = Math.floor(i * yRatio) * w1Scanline;
- for (j = 0; j < w2; j++) {
- oldIndex = py + xScaled[j];
- dest[newIndex++] = src[oldIndex++];
- dest[newIndex++] = src[oldIndex++];
- dest[newIndex++] = src[oldIndex++];
- newIndex += alpha01;
- }
- }
- }
- // Constructor should define this.numComps, this.defaultColor, this.name
- function ColorSpace() {
- error('should not call ColorSpace constructor');
- }
- ColorSpace.prototype = {
- /**
- * Converts the color value to the RGB color. The color components are
- * located in the src array starting from the srcOffset. Returns the array
- * of the rgb components, each value ranging from [0,255].
- */
- getRgb: function ColorSpace_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- this.getRgbItem(src, srcOffset, rgb, 0);
- return rgb;
- },
- /**
- * Converts the color value to the RGB color, similar to the getRgb method.
- * The result placed into the dest array starting from the destOffset.
- */
- getRgbItem: function ColorSpace_getRgbItem(src, srcOffset, dest, destOffset) {
- error('Should not call ColorSpace.getRgbItem');
- },
- /**
- * Converts the specified number of the color values to the RGB colors.
- * The colors are located in the src array starting from the srcOffset.
- * The result is placed into the dest array starting from the destOffset.
- * The src array items shall be in [0,2^bits) range, the dest array items
- * will be in [0,255] range. alpha01 indicates how many alpha components
- * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
- * array).
- */
- getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- error('Should not call ColorSpace.getRgbBuffer');
- },
- /**
- * Determines the number of bytes required to store the result of the
- * conversion done by the getRgbBuffer method. As in getRgbBuffer,
- * |alpha01| is either 0 (RGB output) or 1 (RGBA output).
- */
- getOutputLength: function ColorSpace_getOutputLength(inputLength, alpha01) {
- error('Should not call ColorSpace.getOutputLength');
- },
- /**
- * Returns true if source data will be equal the result/output data.
- */
- isPassthrough: function ColorSpace_isPassthrough(bits) {
- return false;
- },
- /**
- * Fills in the RGB colors in the destination buffer. alpha01 indicates
- * how many alpha components there are in the dest array; it will be either
- * 0 (RGB array) or 1 (RGBA array).
- */
- fillRgb: function ColorSpace_fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
- var count = originalWidth * originalHeight;
- var rgbBuf = null;
- var numComponentColors = 1 << bpc;
- var needsResizing = originalHeight !== height || originalWidth !== width;
- var i, ii;
- if (this.isPassthrough(bpc)) {
- rgbBuf = comps;
- } else if (this.numComps === 1 && count > numComponentColors && this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') {
- // Optimization: create a color map when there is just one component and
- // we are converting more colors than the size of the color map. We
- // don't build the map if the colorspace is gray or rgb since those
- // methods are faster than building a map. This mainly offers big speed
- // ups for indexed and alternate colorspaces.
- //
- // TODO it may be worth while to cache the color map. While running
- // testing I never hit a cache so I will leave that out for now (perhaps
- // we are reparsing colorspaces too much?).
- var allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
- var key;
- for (i = 0; i < numComponentColors; i++) {
- allColors[i] = i;
- }
- var colorMap = new Uint8Array(numComponentColors * 3);
- this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, /* alpha01 = */
- 0);
- var destPos, rgbPos;
- if (!needsResizing) {
- // Fill in the RGB values directly into |dest|.
- destPos = 0;
- for (i = 0; i < count; ++i) {
- key = comps[i] * 3;
- dest[destPos++] = colorMap[key];
- dest[destPos++] = colorMap[key + 1];
- dest[destPos++] = colorMap[key + 2];
- destPos += alpha01;
- }
- } else {
- rgbBuf = new Uint8Array(count * 3);
- rgbPos = 0;
- for (i = 0; i < count; ++i) {
- key = comps[i] * 3;
- rgbBuf[rgbPos++] = colorMap[key];
- rgbBuf[rgbPos++] = colorMap[key + 1];
- rgbBuf[rgbPos++] = colorMap[key + 2];
- }
- }
- } else {
- if (!needsResizing) {
- // Fill in the RGB values directly into |dest|.
- this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
- } else {
- rgbBuf = new Uint8Array(count * 3);
- this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, /* alpha01 = */
- 0);
- }
- }
- if (rgbBuf) {
- if (needsResizing) {
- resizeRgbImage(rgbBuf, bpc, originalWidth, originalHeight, width, height, alpha01, dest);
- } else {
- rgbPos = 0;
- destPos = 0;
- for (i = 0, ii = width * actualHeight; i < ii; i++) {
- dest[destPos++] = rgbBuf[rgbPos++];
- dest[destPos++] = rgbBuf[rgbPos++];
- dest[destPos++] = rgbBuf[rgbPos++];
- destPos += alpha01;
- }
- }
- }
- },
- /**
- * True if the colorspace has components in the default range of [0, 1].
- * This should be true for all colorspaces except for lab color spaces
- * which are [0,100], [-128, 127], [-128, 127].
- */
- usesZeroToOneRange: true
- };
- ColorSpace.parse = function ColorSpace_parse(cs, xref, res) {
- var IR = ColorSpace.parseToIR(cs, xref, res);
- if (IR instanceof AlternateCS) {
- return IR;
- }
- return ColorSpace.fromIR(IR);
- };
- ColorSpace.fromIR = function ColorSpace_fromIR(IR) {
- var name = isArray(IR) ? IR[0] : IR;
- var whitePoint, blackPoint, gamma;
- switch (name) {
- case 'DeviceGrayCS':
- return this.singletons.gray;
- case 'DeviceRgbCS':
- return this.singletons.rgb;
- case 'DeviceCmykCS':
- return this.singletons.cmyk;
- case 'CalGrayCS':
- whitePoint = IR[1];
- blackPoint = IR[2];
- gamma = IR[3];
- return new CalGrayCS(whitePoint, blackPoint, gamma);
- case 'CalRGBCS':
- whitePoint = IR[1];
- blackPoint = IR[2];
- gamma = IR[3];
- var matrix = IR[4];
- return new CalRGBCS(whitePoint, blackPoint, gamma, matrix);
- case 'PatternCS':
- var basePatternCS = IR[1];
- if (basePatternCS) {
- basePatternCS = ColorSpace.fromIR(basePatternCS);
- }
- return new PatternCS(basePatternCS);
- case 'IndexedCS':
- var baseIndexedCS = IR[1];
- var hiVal = IR[2];
- var lookup = IR[3];
- return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup);
- case 'AlternateCS':
- var numComps = IR[1];
- var alt = IR[2];
- var tintFn = IR[3];
- return new AlternateCS(numComps, ColorSpace.fromIR(alt), tintFn);
- case 'LabCS':
- whitePoint = IR[1];
- blackPoint = IR[2];
- var range = IR[3];
- return new LabCS(whitePoint, blackPoint, range);
- default:
- error('Unknown name ' + name);
- }
- return null;
- };
- ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) {
- if (isName(cs)) {
- var colorSpaces = res.get('ColorSpace');
- if (isDict(colorSpaces)) {
- var refcs = colorSpaces.get(cs.name);
- if (refcs) {
- cs = refcs;
- }
- }
- }
- cs = xref.fetchIfRef(cs);
- var mode;
- if (isName(cs)) {
- mode = cs.name;
- this.mode = mode;
- switch (mode) {
- case 'DeviceGray':
- case 'G':
- return 'DeviceGrayCS';
- case 'DeviceRGB':
- case 'RGB':
- return 'DeviceRgbCS';
- case 'DeviceCMYK':
- case 'CMYK':
- return 'DeviceCmykCS';
- case 'Pattern':
- return [
- 'PatternCS',
- null
- ];
- default:
- error('unrecognized colorspace ' + mode);
- }
- } else if (isArray(cs)) {
- mode = xref.fetchIfRef(cs[0]).name;
- this.mode = mode;
- var numComps, params, alt, whitePoint, blackPoint, gamma;
- switch (mode) {
- case 'DeviceGray':
- case 'G':
- return 'DeviceGrayCS';
- case 'DeviceRGB':
- case 'RGB':
- return 'DeviceRgbCS';
- case 'DeviceCMYK':
- case 'CMYK':
- return 'DeviceCmykCS';
- case 'CalGray':
- params = xref.fetchIfRef(cs[1]);
- whitePoint = params.getArray('WhitePoint');
- blackPoint = params.getArray('BlackPoint');
- gamma = params.get('Gamma');
- return [
- 'CalGrayCS',
- whitePoint,
- blackPoint,
- gamma
- ];
- case 'CalRGB':
- params = xref.fetchIfRef(cs[1]);
- whitePoint = params.getArray('WhitePoint');
- blackPoint = params.getArray('BlackPoint');
- gamma = params.getArray('Gamma');
- var matrix = params.getArray('Matrix');
- return [
- 'CalRGBCS',
- whitePoint,
- blackPoint,
- gamma,
- matrix
- ];
- case 'ICCBased':
- var stream = xref.fetchIfRef(cs[1]);
- var dict = stream.dict;
- numComps = dict.get('N');
- alt = dict.get('Alternate');
- if (alt) {
- var altIR = ColorSpace.parseToIR(alt, xref, res);
- // Parse the /Alternate CS to ensure that the number of components
- // are correct, and also (indirectly) that it is not a PatternCS.
- var altCS = ColorSpace.fromIR(altIR);
- if (altCS.numComps === numComps) {
- return altIR;
- }
- warn('ICCBased color space: Ignoring incorrect /Alternate entry.');
- }
- if (numComps === 1) {
- return 'DeviceGrayCS';
- } else if (numComps === 3) {
- return 'DeviceRgbCS';
- } else if (numComps === 4) {
- return 'DeviceCmykCS';
- }
- break;
- case 'Pattern':
- var basePatternCS = cs[1] || null;
- if (basePatternCS) {
- basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
- }
- return [
- 'PatternCS',
- basePatternCS
- ];
- case 'Indexed':
- case 'I':
- var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
- var hiVal = xref.fetchIfRef(cs[2]) + 1;
- var lookup = xref.fetchIfRef(cs[3]);
- if (isStream(lookup)) {
- lookup = lookup.getBytes();
- }
- return [
- 'IndexedCS',
- baseIndexedCS,
- hiVal,
- lookup
- ];
- case 'Separation':
- case 'DeviceN':
- var name = xref.fetchIfRef(cs[1]);
- numComps = 1;
- if (isName(name)) {
- numComps = 1;
- } else if (isArray(name)) {
- numComps = name.length;
- }
- alt = ColorSpace.parseToIR(cs[2], xref, res);
- var tintFn = PDFFunction.parse(xref, xref.fetchIfRef(cs[3]));
- return [
- 'AlternateCS',
- numComps,
- alt,
- tintFn
- ];
- case 'Lab':
- params = xref.fetchIfRef(cs[1]);
- whitePoint = params.getArray('WhitePoint');
- blackPoint = params.getArray('BlackPoint');
- var range = params.getArray('Range');
- return [
- 'LabCS',
- whitePoint,
- blackPoint,
- range
- ];
- default:
- error('unimplemented color space object "' + mode + '"');
- }
- } else {
- error('unrecognized color space object: "' + cs + '"');
- }
- return null;
- };
- /**
- * Checks if a decode map matches the default decode map for a color space.
- * This handles the general decode maps where there are two values per
- * component. e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
- * This does not handle Lab, Indexed, or Pattern decode maps since they are
- * slightly different.
- * @param {Array} decode Decode map (usually from an image).
- * @param {Number} n Number of components the color space has.
- */
- ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) {
- if (!isArray(decode)) {
- return true;
- }
- if (n * 2 !== decode.length) {
- warn('The decode map is not the correct length');
- return true;
- }
- for (var i = 0, ii = decode.length; i < ii; i += 2) {
- if (decode[i] !== 0 || decode[i + 1] !== 1) {
- return false;
- }
- }
- return true;
- };
- ColorSpace.singletons = {
- get gray() {
- return shadow(this, 'gray', new DeviceGrayCS());
- },
- get rgb() {
- return shadow(this, 'rgb', new DeviceRgbCS());
- },
- get cmyk() {
- return shadow(this, 'cmyk', new DeviceCmykCS());
- }
- };
- return ColorSpace;
- }();
- /**
- * Alternate color space handles both Separation and DeviceN color spaces. A
- * Separation color space is actually just a DeviceN with one color component.
- * Both color spaces use a tinting function to convert colors to a base color
- * space.
- */
- var AlternateCS = function AlternateCSClosure() {
- function AlternateCS(numComps, base, tintFn) {
- this.name = 'Alternate';
- this.numComps = numComps;
- this.defaultColor = new Float32Array(numComps);
- for (var i = 0; i < numComps; ++i) {
- this.defaultColor[i] = 1;
- }
- this.base = base;
- this.tintFn = tintFn;
- this.tmpBuf = new Float32Array(base.numComps);
- }
- AlternateCS.prototype = {
- getRgb: ColorSpace.prototype.getRgb,
- getRgbItem: function AlternateCS_getRgbItem(src, srcOffset, dest, destOffset) {
- var tmpBuf = this.tmpBuf;
- this.tintFn(src, srcOffset, tmpBuf, 0);
- this.base.getRgbItem(tmpBuf, 0, dest, destOffset);
- },
- getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var tintFn = this.tintFn;
- var base = this.base;
- var scale = 1 / ((1 << bits) - 1);
- var baseNumComps = base.numComps;
- var usesZeroToOneRange = base.usesZeroToOneRange;
- var isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && alpha01 === 0;
- var pos = isPassthrough ? destOffset : 0;
- var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count);
- var numComps = this.numComps;
- var scaled = new Float32Array(numComps);
- var tinted = new Float32Array(baseNumComps);
- var i, j;
- if (usesZeroToOneRange) {
- for (i = 0; i < count; i++) {
- for (j = 0; j < numComps; j++) {
- scaled[j] = src[srcOffset++] * scale;
- }
- tintFn(scaled, 0, tinted, 0);
- for (j = 0; j < baseNumComps; j++) {
- baseBuf[pos++] = tinted[j] * 255;
- }
- }
- } else {
- for (i = 0; i < count; i++) {
- for (j = 0; j < numComps; j++) {
- scaled[j] = src[srcOffset++] * scale;
- }
- tintFn(scaled, 0, tinted, 0);
- base.getRgbItem(tinted, 0, baseBuf, pos);
- pos += baseNumComps;
- }
- }
- if (!isPassthrough) {
- base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01);
- }
- },
- getOutputLength: function AlternateCS_getOutputLength(inputLength, alpha01) {
- return this.base.getOutputLength(inputLength * this.base.numComps / this.numComps, alpha01);
- },
- isPassthrough: ColorSpace.prototype.isPassthrough,
- fillRgb: ColorSpace.prototype.fillRgb,
- isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- },
- usesZeroToOneRange: true
- };
- return AlternateCS;
- }();
- var PatternCS = function PatternCSClosure() {
- function PatternCS(baseCS) {
- this.name = 'Pattern';
- this.base = baseCS;
- }
- PatternCS.prototype = {};
- return PatternCS;
- }();
- var IndexedCS = function IndexedCSClosure() {
- function IndexedCS(base, highVal, lookup) {
- this.name = 'Indexed';
- this.numComps = 1;
- this.defaultColor = new Uint8Array([0]);
- this.base = base;
- this.highVal = highVal;
- var baseNumComps = base.numComps;
- var length = baseNumComps * highVal;
- var lookupArray;
- if (isStream(lookup)) {
- lookupArray = new Uint8Array(length);
- var bytes = lookup.getBytes(length);
- lookupArray.set(bytes);
- } else if (isString(lookup)) {
- lookupArray = new Uint8Array(length);
- for (var i = 0; i < length; ++i) {
- lookupArray[i] = lookup.charCodeAt(i);
- }
- } else if (lookup instanceof Uint8Array || lookup instanceof Array) {
- lookupArray = lookup;
- } else {
- error('Unrecognized lookup table: ' + lookup);
- }
- this.lookup = lookupArray;
- }
- IndexedCS.prototype = {
- getRgb: ColorSpace.prototype.getRgb,
- getRgbItem: function IndexedCS_getRgbItem(src, srcOffset, dest, destOffset) {
- var numComps = this.base.numComps;
- var start = src[srcOffset] * numComps;
- this.base.getRgbItem(this.lookup, start, dest, destOffset);
- },
- getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var base = this.base;
- var numComps = base.numComps;
- var outputDelta = base.getOutputLength(numComps, alpha01);
- var lookup = this.lookup;
- for (var i = 0; i < count; ++i) {
- var lookupPos = src[srcOffset++] * numComps;
- base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01);
- destOffset += outputDelta;
- }
- },
- getOutputLength: function IndexedCS_getOutputLength(inputLength, alpha01) {
- return this.base.getOutputLength(inputLength * this.base.numComps, alpha01);
- },
- isPassthrough: ColorSpace.prototype.isPassthrough,
- fillRgb: ColorSpace.prototype.fillRgb,
- isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) {
- // indexed color maps shouldn't be changed
- return true;
- },
- usesZeroToOneRange: true
- };
- return IndexedCS;
- }();
- var DeviceGrayCS = function DeviceGrayCSClosure() {
- function DeviceGrayCS() {
- this.name = 'DeviceGray';
- this.numComps = 1;
- this.defaultColor = new Float32Array([0]);
- }
- DeviceGrayCS.prototype = {
- getRgb: ColorSpace.prototype.getRgb,
- getRgbItem: function DeviceGrayCS_getRgbItem(src, srcOffset, dest, destOffset) {
- var c = src[srcOffset] * 255 | 0;
- c = c < 0 ? 0 : c > 255 ? 255 : c;
- dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c;
- },
- getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var scale = 255 / ((1 << bits) - 1);
- var j = srcOffset, q = destOffset;
- for (var i = 0; i < count; ++i) {
- var c = scale * src[j++] | 0;
- dest[q++] = c;
- dest[q++] = c;
- dest[q++] = c;
- q += alpha01;
- }
- },
- getOutputLength: function DeviceGrayCS_getOutputLength(inputLength, alpha01) {
- return inputLength * (3 + alpha01);
- },
- isPassthrough: ColorSpace.prototype.isPassthrough,
- fillRgb: ColorSpace.prototype.fillRgb,
- isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- },
- usesZeroToOneRange: true
- };
- return DeviceGrayCS;
- }();
- var DeviceRgbCS = function DeviceRgbCSClosure() {
- function DeviceRgbCS() {
- this.name = 'DeviceRGB';
- this.numComps = 3;
- this.defaultColor = new Float32Array([
- 0,
- 0,
- 0
- ]);
- }
- DeviceRgbCS.prototype = {
- getRgb: ColorSpace.prototype.getRgb,
- getRgbItem: function DeviceRgbCS_getRgbItem(src, srcOffset, dest, destOffset) {
- var r = src[srcOffset] * 255 | 0;
- var g = src[srcOffset + 1] * 255 | 0;
- var b = src[srcOffset + 2] * 255 | 0;
- dest[destOffset] = r < 0 ? 0 : r > 255 ? 255 : r;
- dest[destOffset + 1] = g < 0 ? 0 : g > 255 ? 255 : g;
- dest[destOffset + 2] = b < 0 ? 0 : b > 255 ? 255 : b;
- },
- getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- if (bits === 8 && alpha01 === 0) {
- dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset);
- return;
- }
- var scale = 255 / ((1 << bits) - 1);
- var j = srcOffset, q = destOffset;
- for (var i = 0; i < count; ++i) {
- dest[q++] = scale * src[j++] | 0;
- dest[q++] = scale * src[j++] | 0;
- dest[q++] = scale * src[j++] | 0;
- q += alpha01;
- }
- },
- getOutputLength: function DeviceRgbCS_getOutputLength(inputLength, alpha01) {
- return inputLength * (3 + alpha01) / 3 | 0;
- },
- isPassthrough: function DeviceRgbCS_isPassthrough(bits) {
- return bits === 8;
- },
- fillRgb: ColorSpace.prototype.fillRgb,
- isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- },
- usesZeroToOneRange: true
- };
- return DeviceRgbCS;
- }();
- var DeviceCmykCS = function DeviceCmykCSClosure() {
- // The coefficients below was found using numerical analysis: the method of
- // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
- // where color_value is the tabular value from the table of sampled RGB colors
- // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
- // CMYK color conversion using the estimation below:
- // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
- function convertToRgb(src, srcOffset, srcScale, dest, destOffset) {
- var c = src[srcOffset + 0] * srcScale;
- var m = src[srcOffset + 1] * srcScale;
- var y = src[srcOffset + 2] * srcScale;
- var k = src[srcOffset + 3] * srcScale;
- var r = c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k + -285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y + -17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) + k * (-21.86122147463605 * k - 189.48180835922747) + 255 | 0;
- var g = c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k + -79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + k * (-20.737325471181034 * k - 187.80453709719578) + 255 | 0;
- var b = c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k + -14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k + -193.58209356861505) + k * (-22.33816807309886 * k - 180.12613974708367) + 255 | 0;
- dest[destOffset] = r > 255 ? 255 : r < 0 ? 0 : r;
- dest[destOffset + 1] = g > 255 ? 255 : g < 0 ? 0 : g;
- dest[destOffset + 2] = b > 255 ? 255 : b < 0 ? 0 : b;
- }
- function DeviceCmykCS() {
- this.name = 'DeviceCMYK';
- this.numComps = 4;
- this.defaultColor = new Float32Array([
- 0,
- 0,
- 0,
- 1
- ]);
- }
- DeviceCmykCS.prototype = {
- getRgb: ColorSpace.prototype.getRgb,
- getRgbItem: function DeviceCmykCS_getRgbItem(src, srcOffset, dest, destOffset) {
- convertToRgb(src, srcOffset, 1, dest, destOffset);
- },
- getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var scale = 1 / ((1 << bits) - 1);
- for (var i = 0; i < count; i++) {
- convertToRgb(src, srcOffset, scale, dest, destOffset);
- srcOffset += 4;
- destOffset += 3 + alpha01;
- }
- },
- getOutputLength: function DeviceCmykCS_getOutputLength(inputLength, alpha01) {
- return inputLength / 4 * (3 + alpha01) | 0;
- },
- isPassthrough: ColorSpace.prototype.isPassthrough,
- fillRgb: ColorSpace.prototype.fillRgb,
- isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- },
- usesZeroToOneRange: true
- };
- return DeviceCmykCS;
- }();
- //
- // CalGrayCS: Based on "PDF Reference, Sixth Ed", p.245
- //
- var CalGrayCS = function CalGrayCSClosure() {
- function CalGrayCS(whitePoint, blackPoint, gamma) {
- this.name = 'CalGray';
- this.numComps = 1;
- this.defaultColor = new Float32Array([0]);
- if (!whitePoint) {
- error('WhitePoint missing - required for color space CalGray');
- }
- blackPoint = blackPoint || [
- 0,
- 0,
- 0
- ];
- gamma = gamma || 1;
- // Translate arguments to spec variables.
- this.XW = whitePoint[0];
- this.YW = whitePoint[1];
- this.ZW = whitePoint[2];
- this.XB = blackPoint[0];
- this.YB = blackPoint[1];
- this.ZB = blackPoint[2];
- this.G = gamma;
- // Validate variables as per spec.
- if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
- error('Invalid WhitePoint components for ' + this.name + ', no fallback available');
- }
- if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
- info('Invalid BlackPoint for ' + this.name + ', falling back to default');
- this.XB = this.YB = this.ZB = 0;
- }
- if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
- warn(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB + ', ZB: ' + this.ZB + ', only default values are supported.');
- }
- if (this.G < 1) {
- info('Invalid Gamma: ' + this.G + ' for ' + this.name + ', falling back to default');
- this.G = 1;
- }
- }
- function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) {
- // A represents a gray component of a calibrated gray space.
- // A <---> AG in the spec
- var A = src[srcOffset] * scale;
- var AG = Math.pow(A, cs.G);
- // Computes L as per spec. ( = cs.YW * AG )
- // Except if other than default BlackPoint values are used.
- var L = cs.YW * AG;
- // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html, Ch 4.
- // Convert values to rgb range [0, 255].
- var val = Math.max(295.8 * Math.pow(L, 0.333333333333333333) - 40.8, 0) | 0;
- dest[destOffset] = val;
- dest[destOffset + 1] = val;
- dest[destOffset + 2] = val;
- }
- CalGrayCS.prototype = {
- getRgb: ColorSpace.prototype.getRgb,
- getRgbItem: function CalGrayCS_getRgbItem(src, srcOffset, dest, destOffset) {
- convertToRgb(this, src, srcOffset, dest, destOffset, 1);
- },
- getRgbBuffer: function CalGrayCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var scale = 1 / ((1 << bits) - 1);
- for (var i = 0; i < count; ++i) {
- convertToRgb(this, src, srcOffset, dest, destOffset, scale);
- srcOffset += 1;
- destOffset += 3 + alpha01;
- }
- },
- getOutputLength: function CalGrayCS_getOutputLength(inputLength, alpha01) {
- return inputLength * (3 + alpha01);
- },
- isPassthrough: ColorSpace.prototype.isPassthrough,
- fillRgb: ColorSpace.prototype.fillRgb,
- isDefaultDecode: function CalGrayCS_isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- },
- usesZeroToOneRange: true
- };
- return CalGrayCS;
- }();
- //
- // CalRGBCS: Based on "PDF Reference, Sixth Ed", p.247
- //
- var CalRGBCS = function CalRGBCSClosure() {
- // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
- // matrices.
- var BRADFORD_SCALE_MATRIX = new Float32Array([
- 0.8951,
- 0.2664,
- -0.1614,
- -0.7502,
- 1.7135,
- 0.0367,
- 0.0389,
- -0.0685,
- 1.0296
- ]);
- var BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
- 0.9869929,
- -0.1470543,
- 0.1599627,
- 0.4323053,
- 0.5183603,
- 0.0492912,
- -0.0085287,
- 0.0400428,
- 0.9684867
- ]);
- // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
- var SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
- 3.2404542,
- -1.5371385,
- -0.4985314,
- -0.9692660,
- 1.8760108,
- 0.0415560,
- 0.0556434,
- -0.2040259,
- 1.0572252
- ]);
- var FLAT_WHITEPOINT_MATRIX = new Float32Array([
- 1,
- 1,
- 1
- ]);
- var tempNormalizeMatrix = new Float32Array(3);
- var tempConvertMatrix1 = new Float32Array(3);
- var tempConvertMatrix2 = new Float32Array(3);
- var DECODE_L_CONSTANT = Math.pow((8 + 16) / 116, 3) / 8.0;
- function CalRGBCS(whitePoint, blackPoint, gamma, matrix) {
- this.name = 'CalRGB';
- this.numComps = 3;
- this.defaultColor = new Float32Array(3);
- if (!whitePoint) {
- error('WhitePoint missing - required for color space CalRGB');
- }
- blackPoint = blackPoint || new Float32Array(3);
- gamma = gamma || new Float32Array([
- 1,
- 1,
- 1
- ]);
- matrix = matrix || new Float32Array([
- 1,
- 0,
- 0,
- 0,
- 1,
- 0,
- 0,
- 0,
- 1
- ]);
- // Translate arguments to spec variables.
- var XW = whitePoint[0];
- var YW = whitePoint[1];
- var ZW = whitePoint[2];
- this.whitePoint = whitePoint;
- var XB = blackPoint[0];
- var YB = blackPoint[1];
- var ZB = blackPoint[2];
- this.blackPoint = blackPoint;
- this.GR = gamma[0];
- this.GG = gamma[1];
- this.GB = gamma[2];
- this.MXA = matrix[0];
- this.MYA = matrix[1];
- this.MZA = matrix[2];
- this.MXB = matrix[3];
- this.MYB = matrix[4];
- this.MZB = matrix[5];
- this.MXC = matrix[6];
- this.MYC = matrix[7];
- this.MZC = matrix[8];
- // Validate variables as per spec.
- if (XW < 0 || ZW < 0 || YW !== 1) {
- error('Invalid WhitePoint components for ' + this.name + ', no fallback available');
- }
- if (XB < 0 || YB < 0 || ZB < 0) {
- info('Invalid BlackPoint for ' + this.name + ' [' + XB + ', ' + YB + ', ' + ZB + '], falling back to default');
- this.blackPoint = new Float32Array(3);
- }
- if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
- info('Invalid Gamma [' + this.GR + ', ' + this.GG + ', ' + this.GB + '] for ' + this.name + ', falling back to default');
- this.GR = this.GG = this.GB = 1;
- }
- if (this.MXA < 0 || this.MYA < 0 || this.MZA < 0 || this.MXB < 0 || this.MYB < 0 || this.MZB < 0 || this.MXC < 0 || this.MYC < 0 || this.MZC < 0) {
- info('Invalid Matrix for ' + this.name + ' [' + this.MXA + ', ' + this.MYA + ', ' + this.MZA + this.MXB + ', ' + this.MYB + ', ' + this.MZB + this.MXC + ', ' + this.MYC + ', ' + this.MZC + '], falling back to default');
- this.MXA = this.MYB = this.MZC = 1;
- this.MXB = this.MYA = this.MZA = this.MXC = this.MYC = this.MZB = 0;
- }
- }
- function matrixProduct(a, b, result) {
- result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
- result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
- result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
- }
- function convertToFlat(sourceWhitePoint, LMS, result) {
- result[0] = LMS[0] * 1 / sourceWhitePoint[0];
- result[1] = LMS[1] * 1 / sourceWhitePoint[1];
- result[2] = LMS[2] * 1 / sourceWhitePoint[2];
- }
- function convertToD65(sourceWhitePoint, LMS, result) {
- var D65X = 0.95047;
- var D65Y = 1;
- var D65Z = 1.08883;
- result[0] = LMS[0] * D65X / sourceWhitePoint[0];
- result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
- result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
- }
- function sRGBTransferFunction(color) {
- // See http://en.wikipedia.org/wiki/SRGB.
- if (color <= 0.0031308) {
- return adjustToRange(0, 1, 12.92 * color);
- }
- return adjustToRange(0, 1, (1 + 0.055) * Math.pow(color, 1 / 2.4) - 0.055);
- }
- function adjustToRange(min, max, value) {
- return Math.max(min, Math.min(max, value));
- }
- function decodeL(L) {
- if (L < 0) {
- return -decodeL(-L);
- }
- if (L > 8.0) {
- return Math.pow((L + 16) / 116, 3);
- }
- return L * DECODE_L_CONSTANT;
- }
- function compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
- // In case the blackPoint is already the default blackPoint then there is
- // no need to do compensation.
- if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
- result[0] = XYZ_Flat[0];
- result[1] = XYZ_Flat[1];
- result[2] = XYZ_Flat[2];
- return;
- }
- // For the blackPoint calculation details, please see
- // http://www.adobe.com/content/dam/Adobe/en/devnet/photoshop/sdk/
- // AdobeBPC.pdf.
- // The destination blackPoint is the default blackPoint [0, 0, 0].
- var zeroDecodeL = decodeL(0);
- var X_DST = zeroDecodeL;
- var X_SRC = decodeL(sourceBlackPoint[0]);
- var Y_DST = zeroDecodeL;
- var Y_SRC = decodeL(sourceBlackPoint[1]);
- var Z_DST = zeroDecodeL;
- var Z_SRC = decodeL(sourceBlackPoint[2]);
- var X_Scale = (1 - X_DST) / (1 - X_SRC);
- var X_Offset = 1 - X_Scale;
- var Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
- var Y_Offset = 1 - Y_Scale;
- var Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
- var Z_Offset = 1 - Z_Scale;
- result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
- result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
- result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
- }
- function normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
- // In case the whitePoint is already flat then there is no need to do
- // normalization.
- if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
- result[0] = XYZ_In[0];
- result[1] = XYZ_In[1];
- result[2] = XYZ_In[2];
- return;
- }
- var LMS = result;
- matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
- var LMS_Flat = tempNormalizeMatrix;
- convertToFlat(sourceWhitePoint, LMS, LMS_Flat);
- matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result);
- }
- function normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
- var LMS = result;
- matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
- var LMS_D65 = tempNormalizeMatrix;
- convertToD65(sourceWhitePoint, LMS, LMS_D65);
- matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result);
- }
- function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) {
- // A, B and C represent a red, green and blue components of a calibrated
- // rgb space.
- var A = adjustToRange(0, 1, src[srcOffset] * scale);
- var B = adjustToRange(0, 1, src[srcOffset + 1] * scale);
- var C = adjustToRange(0, 1, src[srcOffset + 2] * scale);
- // A <---> AGR in the spec
- // B <---> BGG in the spec
- // C <---> CGB in the spec
- var AGR = Math.pow(A, cs.GR);
- var BGG = Math.pow(B, cs.GG);
- var CGB = Math.pow(C, cs.GB);
- // Computes intermediate variables L, M, N as per spec.
- // To decode X, Y, Z values map L, M, N directly to them.
- var X = cs.MXA * AGR + cs.MXB * BGG + cs.MXC * CGB;
- var Y = cs.MYA * AGR + cs.MYB * BGG + cs.MYC * CGB;
- var Z = cs.MZA * AGR + cs.MZB * BGG + cs.MZC * CGB;
- // The following calculations are based on this document:
- // http://www.adobe.com/content/dam/Adobe/en/devnet/photoshop/sdk/
- // AdobeBPC.pdf.
- var XYZ = tempConvertMatrix1;
- XYZ[0] = X;
- XYZ[1] = Y;
- XYZ[2] = Z;
- var XYZ_Flat = tempConvertMatrix2;
- normalizeWhitePointToFlat(cs.whitePoint, XYZ, XYZ_Flat);
- var XYZ_Black = tempConvertMatrix1;
- compensateBlackPoint(cs.blackPoint, XYZ_Flat, XYZ_Black);
- var XYZ_D65 = tempConvertMatrix2;
- normalizeWhitePointToD65(FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65);
- var SRGB = tempConvertMatrix1;
- matrixProduct(SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
- var sR = sRGBTransferFunction(SRGB[0]);
- var sG = sRGBTransferFunction(SRGB[1]);
- var sB = sRGBTransferFunction(SRGB[2]);
- // Convert the values to rgb range [0, 255].
- dest[destOffset] = Math.round(sR * 255);
- dest[destOffset + 1] = Math.round(sG * 255);
- dest[destOffset + 2] = Math.round(sB * 255);
- }
- CalRGBCS.prototype = {
- getRgb: function CalRGBCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- this.getRgbItem(src, srcOffset, rgb, 0);
- return rgb;
- },
- getRgbItem: function CalRGBCS_getRgbItem(src, srcOffset, dest, destOffset) {
- convertToRgb(this, src, srcOffset, dest, destOffset, 1);
- },
- getRgbBuffer: function CalRGBCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var scale = 1 / ((1 << bits) - 1);
- for (var i = 0; i < count; ++i) {
- convertToRgb(this, src, srcOffset, dest, destOffset, scale);
- srcOffset += 3;
- destOffset += 3 + alpha01;
- }
- },
- getOutputLength: function CalRGBCS_getOutputLength(inputLength, alpha01) {
- return inputLength * (3 + alpha01) / 3 | 0;
- },
- isPassthrough: ColorSpace.prototype.isPassthrough,
- fillRgb: ColorSpace.prototype.fillRgb,
- isDefaultDecode: function CalRGBCS_isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- },
- usesZeroToOneRange: true
- };
- return CalRGBCS;
- }();
- //
- // LabCS: Based on "PDF Reference, Sixth Ed", p.250
- //
- var LabCS = function LabCSClosure() {
- function LabCS(whitePoint, blackPoint, range) {
- this.name = 'Lab';
- this.numComps = 3;
- this.defaultColor = new Float32Array([
- 0,
- 0,
- 0
- ]);
- if (!whitePoint) {
- error('WhitePoint missing - required for color space Lab');
- }
- blackPoint = blackPoint || [
- 0,
- 0,
- 0
- ];
- range = range || [
- -100,
- 100,
- -100,
- 100
- ];
- // Translate args to spec variables
- this.XW = whitePoint[0];
- this.YW = whitePoint[1];
- this.ZW = whitePoint[2];
- this.amin = range[0];
- this.amax = range[1];
- this.bmin = range[2];
- this.bmax = range[3];
- // These are here just for completeness - the spec doesn't offer any
- // formulas that use BlackPoint in Lab
- this.XB = blackPoint[0];
- this.YB = blackPoint[1];
- this.ZB = blackPoint[2];
- // Validate vars as per spec
- if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
- error('Invalid WhitePoint components, no fallback available');
- }
- if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
- info('Invalid BlackPoint, falling back to default');
- this.XB = this.YB = this.ZB = 0;
- }
- if (this.amin > this.amax || this.bmin > this.bmax) {
- info('Invalid Range, falling back to defaults');
- this.amin = -100;
- this.amax = 100;
- this.bmin = -100;
- this.bmax = 100;
- }
- }
- // Function g(x) from spec
- function fn_g(x) {
- if (x >= 6 / 29) {
- return x * x * x;
- } else {
- return 108 / 841 * (x - 4 / 29);
- }
- }
- function decode(value, high1, low2, high2) {
- return low2 + value * (high2 - low2) / high1;
- }
- // If decoding is needed maxVal should be 2^bits per component - 1.
- function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) {
- // XXX: Lab input is in the range of [0, 100], [amin, amax], [bmin, bmax]
- // not the usual [0, 1]. If a command like setFillColor is used the src
- // values will already be within the correct range. However, if we are
- // converting an image we have to map the values to the correct range given
- // above.
- // Ls,as,bs <---> L*,a*,b* in the spec
- var Ls = src[srcOffset];
- var as = src[srcOffset + 1];
- var bs = src[srcOffset + 2];
- if (maxVal !== false) {
- Ls = decode(Ls, maxVal, 0, 100);
- as = decode(as, maxVal, cs.amin, cs.amax);
- bs = decode(bs, maxVal, cs.bmin, cs.bmax);
- }
- // Adjust limits of 'as' and 'bs'
- as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as;
- bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs;
- // Computes intermediate variables X,Y,Z as per spec
- var M = (Ls + 16) / 116;
- var L = M + as / 500;
- var N = M - bs / 200;
- var X = cs.XW * fn_g(L);
- var Y = cs.YW * fn_g(M);
- var Z = cs.ZW * fn_g(N);
- var r, g, b;
- // Using different conversions for D50 and D65 white points,
- // per http://www.color.org/srgb.pdf
- if (cs.ZW < 1) {
- // Assuming D50 (X=0.9642, Y=1.00, Z=0.8249)
- r = X * 3.1339 + Y * -1.6170 + Z * -0.4906;
- g = X * -0.9785 + Y * 1.9160 + Z * 0.0333;
- b = X * 0.0720 + Y * -0.2290 + Z * 1.4057;
- } else {
- // Assuming D65 (X=0.9505, Y=1.00, Z=1.0888)
- r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
- g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
- b = X * 0.0557 + Y * -0.2040 + Z * 1.0570;
- }
- // clamp color values to [0,1] range then convert to [0,255] range.
- dest[destOffset] = r <= 0 ? 0 : r >= 1 ? 255 : Math.sqrt(r) * 255 | 0;
- dest[destOffset + 1] = g <= 0 ? 0 : g >= 1 ? 255 : Math.sqrt(g) * 255 | 0;
- dest[destOffset + 2] = b <= 0 ? 0 : b >= 1 ? 255 : Math.sqrt(b) * 255 | 0;
- }
- LabCS.prototype = {
- getRgb: ColorSpace.prototype.getRgb,
- getRgbItem: function LabCS_getRgbItem(src, srcOffset, dest, destOffset) {
- convertToRgb(this, src, srcOffset, false, dest, destOffset);
- },
- getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var maxVal = (1 << bits) - 1;
- for (var i = 0; i < count; i++) {
- convertToRgb(this, src, srcOffset, maxVal, dest, destOffset);
- srcOffset += 3;
- destOffset += 3 + alpha01;
- }
- },
- getOutputLength: function LabCS_getOutputLength(inputLength, alpha01) {
- return inputLength * (3 + alpha01) / 3 | 0;
- },
- isPassthrough: ColorSpace.prototype.isPassthrough,
- fillRgb: ColorSpace.prototype.fillRgb,
- isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) {
- // XXX: Decoding is handled with the lab conversion because of the strange
- // ranges that are used.
- return true;
- },
- usesZeroToOneRange: false
- };
- return LabCS;
- }();
- exports.ColorSpace = ColorSpace;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreImage = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreColorSpace, root.pdfjsCoreStream, root.pdfjsCoreJpx);
- }(this, function (exports, sharedUtil, corePrimitives, coreColorSpace, coreStream, coreJpx) {
- var ImageKind = sharedUtil.ImageKind;
- var assert = sharedUtil.assert;
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var isArray = sharedUtil.isArray;
- var warn = sharedUtil.warn;
- var Name = corePrimitives.Name;
- var isStream = corePrimitives.isStream;
- var ColorSpace = coreColorSpace.ColorSpace;
- var DecodeStream = coreStream.DecodeStream;
- var JpegStream = coreStream.JpegStream;
- var JpxImage = coreJpx.JpxImage;
- var PDFImage = function PDFImageClosure() {
- /**
- * Decodes the image using native decoder if possible. Resolves the promise
- * when the image data is ready.
- */
- function handleImageData(image, nativeDecoder) {
- if (nativeDecoder && nativeDecoder.canDecode(image)) {
- return nativeDecoder.decode(image);
- } else {
- return Promise.resolve(image);
- }
- }
- /**
- * Decode and clamp a value. The formula is different from the spec because we
- * don't decode to float range [0,1], we decode it in the [0,max] range.
- */
- function decodeAndClamp(value, addend, coefficient, max) {
- value = addend + value * coefficient;
- // Clamp the value to the range
- return value < 0 ? 0 : value > max ? max : value;
- }
- /**
- * Resizes an image mask with 1 component.
- * @param {TypedArray} src - The source buffer.
- * @param {Number} bpc - Number of bits per component.
- * @param {Number} w1 - Original width.
- * @param {Number} h1 - Original height.
- * @param {Number} w2 - New width.
- * @param {Number} h2 - New height.
- * @returns {TypedArray} The resized image mask buffer.
- */
- function resizeImageMask(src, bpc, w1, h1, w2, h2) {
- var length = w2 * h2;
- var dest = bpc <= 8 ? new Uint8Array(length) : bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
- var xRatio = w1 / w2;
- var yRatio = h1 / h2;
- var i, j, py, newIndex = 0, oldIndex;
- var xScaled = new Uint16Array(w2);
- var w1Scanline = w1;
- for (i = 0; i < w2; i++) {
- xScaled[i] = Math.floor(i * xRatio);
- }
- for (i = 0; i < h2; i++) {
- py = Math.floor(i * yRatio) * w1Scanline;
- for (j = 0; j < w2; j++) {
- oldIndex = py + xScaled[j];
- dest[newIndex++] = src[oldIndex];
- }
- }
- return dest;
- }
- function PDFImage(xref, res, image, inline, smask, mask, isMask) {
- this.image = image;
- var dict = image.dict;
- if (dict.has('Filter')) {
- var filter = dict.get('Filter').name;
- if (filter === 'JPXDecode') {
- var jpxImage = new JpxImage();
- jpxImage.parseImageProperties(image.stream);
- image.stream.reset();
- image.bitsPerComponent = jpxImage.bitsPerComponent;
- image.numComps = jpxImage.componentsCount;
- } else if (filter === 'JBIG2Decode') {
- image.bitsPerComponent = 1;
- image.numComps = 1;
- }
- }
- // TODO cache rendered images?
- this.width = dict.get('Width', 'W');
- this.height = dict.get('Height', 'H');
- if (this.width < 1 || this.height < 1) {
- error('Invalid image width: ' + this.width + ' or height: ' + this.height);
- }
- this.interpolate = dict.get('Interpolate', 'I') || false;
- this.imageMask = dict.get('ImageMask', 'IM') || false;
- this.matte = dict.get('Matte') || false;
- var bitsPerComponent = image.bitsPerComponent;
- if (!bitsPerComponent) {
- bitsPerComponent = dict.get('BitsPerComponent', 'BPC');
- if (!bitsPerComponent) {
- if (this.imageMask) {
- bitsPerComponent = 1;
- } else {
- error('Bits per component missing in image: ' + this.imageMask);
- }
- }
- }
- this.bpc = bitsPerComponent;
- if (!this.imageMask) {
- var colorSpace = dict.get('ColorSpace', 'CS');
- if (!colorSpace) {
- info('JPX images (which do not require color spaces)');
- switch (image.numComps) {
- case 1:
- colorSpace = Name.get('DeviceGray');
- break;
- case 3:
- colorSpace = Name.get('DeviceRGB');
- break;
- case 4:
- colorSpace = Name.get('DeviceCMYK');
- break;
- default:
- error('JPX images with ' + this.numComps + ' color components not supported.');
- }
- }
- this.colorSpace = ColorSpace.parse(colorSpace, xref, res);
- this.numComps = this.colorSpace.numComps;
- }
- this.decode = dict.getArray('Decode', 'D');
- this.needsDecode = false;
- if (this.decode && (this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode) || isMask && !ColorSpace.isDefaultDecode(this.decode, 1))) {
- this.needsDecode = true;
- // Do some preprocessing to avoid more math.
- var max = (1 << bitsPerComponent) - 1;
- this.decodeCoefficients = [];
- this.decodeAddends = [];
- for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) {
- var dmin = this.decode[i];
- var dmax = this.decode[i + 1];
- this.decodeCoefficients[j] = dmax - dmin;
- this.decodeAddends[j] = max * dmin;
- }
- }
- if (smask) {
- this.smask = new PDFImage(xref, res, smask, false);
- } else if (mask) {
- if (isStream(mask)) {
- var maskDict = mask.dict, imageMask = maskDict.get('ImageMask', 'IM');
- if (!imageMask) {
- warn('Ignoring /Mask in image without /ImageMask.');
- } else {
- this.mask = new PDFImage(xref, res, mask, false, null, null, true);
- }
- } else {
- // Color key mask (just an array).
- this.mask = mask;
- }
- }
- }
- /**
- * Handles processing of image data and returns the Promise that is resolved
- * with a PDFImage when the image is ready to be used.
- */
- PDFImage.buildImage = function PDFImage_buildImage(handler, xref, res, image, inline, nativeDecoder) {
- var imagePromise = handleImageData(image, nativeDecoder);
- var smaskPromise;
- var maskPromise;
- var smask = image.dict.get('SMask');
- var mask = image.dict.get('Mask');
- if (smask) {
- smaskPromise = handleImageData(smask, nativeDecoder);
- maskPromise = Promise.resolve(null);
- } else {
- smaskPromise = Promise.resolve(null);
- if (mask) {
- if (isStream(mask)) {
- maskPromise = handleImageData(mask, nativeDecoder);
- } else if (isArray(mask)) {
- maskPromise = Promise.resolve(mask);
- } else {
- warn('Unsupported mask format.');
- maskPromise = Promise.resolve(null);
- }
- } else {
- maskPromise = Promise.resolve(null);
- }
- }
- return Promise.all([
- imagePromise,
- smaskPromise,
- maskPromise
- ]).then(function (results) {
- var imageData = results[0];
- var smaskData = results[1];
- var maskData = results[2];
- return new PDFImage(xref, res, imageData, inline, smaskData, maskData);
- });
- };
- PDFImage.createMask = function PDFImage_createMask(imgArray, width, height, imageIsFromDecodeStream, inverseDecode) {
- // |imgArray| might not contain full data for every pixel of the mask, so
- // we need to distinguish between |computedLength| and |actualLength|.
- // In particular, if inverseDecode is true, then the array we return must
- // have a length of |computedLength|.
- var computedLength = (width + 7 >> 3) * height;
- var actualLength = imgArray.byteLength;
- var haveFullData = computedLength === actualLength;
- var data, i;
- if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) {
- // imgArray came from a DecodeStream and its data is in an appropriate
- // form, so we can just transfer it.
- data = imgArray;
- } else if (!inverseDecode) {
- data = new Uint8Array(actualLength);
- data.set(imgArray);
- } else {
- data = new Uint8Array(computedLength);
- data.set(imgArray);
- for (i = actualLength; i < computedLength; i++) {
- data[i] = 0xff;
- }
- }
- // If necessary, invert the original mask data (but not any extra we might
- // have added above). It's safe to modify the array -- whether it's the
- // original or a copy, we're about to transfer it anyway, so nothing else
- // in this thread can be relying on its contents.
- if (inverseDecode) {
- for (i = 0; i < actualLength; i++) {
- data[i] = ~data[i];
- }
- }
- return {
- data: data,
- width: width,
- height: height
- };
- };
- PDFImage.prototype = {
- get drawWidth() {
- return Math.max(this.width, this.smask && this.smask.width || 0, this.mask && this.mask.width || 0);
- },
- get drawHeight() {
- return Math.max(this.height, this.smask && this.smask.height || 0, this.mask && this.mask.height || 0);
- },
- decodeBuffer: function PDFImage_decodeBuffer(buffer) {
- var bpc = this.bpc;
- var numComps = this.numComps;
- var decodeAddends = this.decodeAddends;
- var decodeCoefficients = this.decodeCoefficients;
- var max = (1 << bpc) - 1;
- var i, ii;
- if (bpc === 1) {
- // If the buffer needed decode that means it just needs to be inverted.
- for (i = 0, ii = buffer.length; i < ii; i++) {
- buffer[i] = +!buffer[i];
- }
- return;
- }
- var index = 0;
- for (i = 0, ii = this.width * this.height; i < ii; i++) {
- for (var j = 0; j < numComps; j++) {
- buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], decodeCoefficients[j], max);
- index++;
- }
- }
- },
- getComponents: function PDFImage_getComponents(buffer) {
- var bpc = this.bpc;
- // This image doesn't require any extra work.
- if (bpc === 8) {
- return buffer;
- }
- var width = this.width;
- var height = this.height;
- var numComps = this.numComps;
- var length = width * height * numComps;
- var bufferPos = 0;
- var output = bpc <= 8 ? new Uint8Array(length) : bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
- var rowComps = width * numComps;
- var max = (1 << bpc) - 1;
- var i = 0, ii, buf;
- if (bpc === 1) {
- // Optimization for reading 1 bpc images.
- var mask, loop1End, loop2End;
- for (var j = 0; j < height; j++) {
- loop1End = i + (rowComps & ~7);
- loop2End = i + rowComps;
- // unroll loop for all full bytes
- while (i < loop1End) {
- buf = buffer[bufferPos++];
- output[i] = buf >> 7 & 1;
- output[i + 1] = buf >> 6 & 1;
- output[i + 2] = buf >> 5 & 1;
- output[i + 3] = buf >> 4 & 1;
- output[i + 4] = buf >> 3 & 1;
- output[i + 5] = buf >> 2 & 1;
- output[i + 6] = buf >> 1 & 1;
- output[i + 7] = buf & 1;
- i += 8;
- }
- // handle remaining bits
- if (i < loop2End) {
- buf = buffer[bufferPos++];
- mask = 128;
- while (i < loop2End) {
- output[i++] = +!!(buf & mask);
- mask >>= 1;
- }
- }
- }
- } else {
- // The general case that handles all other bpc values.
- var bits = 0;
- buf = 0;
- for (i = 0, ii = length; i < ii; ++i) {
- if (i % rowComps === 0) {
- buf = 0;
- bits = 0;
- }
- while (bits < bpc) {
- buf = buf << 8 | buffer[bufferPos++];
- bits += 8;
- }
- var remainingBits = bits - bpc;
- var value = buf >> remainingBits;
- output[i] = value < 0 ? 0 : value > max ? max : value;
- buf = buf & (1 << remainingBits) - 1;
- bits = remainingBits;
- }
- }
- return output;
- },
- fillOpacity: function PDFImage_fillOpacity(rgbaBuf, width, height, actualHeight, image) {
- var smask = this.smask;
- var mask = this.mask;
- var alphaBuf, sw, sh, i, ii, j;
- if (smask) {
- sw = smask.width;
- sh = smask.height;
- alphaBuf = new Uint8Array(sw * sh);
- smask.fillGrayBuffer(alphaBuf);
- if (sw !== width || sh !== height) {
- alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh, width, height);
- }
- } else if (mask) {
- if (mask instanceof PDFImage) {
- sw = mask.width;
- sh = mask.height;
- alphaBuf = new Uint8Array(sw * sh);
- mask.numComps = 1;
- mask.fillGrayBuffer(alphaBuf);
- // Need to invert values in rgbaBuf
- for (i = 0, ii = sw * sh; i < ii; ++i) {
- alphaBuf[i] = 255 - alphaBuf[i];
- }
- if (sw !== width || sh !== height) {
- alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh, width, height);
- }
- } else if (isArray(mask)) {
- // Color key mask: if any of the components are outside the range
- // then they should be painted.
- alphaBuf = new Uint8Array(width * height);
- var numComps = this.numComps;
- for (i = 0, ii = width * height; i < ii; ++i) {
- var opacity = 0;
- var imageOffset = i * numComps;
- for (j = 0; j < numComps; ++j) {
- var color = image[imageOffset + j];
- var maskOffset = j * 2;
- if (color < mask[maskOffset] || color > mask[maskOffset + 1]) {
- opacity = 255;
- break;
- }
- }
- alphaBuf[i] = opacity;
- }
- } else {
- error('Unknown mask format.');
- }
- }
- if (alphaBuf) {
- for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
- rgbaBuf[j] = alphaBuf[i];
- }
- } else {
- // No mask.
- for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
- rgbaBuf[j] = 255;
- }
- }
- },
- undoPreblend: function PDFImage_undoPreblend(buffer, width, height) {
- var matte = this.smask && this.smask.matte;
- if (!matte) {
- return;
- }
- var matteRgb = this.colorSpace.getRgb(matte, 0);
- var matteR = matteRgb[0];
- var matteG = matteRgb[1];
- var matteB = matteRgb[2];
- var length = width * height * 4;
- var r, g, b;
- for (var i = 0; i < length; i += 4) {
- var alpha = buffer[i + 3];
- if (alpha === 0) {
- // according formula we have to get Infinity in all components
- // making it white (typical paper color) should be okay
- buffer[i] = 255;
- buffer[i + 1] = 255;
- buffer[i + 2] = 255;
- continue;
- }
- var k = 255 / alpha;
- r = (buffer[i] - matteR) * k + matteR;
- g = (buffer[i + 1] - matteG) * k + matteG;
- b = (buffer[i + 2] - matteB) * k + matteB;
- buffer[i] = r <= 0 ? 0 : r >= 255 ? 255 : r | 0;
- buffer[i + 1] = g <= 0 ? 0 : g >= 255 ? 255 : g | 0;
- buffer[i + 2] = b <= 0 ? 0 : b >= 255 ? 255 : b | 0;
- }
- },
- createImageData: function PDFImage_createImageData(forceRGBA) {
- var drawWidth = this.drawWidth;
- var drawHeight = this.drawHeight;
- var imgData = {
- // other fields are filled in below
- width: drawWidth,
- height: drawHeight
- };
- var numComps = this.numComps;
- var originalWidth = this.width;
- var originalHeight = this.height;
- var bpc = this.bpc;
- // Rows start at byte boundary.
- var rowBytes = originalWidth * numComps * bpc + 7 >> 3;
- var imgArray;
- if (!forceRGBA) {
- // If it is a 1-bit-per-pixel grayscale (i.e. black-and-white) image
- // without any complications, we pass a same-sized copy to the main
- // thread rather than expanding by 32x to RGBA form. This saves *lots*
- // of memory for many scanned documents. It's also much faster.
- //
- // Similarly, if it is a 24-bit-per pixel RGB image without any
- // complications, we avoid expanding by 1.333x to RGBA form.
- var kind;
- if (this.colorSpace.name === 'DeviceGray' && bpc === 1) {
- kind = ImageKind.GRAYSCALE_1BPP;
- } else if (this.colorSpace.name === 'DeviceRGB' && bpc === 8 && !this.needsDecode) {
- kind = ImageKind.RGB_24BPP;
- }
- if (kind && !this.smask && !this.mask && drawWidth === originalWidth && drawHeight === originalHeight) {
- imgData.kind = kind;
- imgArray = this.getImageBytes(originalHeight * rowBytes);
- // If imgArray came from a DecodeStream, we're safe to transfer it
- // (and thus detach its underlying buffer) because it will constitute
- // the entire DecodeStream's data. But if it came from a Stream, we
- // need to copy it because it'll only be a portion of the Stream's
- // data, and the rest will be read later on.
- if (this.image instanceof DecodeStream) {
- imgData.data = imgArray;
- } else {
- var newArray = new Uint8Array(imgArray.length);
- newArray.set(imgArray);
- imgData.data = newArray;
- }
- if (this.needsDecode) {
- // Invert the buffer (which must be grayscale if we reached here).
- assert(kind === ImageKind.GRAYSCALE_1BPP);
- var buffer = imgData.data;
- for (var i = 0, ii = buffer.length; i < ii; i++) {
- buffer[i] ^= 0xff;
- }
- }
- return imgData;
- }
- if (this.image instanceof JpegStream && !this.smask && !this.mask && (this.colorSpace.name === 'DeviceGray' || this.colorSpace.name === 'DeviceRGB' || this.colorSpace.name === 'DeviceCMYK')) {
- imgData.kind = ImageKind.RGB_24BPP;
- imgData.data = this.getImageBytes(originalHeight * rowBytes, drawWidth, drawHeight, true);
- return imgData;
- }
- }
- imgArray = this.getImageBytes(originalHeight * rowBytes);
- // imgArray can be incomplete (e.g. after CCITT fax encoding).
- var actualHeight = 0 | imgArray.length / rowBytes * drawHeight / originalHeight;
- var comps = this.getComponents(imgArray);
- // If opacity data is present, use RGBA_32BPP form. Otherwise, use the
- // more compact RGB_24BPP form if allowable.
- var alpha01, maybeUndoPreblend;
- if (!forceRGBA && !this.smask && !this.mask) {
- imgData.kind = ImageKind.RGB_24BPP;
- imgData.data = new Uint8Array(drawWidth * drawHeight * 3);
- alpha01 = 0;
- maybeUndoPreblend = false;
- } else {
- imgData.kind = ImageKind.RGBA_32BPP;
- imgData.data = new Uint8Array(drawWidth * drawHeight * 4);
- alpha01 = 1;
- maybeUndoPreblend = true;
- // Color key masking (opacity) must be performed before decoding.
- this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight, comps);
- }
- if (this.needsDecode) {
- this.decodeBuffer(comps);
- }
- this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight, drawWidth, drawHeight, actualHeight, bpc, comps, alpha01);
- if (maybeUndoPreblend) {
- this.undoPreblend(imgData.data, drawWidth, actualHeight);
- }
- return imgData;
- },
- fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) {
- var numComps = this.numComps;
- if (numComps !== 1) {
- error('Reading gray scale from a color image: ' + numComps);
- }
- var width = this.width;
- var height = this.height;
- var bpc = this.bpc;
- // rows start at byte boundary
- var rowBytes = width * numComps * bpc + 7 >> 3;
- var imgArray = this.getImageBytes(height * rowBytes);
- var comps = this.getComponents(imgArray);
- var i, length;
- if (bpc === 1) {
- // inline decoding (= inversion) for 1 bpc images
- length = width * height;
- if (this.needsDecode) {
- // invert and scale to {0, 255}
- for (i = 0; i < length; ++i) {
- buffer[i] = comps[i] - 1 & 255;
- }
- } else {
- // scale to {0, 255}
- for (i = 0; i < length; ++i) {
- buffer[i] = -comps[i] & 255;
- }
- }
- return;
- }
- if (this.needsDecode) {
- this.decodeBuffer(comps);
- }
- length = width * height;
- // we aren't using a colorspace so we need to scale the value
- var scale = 255 / ((1 << bpc) - 1);
- for (i = 0; i < length; ++i) {
- buffer[i] = scale * comps[i] | 0;
- }
- },
- getImageBytes: function PDFImage_getImageBytes(length, drawWidth, drawHeight, forceRGB) {
- this.image.reset();
- this.image.drawWidth = drawWidth || this.width;
- this.image.drawHeight = drawHeight || this.height;
- this.image.forceRGB = !!forceRGB;
- return this.image.getBytes(length);
- }
- };
- return PDFImage;
- }();
- exports.PDFImage = PDFImage;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreObj = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreCrypto, root.pdfjsCoreParser, root.pdfjsCoreChunkedStream, root.pdfjsCoreColorSpace);
- }(this, function (exports, sharedUtil, corePrimitives, coreCrypto, coreParser, coreChunkedStream, coreColorSpace) {
- var InvalidPDFException = sharedUtil.InvalidPDFException;
- var MissingDataException = sharedUtil.MissingDataException;
- var XRefParseException = sharedUtil.XRefParseException;
- var assert = sharedUtil.assert;
- var bytesToString = sharedUtil.bytesToString;
- var createPromiseCapability = sharedUtil.createPromiseCapability;
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var isArray = sharedUtil.isArray;
- var isBool = sharedUtil.isBool;
- var isInt = sharedUtil.isInt;
- var isString = sharedUtil.isString;
- var shadow = sharedUtil.shadow;
- var stringToPDFString = sharedUtil.stringToPDFString;
- var stringToUTF8String = sharedUtil.stringToUTF8String;
- var warn = sharedUtil.warn;
- var createValidAbsoluteUrl = sharedUtil.createValidAbsoluteUrl;
- var Util = sharedUtil.Util;
- var Ref = corePrimitives.Ref;
- var RefSet = corePrimitives.RefSet;
- var RefSetCache = corePrimitives.RefSetCache;
- var isName = corePrimitives.isName;
- var isCmd = corePrimitives.isCmd;
- var isDict = corePrimitives.isDict;
- var isRef = corePrimitives.isRef;
- var isRefsEqual = corePrimitives.isRefsEqual;
- var isStream = corePrimitives.isStream;
- var CipherTransformFactory = coreCrypto.CipherTransformFactory;
- var Lexer = coreParser.Lexer;
- var Parser = coreParser.Parser;
- var ChunkedStream = coreChunkedStream.ChunkedStream;
- var ColorSpace = coreColorSpace.ColorSpace;
- var Catalog = function CatalogClosure() {
- function Catalog(pdfManager, xref, pageFactory) {
- this.pdfManager = pdfManager;
- this.xref = xref;
- this.catDict = xref.getCatalogObj();
- this.fontCache = new RefSetCache();
- assert(isDict(this.catDict), 'catalog object is not a dictionary');
- // TODO refactor to move getPage() to the PDFDocument.
- this.pageFactory = pageFactory;
- this.pagePromises = [];
- }
- Catalog.prototype = {
- get metadata() {
- var streamRef = this.catDict.getRaw('Metadata');
- if (!isRef(streamRef)) {
- return shadow(this, 'metadata', null);
- }
- var encryptMetadata = !this.xref.encrypt ? false : this.xref.encrypt.encryptMetadata;
- var stream = this.xref.fetch(streamRef, !encryptMetadata);
- var metadata;
- if (stream && isDict(stream.dict)) {
- var type = stream.dict.get('Type');
- var subtype = stream.dict.get('Subtype');
- if (isName(type, 'Metadata') && isName(subtype, 'XML')) {
- // XXX: This should examine the charset the XML document defines,
- // however since there are currently no real means to decode
- // arbitrary charsets, let's just hope that the author of the PDF
- // was reasonable enough to stick with the XML default charset,
- // which is UTF-8.
- try {
- metadata = stringToUTF8String(bytesToString(stream.getBytes()));
- } catch (e) {
- info('Skipping invalid metadata.');
- }
- }
- }
- return shadow(this, 'metadata', metadata);
- },
- get toplevelPagesDict() {
- var pagesObj = this.catDict.get('Pages');
- assert(isDict(pagesObj), 'invalid top-level pages dictionary');
- // shadow the prototype getter
- return shadow(this, 'toplevelPagesDict', pagesObj);
- },
- get documentOutline() {
- var obj = null;
- try {
- obj = this.readDocumentOutline();
- } catch (ex) {
- if (ex instanceof MissingDataException) {
- throw ex;
- }
- warn('Unable to read document outline');
- }
- return shadow(this, 'documentOutline', obj);
- },
- readDocumentOutline: function Catalog_readDocumentOutline() {
- var obj = this.catDict.get('Outlines');
- if (!isDict(obj)) {
- return null;
- }
- obj = obj.getRaw('First');
- if (!isRef(obj)) {
- return null;
- }
- var root = { items: [] };
- var queue = [{
- obj: obj,
- parent: root
- }];
- // To avoid recursion, keep track of the already processed items.
- var processed = new RefSet();
- processed.put(obj);
- var xref = this.xref, blackColor = new Uint8Array(3);
- while (queue.length > 0) {
- var i = queue.shift();
- var outlineDict = xref.fetchIfRef(i.obj);
- if (outlineDict === null) {
- continue;
- }
- assert(outlineDict.has('Title'), 'Invalid outline item');
- var data = {
- url: null,
- dest: null
- };
- Catalog.parseDestDictionary({
- destDict: outlineDict,
- resultObj: data,
- docBaseUrl: this.pdfManager.docBaseUrl
- });
- var title = outlineDict.get('Title');
- var flags = outlineDict.get('F') || 0;
- var color = outlineDict.getArray('C'), rgbColor = blackColor;
- // We only need to parse the color when it's valid, and non-default.
- if (isArray(color) && color.length === 3 && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) {
- rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0);
- }
- var outlineItem = {
- dest: data.dest,
- url: data.url,
- unsafeUrl: data.unsafeUrl,
- newWindow: data.newWindow,
- title: stringToPDFString(title),
- color: rgbColor,
- count: outlineDict.get('Count'),
- bold: !!(flags & 2),
- italic: !!(flags & 1),
- items: []
- };
- i.parent.items.push(outlineItem);
- obj = outlineDict.getRaw('First');
- if (isRef(obj) && !processed.has(obj)) {
- queue.push({
- obj: obj,
- parent: outlineItem
- });
- processed.put(obj);
- }
- obj = outlineDict.getRaw('Next');
- if (isRef(obj) && !processed.has(obj)) {
- queue.push({
- obj: obj,
- parent: i.parent
- });
- processed.put(obj);
- }
- }
- return root.items.length > 0 ? root.items : null;
- },
- get numPages() {
- var obj = this.toplevelPagesDict.get('Count');
- assert(isInt(obj), 'page count in top level pages object is not an integer');
- // shadow the prototype getter
- return shadow(this, 'num', obj);
- },
- get destinations() {
- function fetchDestination(dest) {
- return isDict(dest) ? dest.get('D') : dest;
- }
- var xref = this.xref;
- var dests = {}, nameTreeRef, nameDictionaryRef;
- var obj = this.catDict.get('Names');
- if (obj && obj.has('Dests')) {
- nameTreeRef = obj.getRaw('Dests');
- } else if (this.catDict.has('Dests')) {
- nameDictionaryRef = this.catDict.get('Dests');
- }
- if (nameDictionaryRef) {
- // reading simple destination dictionary
- obj = nameDictionaryRef;
- obj.forEach(function catalogForEach(key, value) {
- if (!value) {
- return;
- }
- dests[key] = fetchDestination(value);
- });
- }
- if (nameTreeRef) {
- var nameTree = new NameTree(nameTreeRef, xref);
- var names = nameTree.getAll();
- for (var name in names) {
- dests[name] = fetchDestination(names[name]);
- }
- }
- return shadow(this, 'destinations', dests);
- },
- getDestination: function Catalog_getDestination(destinationId) {
- function fetchDestination(dest) {
- return isDict(dest) ? dest.get('D') : dest;
- }
- var xref = this.xref;
- var dest = null, nameTreeRef, nameDictionaryRef;
- var obj = this.catDict.get('Names');
- if (obj && obj.has('Dests')) {
- nameTreeRef = obj.getRaw('Dests');
- } else if (this.catDict.has('Dests')) {
- nameDictionaryRef = this.catDict.get('Dests');
- }
- if (nameDictionaryRef) {
- // Simple destination dictionary.
- var value = nameDictionaryRef.get(destinationId);
- if (value) {
- dest = fetchDestination(value);
- }
- }
- if (nameTreeRef) {
- var nameTree = new NameTree(nameTreeRef, xref);
- dest = fetchDestination(nameTree.get(destinationId));
- }
- return dest;
- },
- get pageLabels() {
- var obj = null;
- try {
- obj = this.readPageLabels();
- } catch (ex) {
- if (ex instanceof MissingDataException) {
- throw ex;
- }
- warn('Unable to read page labels.');
- }
- return shadow(this, 'pageLabels', obj);
- },
- readPageLabels: function Catalog_readPageLabels() {
- var obj = this.catDict.getRaw('PageLabels');
- if (!obj) {
- return null;
- }
- var pageLabels = new Array(this.numPages);
- var style = null;
- var prefix = '';
- var numberTree = new NumberTree(obj, this.xref);
- var nums = numberTree.getAll();
- var currentLabel = '', currentIndex = 1;
- for (var i = 0, ii = this.numPages; i < ii; i++) {
- if (i in nums) {
- var labelDict = nums[i];
- assert(isDict(labelDict), 'The PageLabel is not a dictionary.');
- var type = labelDict.get('Type');
- assert(!type || isName(type, 'PageLabel'), 'Invalid type in PageLabel dictionary.');
- var s = labelDict.get('S');
- assert(!s || isName(s), 'Invalid style in PageLabel dictionary.');
- style = s ? s.name : null;
- var p = labelDict.get('P');
- assert(!p || isString(p), 'Invalid prefix in PageLabel dictionary.');
- prefix = p ? stringToPDFString(p) : '';
- var st = labelDict.get('St');
- assert(!st || isInt(st) && st >= 1, 'Invalid start in PageLabel dictionary.');
- currentIndex = st || 1;
- }
- switch (style) {
- case 'D':
- currentLabel = currentIndex;
- break;
- case 'R':
- case 'r':
- currentLabel = Util.toRoman(currentIndex, style === 'r');
- break;
- case 'A':
- case 'a':
- var LIMIT = 26;
- // Use only the characters A--Z, or a--z.
- var A_UPPER_CASE = 0x41, A_LOWER_CASE = 0x61;
- var baseCharCode = style === 'a' ? A_LOWER_CASE : A_UPPER_CASE;
- var letterIndex = currentIndex - 1;
- var character = String.fromCharCode(baseCharCode + letterIndex % LIMIT);
- var charBuf = [];
- for (var j = 0, jj = letterIndex / LIMIT | 0; j <= jj; j++) {
- charBuf.push(character);
- }
- currentLabel = charBuf.join('');
- break;
- default:
- assert(!style, 'Invalid style "' + style + '" in PageLabel dictionary.');
- }
- pageLabels[i] = prefix + currentLabel;
- currentLabel = '';
- currentIndex++;
- }
- return pageLabels;
- },
- get attachments() {
- var xref = this.xref;
- var attachments = null, nameTreeRef;
- var obj = this.catDict.get('Names');
- if (obj) {
- nameTreeRef = obj.getRaw('EmbeddedFiles');
- }
- if (nameTreeRef) {
- var nameTree = new NameTree(nameTreeRef, xref);
- var names = nameTree.getAll();
- for (var name in names) {
- var fs = new FileSpec(names[name], xref);
- if (!attachments) {
- attachments = Object.create(null);
- }
- attachments[stringToPDFString(name)] = fs.serializable;
- }
- }
- return shadow(this, 'attachments', attachments);
- },
- get javaScript() {
- var xref = this.xref;
- var obj = this.catDict.get('Names');
- var javaScript = [];
- function appendIfJavaScriptDict(jsDict) {
- var type = jsDict.get('S');
- if (!isName(type, 'JavaScript')) {
- return;
- }
- var js = jsDict.get('JS');
- if (isStream(js)) {
- js = bytesToString(js.getBytes());
- } else if (!isString(js)) {
- return;
- }
- javaScript.push(stringToPDFString(js));
- }
- if (obj && obj.has('JavaScript')) {
- var nameTree = new NameTree(obj.getRaw('JavaScript'), xref);
- var names = nameTree.getAll();
- for (var name in names) {
- // We don't really use the JavaScript right now. This code is
- // defensive so we don't cause errors on document load.
- var jsDict = names[name];
- if (isDict(jsDict)) {
- appendIfJavaScriptDict(jsDict);
- }
- }
- }
- // Append OpenAction actions to javaScript array
- var openactionDict = this.catDict.get('OpenAction');
- if (isDict(openactionDict, 'Action')) {
- var actionType = openactionDict.get('S');
- if (isName(actionType, 'Named')) {
- // The named Print action is not a part of the PDF 1.7 specification,
- // but is supported by many PDF readers/writers (including Adobe's).
- var action = openactionDict.get('N');
- if (isName(action, 'Print')) {
- javaScript.push('print({});');
- }
- } else {
- appendIfJavaScriptDict(openactionDict);
- }
- }
- return shadow(this, 'javaScript', javaScript);
- },
- cleanup: function Catalog_cleanup() {
- var promises = [];
- this.fontCache.forEach(function (promise) {
- promises.push(promise);
- });
- return Promise.all(promises).then(function (translatedFonts) {
- for (var i = 0, ii = translatedFonts.length; i < ii; i++) {
- var font = translatedFonts[i].dict;
- delete font.translated;
- }
- this.fontCache.clear();
- }.bind(this));
- },
- getPage: function Catalog_getPage(pageIndex) {
- if (!(pageIndex in this.pagePromises)) {
- this.pagePromises[pageIndex] = this.getPageDict(pageIndex).then(function (a) {
- var dict = a[0];
- var ref = a[1];
- return this.pageFactory.createPage(pageIndex, dict, ref, this.fontCache);
- }.bind(this));
- }
- return this.pagePromises[pageIndex];
- },
- getPageDict: function Catalog_getPageDict(pageIndex) {
- var capability = createPromiseCapability();
- var nodesToVisit = [this.catDict.getRaw('Pages')];
- var currentPageIndex = 0;
- var xref = this.xref;
- var checkAllKids = false;
- function next() {
- while (nodesToVisit.length) {
- var currentNode = nodesToVisit.pop();
- if (isRef(currentNode)) {
- xref.fetchAsync(currentNode).then(function (obj) {
- if (isDict(obj, 'Page') || isDict(obj) && !obj.has('Kids')) {
- if (pageIndex === currentPageIndex) {
- capability.resolve([
- obj,
- currentNode
- ]);
- } else {
- currentPageIndex++;
- next();
- }
- return;
- }
- nodesToVisit.push(obj);
- next();
- }, capability.reject);
- return;
- }
- // Must be a child page dictionary.
- assert(isDict(currentNode), 'page dictionary kid reference points to wrong type of object');
- var count = currentNode.get('Count');
- // If the current node doesn't have any children, avoid getting stuck
- // in an empty node further down in the tree (see issue5644.pdf).
- if (count === 0) {
- checkAllKids = true;
- }
- // Skip nodes where the page can't be.
- if (currentPageIndex + count <= pageIndex) {
- currentPageIndex += count;
- continue;
- }
- var kids = currentNode.get('Kids');
- assert(isArray(kids), 'page dictionary kids object is not an array');
- if (!checkAllKids && count === kids.length) {
- // Nodes that don't have the page have been skipped and this is the
- // bottom of the tree which means the page requested must be a
- // descendant of this pages node. Ideally we would just resolve the
- // promise with the page ref here, but there is the case where more
- // pages nodes could link to single a page (see issue 3666 pdf). To
- // handle this push it back on the queue so if it is a pages node it
- // will be descended into.
- nodesToVisit = [kids[pageIndex - currentPageIndex]];
- currentPageIndex = pageIndex;
- continue;
- } else {
- for (var last = kids.length - 1; last >= 0; last--) {
- nodesToVisit.push(kids[last]);
- }
- }
- }
- capability.reject('Page index ' + pageIndex + ' not found.');
- }
- next();
- return capability.promise;
- },
- getPageIndex: function Catalog_getPageIndex(pageRef) {
- // The page tree nodes have the count of all the leaves below them. To get
- // how many pages are before we just have to walk up the tree and keep
- // adding the count of siblings to the left of the node.
- var xref = this.xref;
- function pagesBeforeRef(kidRef) {
- var total = 0;
- var parentRef;
- return xref.fetchAsync(kidRef).then(function (node) {
- if (isRefsEqual(kidRef, pageRef) && !isDict(node, 'Page') && !(isDict(node) && !node.has('Type') && node.has('Contents'))) {
- throw new Error('The reference does not point to a /Page Dict.');
- }
- if (!node) {
- return null;
- }
- assert(isDict(node), 'node must be a Dict.');
- parentRef = node.getRaw('Parent');
- return node.getAsync('Parent');
- }).then(function (parent) {
- if (!parent) {
- return null;
- }
- assert(isDict(parent), 'parent must be a Dict.');
- return parent.getAsync('Kids');
- }).then(function (kids) {
- if (!kids) {
- return null;
- }
- var kidPromises = [];
- var found = false;
- for (var i = 0; i < kids.length; i++) {
- var kid = kids[i];
- assert(isRef(kid), 'kid must be a Ref.');
- if (kid.num === kidRef.num) {
- found = true;
- break;
- }
- kidPromises.push(xref.fetchAsync(kid).then(function (kid) {
- if (kid.has('Count')) {
- var count = kid.get('Count');
- total += count;
- } else {
- // page leaf node
- total++;
- }
- }));
- }
- if (!found) {
- error('kid ref not found in parents kids');
- }
- return Promise.all(kidPromises).then(function () {
- return [
- total,
- parentRef
- ];
- });
- });
- }
- var total = 0;
- function next(ref) {
- return pagesBeforeRef(ref).then(function (args) {
- if (!args) {
- return total;
- }
- var count = args[0];
- var parentRef = args[1];
- total += count;
- return next(parentRef);
- });
- }
- return next(pageRef);
- }
- };
- /**
- * Helper function used to parse the contents of destination dictionaries.
- * @param {Dict} destDict - The dictionary containing the destination.
- * @param {Object} resultObj - The object where the parsed destination
- * properties will be placed.
- * @param {string} docBaseUrl - (optional) The document base URL that is used
- * when attempting to recover valid absolute URLs from relative ones.
- */
- Catalog.parseDestDictionary = function Catalog_parseDestDictionary(params) {
- // Lets URLs beginning with 'www.' default to using the 'http://' protocol.
- function addDefaultProtocolToUrl(url) {
- if (url.indexOf('www.') === 0) {
- return 'http://' + url;
- }
- return url;
- }
- // According to ISO 32000-1:2008, section 12.6.4.7, URIs should be encoded
- // in 7-bit ASCII. Some bad PDFs use UTF-8 encoding, see Bugzilla 1122280.
- function tryConvertUrlEncoding(url) {
- try {
- return stringToUTF8String(url);
- } catch (e) {
- return url;
- }
- }
- var destDict = params.destDict;
- if (!isDict(destDict)) {
- warn('Catalog_parseDestDictionary: "destDict" must be a dictionary.');
- return;
- }
- var resultObj = params.resultObj;
- if (typeof resultObj !== 'object') {
- warn('Catalog_parseDestDictionary: "resultObj" must be an object.');
- return;
- }
- var docBaseUrl = params.docBaseUrl || null;
- var action = destDict.get('A'), url, dest;
- if (isDict(action)) {
- var linkType = action.get('S').name;
- switch (linkType) {
- case 'URI':
- url = action.get('URI');
- if (isName(url)) {
- // Some bad PDFs do not put parentheses around relative URLs.
- url = '/' + url.name;
- } else if (isString(url)) {
- url = addDefaultProtocolToUrl(url);
- }
- // TODO: pdf spec mentions urls can be relative to a Base
- // entry in the dictionary.
- break;
- case 'GoTo':
- dest = action.get('D');
- break;
- case 'Launch':
- // We neither want, nor can, support arbitrary 'Launch' actions.
- // However, in practice they are mostly used for linking to other PDF
- // files, which we thus attempt to support (utilizing `docBaseUrl`).
- case 'GoToR':
- var urlDict = action.get('F');
- if (isDict(urlDict)) {
- // We assume that we found a FileSpec dictionary
- // and fetch the URL without checking any further.
- url = urlDict.get('F') || null;
- } else if (isString(urlDict)) {
- url = urlDict;
- }
- // NOTE: the destination is relative to the *remote* document.
- var remoteDest = action.get('D');
- if (remoteDest) {
- if (isName(remoteDest)) {
- remoteDest = remoteDest.name;
- }
- if (isString(url)) {
- var baseUrl = url.split('#')[0];
- if (isString(remoteDest)) {
- // In practice, a named destination may contain only a number.
- // If that happens, use the '#nameddest=' form to avoid the link
- // redirecting to a page, instead of the correct destination.
- url = baseUrl + '#' + (/^\d+$/.test(remoteDest) ? 'nameddest=' : '') + remoteDest;
- } else if (isArray(remoteDest)) {
- url = baseUrl + '#' + JSON.stringify(remoteDest);
- }
- }
- }
- // The 'NewWindow' property, equal to `LinkTarget.BLANK`.
- var newWindow = action.get('NewWindow');
- if (isBool(newWindow)) {
- resultObj.newWindow = newWindow;
- }
- break;
- case 'Named':
- var namedAction = action.get('N');
- if (isName(namedAction)) {
- resultObj.action = namedAction.name;
- }
- break;
- case 'JavaScript':
- var jsAction = action.get('JS'), js;
- if (isStream(jsAction)) {
- js = bytesToString(jsAction.getBytes());
- } else if (isString(jsAction)) {
- js = jsAction;
- }
- if (js) {
- // Attempt to recover valid URLs from 'JS' entries with certain
- // white-listed formats, e.g.
- // - window.open('http://example.com')
- // - app.launchURL('http://example.com', true)
- var URL_OPEN_METHODS = [
- 'app.launchURL',
- 'window.open'
- ];
- var regex = new RegExp('^(?:' + URL_OPEN_METHODS.join('|') + ')' + '\\((?:\'|\")(\\S+)(?:\'|\")(?:,|\\))');
- var jsUrl = regex.exec(stringToPDFString(js), 'i');
- if (jsUrl && jsUrl[1]) {
- url = jsUrl[1];
- break;
- }
- }
- default:
- warn('Catalog_parseDestDictionary: Unrecognized link type "' + linkType + '".');
- break;
- }
- } else if (destDict.has('Dest')) {
- // Simple destination link.
- dest = destDict.get('Dest');
- }
- if (isString(url)) {
- url = tryConvertUrlEncoding(url);
- var absoluteUrl = createValidAbsoluteUrl(url, docBaseUrl);
- if (absoluteUrl) {
- resultObj.url = absoluteUrl.href;
- }
- resultObj.unsafeUrl = url;
- }
- if (dest) {
- if (isName(dest)) {
- dest = dest.name;
- }
- if (isString(dest) || isArray(dest)) {
- resultObj.dest = dest;
- }
- }
- };
- return Catalog;
- }();
- var XRef = function XRefClosure() {
- function XRef(stream, password) {
- this.stream = stream;
- this.entries = [];
- this.xrefstms = Object.create(null);
- // prepare the XRef cache
- this.cache = [];
- this.password = password;
- this.stats = {
- streamTypes: [],
- fontTypes: []
- };
- }
- XRef.prototype = {
- setStartXRef: function XRef_setStartXRef(startXRef) {
- // Store the starting positions of xref tables as we process them
- // so we can recover from missing data errors
- this.startXRefQueue = [startXRef];
- },
- parse: function XRef_parse(recoveryMode) {
- var trailerDict;
- if (!recoveryMode) {
- trailerDict = this.readXRef();
- } else {
- warn('Indexing all PDF objects');
- trailerDict = this.indexObjects();
- }
- trailerDict.assignXref(this);
- this.trailer = trailerDict;
- var encrypt = trailerDict.get('Encrypt');
- if (encrypt) {
- var ids = trailerDict.get('ID');
- var fileId = ids && ids.length ? ids[0] : '';
- // The 'Encrypt' dictionary itself should not be encrypted, and by
- // setting `suppressEncryption` we can prevent an infinite loop inside
- // of `XRef_fetchUncompressed` if the dictionary contains indirect
- // objects (fixes issue7665.pdf).
- encrypt.suppressEncryption = true;
- this.encrypt = new CipherTransformFactory(encrypt, fileId, this.password);
- }
- // get the root dictionary (catalog) object
- if (!(this.root = trailerDict.get('Root'))) {
- error('Invalid root reference');
- }
- },
- processXRefTable: function XRef_processXRefTable(parser) {
- if (!('tableState' in this)) {
- // Stores state of the table as we process it so we can resume
- // from middle of table in case of missing data error
- this.tableState = {
- entryNum: 0,
- streamPos: parser.lexer.stream.pos,
- parserBuf1: parser.buf1,
- parserBuf2: parser.buf2
- };
- }
- var obj = this.readXRefTable(parser);
- // Sanity check
- if (!isCmd(obj, 'trailer')) {
- error('Invalid XRef table: could not find trailer dictionary');
- }
- // Read trailer dictionary, e.g.
- // trailer
- // << /Size 22
- // /Root 20R
- // /Info 10R
- // /ID [ <81b14aafa313db63dbd6f981e49f94f4> ]
- // >>
- // The parser goes through the entire stream << ... >> and provides
- // a getter interface for the key-value table
- var dict = parser.getObj();
- // The pdflib PDF generator can generate a nested trailer dictionary
- if (!isDict(dict) && dict.dict) {
- dict = dict.dict;
- }
- if (!isDict(dict)) {
- error('Invalid XRef table: could not parse trailer dictionary');
- }
- delete this.tableState;
- return dict;
- },
- readXRefTable: function XRef_readXRefTable(parser) {
- // Example of cross-reference table:
- // xref
- // 0 1 <-- subsection header (first obj #, obj count)
- // 0000000000 65535 f <-- actual object (offset, generation #, f/n)
- // 23 2 <-- subsection header ... and so on ...
- // 0000025518 00002 n
- // 0000025635 00000 n
- // trailer
- // ...
- var stream = parser.lexer.stream;
- var tableState = this.tableState;
- stream.pos = tableState.streamPos;
- parser.buf1 = tableState.parserBuf1;
- parser.buf2 = tableState.parserBuf2;
- // Outer loop is over subsection headers
- var obj;
- while (true) {
- if (!('firstEntryNum' in tableState) || !('entryCount' in tableState)) {
- if (isCmd(obj = parser.getObj(), 'trailer')) {
- break;
- }
- tableState.firstEntryNum = obj;
- tableState.entryCount = parser.getObj();
- }
- var first = tableState.firstEntryNum;
- var count = tableState.entryCount;
- if (!isInt(first) || !isInt(count)) {
- error('Invalid XRef table: wrong types in subsection header');
- }
- // Inner loop is over objects themselves
- for (var i = tableState.entryNum; i < count; i++) {
- tableState.streamPos = stream.pos;
- tableState.entryNum = i;
- tableState.parserBuf1 = parser.buf1;
- tableState.parserBuf2 = parser.buf2;
- var entry = {};
- entry.offset = parser.getObj();
- entry.gen = parser.getObj();
- var type = parser.getObj();
- if (isCmd(type, 'f')) {
- entry.free = true;
- } else if (isCmd(type, 'n')) {
- entry.uncompressed = true;
- }
- // Validate entry obj
- if (!isInt(entry.offset) || !isInt(entry.gen) || !(entry.free || entry.uncompressed)) {
- error('Invalid entry in XRef subsection: ' + first + ', ' + count);
- }
- // The first xref table entry, i.e. obj 0, should be free. Attempting
- // to adjust an incorrect first obj # (fixes issue 3248 and 7229).
- if (i === 0 && entry.free && first === 1) {
- first = 0;
- }
- if (!this.entries[i + first]) {
- this.entries[i + first] = entry;
- }
- }
- tableState.entryNum = 0;
- tableState.streamPos = stream.pos;
- tableState.parserBuf1 = parser.buf1;
- tableState.parserBuf2 = parser.buf2;
- delete tableState.firstEntryNum;
- delete tableState.entryCount;
- }
- // Sanity check: as per spec, first object must be free
- if (this.entries[0] && !this.entries[0].free) {
- error('Invalid XRef table: unexpected first object');
- }
- return obj;
- },
- processXRefStream: function XRef_processXRefStream(stream) {
- if (!('streamState' in this)) {
- // Stores state of the stream as we process it so we can resume
- // from middle of stream in case of missing data error
- var streamParameters = stream.dict;
- var byteWidths = streamParameters.get('W');
- var range = streamParameters.get('Index');
- if (!range) {
- range = [
- 0,
- streamParameters.get('Size')
- ];
- }
- this.streamState = {
- entryRanges: range,
- byteWidths: byteWidths,
- entryNum: 0,
- streamPos: stream.pos
- };
- }
- this.readXRefStream(stream);
- delete this.streamState;
- return stream.dict;
- },
- readXRefStream: function XRef_readXRefStream(stream) {
- var i, j;
- var streamState = this.streamState;
- stream.pos = streamState.streamPos;
- var byteWidths = streamState.byteWidths;
- var typeFieldWidth = byteWidths[0];
- var offsetFieldWidth = byteWidths[1];
- var generationFieldWidth = byteWidths[2];
- var entryRanges = streamState.entryRanges;
- while (entryRanges.length > 0) {
- var first = entryRanges[0];
- var n = entryRanges[1];
- if (!isInt(first) || !isInt(n)) {
- error('Invalid XRef range fields: ' + first + ', ' + n);
- }
- if (!isInt(typeFieldWidth) || !isInt(offsetFieldWidth) || !isInt(generationFieldWidth)) {
- error('Invalid XRef entry fields length: ' + first + ', ' + n);
- }
- for (i = streamState.entryNum; i < n; ++i) {
- streamState.entryNum = i;
- streamState.streamPos = stream.pos;
- var type = 0, offset = 0, generation = 0;
- for (j = 0; j < typeFieldWidth; ++j) {
- type = type << 8 | stream.getByte();
- }
- // if type field is absent, its default value is 1
- if (typeFieldWidth === 0) {
- type = 1;
- }
- for (j = 0; j < offsetFieldWidth; ++j) {
- offset = offset << 8 | stream.getByte();
- }
- for (j = 0; j < generationFieldWidth; ++j) {
- generation = generation << 8 | stream.getByte();
- }
- var entry = {};
- entry.offset = offset;
- entry.gen = generation;
- switch (type) {
- case 0:
- entry.free = true;
- break;
- case 1:
- entry.uncompressed = true;
- break;
- case 2:
- break;
- default:
- error('Invalid XRef entry type: ' + type);
- }
- if (!this.entries[first + i]) {
- this.entries[first + i] = entry;
- }
- }
- streamState.entryNum = 0;
- streamState.streamPos = stream.pos;
- entryRanges.splice(0, 2);
- }
- },
- indexObjects: function XRef_indexObjects() {
- // Simple scan through the PDF content to find objects,
- // trailers and XRef streams.
- var TAB = 0x9, LF = 0xA, CR = 0xD, SPACE = 0x20;
- var PERCENT = 0x25, LT = 0x3C;
- function readToken(data, offset) {
- var token = '', ch = data[offset];
- while (ch !== LF && ch !== CR && ch !== LT) {
- if (++offset >= data.length) {
- break;
- }
- token += String.fromCharCode(ch);
- ch = data[offset];
- }
- return token;
- }
- function skipUntil(data, offset, what) {
- var length = what.length, dataLength = data.length;
- var skipped = 0;
- // finding byte sequence
- while (offset < dataLength) {
- var i = 0;
- while (i < length && data[offset + i] === what[i]) {
- ++i;
- }
- if (i >= length) {
- break;
- }
- // sequence found
- offset++;
- skipped++;
- }
- return skipped;
- }
- var objRegExp = /^(\d+)\s+(\d+)\s+obj\b/;
- var trailerBytes = new Uint8Array([
- 116,
- 114,
- 97,
- 105,
- 108,
- 101,
- 114
- ]);
- var startxrefBytes = new Uint8Array([
- 115,
- 116,
- 97,
- 114,
- 116,
- 120,
- 114,
- 101,
- 102
- ]);
- var endobjBytes = new Uint8Array([
- 101,
- 110,
- 100,
- 111,
- 98,
- 106
- ]);
- var xrefBytes = new Uint8Array([
- 47,
- 88,
- 82,
- 101,
- 102
- ]);
- // Clear out any existing entries, since they may be bogus.
- this.entries.length = 0;
- var stream = this.stream;
- stream.pos = 0;
- var buffer = stream.getBytes();
- var position = stream.start, length = buffer.length;
- var trailers = [], xrefStms = [];
- while (position < length) {
- var ch = buffer[position];
- if (ch === TAB || ch === LF || ch === CR || ch === SPACE) {
- ++position;
- continue;
- }
- if (ch === PERCENT) {
- // %-comment
- do {
- ++position;
- if (position >= length) {
- break;
- }
- ch = buffer[position];
- } while (ch !== LF && ch !== CR);
- continue;
- }
- var token = readToken(buffer, position);
- var m;
- if (token.indexOf('xref') === 0 && (token.length === 4 || /\s/.test(token[4]))) {
- position += skipUntil(buffer, position, trailerBytes);
- trailers.push(position);
- position += skipUntil(buffer, position, startxrefBytes);
- } else if (m = objRegExp.exec(token)) {
- if (typeof this.entries[m[1]] === 'undefined') {
- this.entries[m[1]] = {
- offset: position - stream.start,
- gen: m[2] | 0,
- uncompressed: true
- };
- }
- var contentLength = skipUntil(buffer, position, endobjBytes) + 7;
- var content = buffer.subarray(position, position + contentLength);
- // checking XRef stream suspect
- // (it shall have '/XRef' and next char is not a letter)
- var xrefTagOffset = skipUntil(content, 0, xrefBytes);
- if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) {
- xrefStms.push(position - stream.start);
- this.xrefstms[position - stream.start] = 1;
- }
- // Avoid recursion
- position += contentLength;
- } else if (token.indexOf('trailer') === 0 && (token.length === 7 || /\s/.test(token[7]))) {
- trailers.push(position);
- position += skipUntil(buffer, position, startxrefBytes);
- } else {
- position += token.length + 1;
- }
- }
- // reading XRef streams
- var i, ii;
- for (i = 0, ii = xrefStms.length; i < ii; ++i) {
- this.startXRefQueue.push(xrefStms[i]);
- this.readXRef(/* recoveryMode */
- true);
- }
- // finding main trailer
- var dict;
- for (i = 0, ii = trailers.length; i < ii; ++i) {
- stream.pos = trailers[i];
- var parser = new Parser(new Lexer(stream), /* allowStreams = */
- true, /* xref = */
- this, /* recoveryMode = */
- true);
- var obj = parser.getObj();
- if (!isCmd(obj, 'trailer')) {
- continue;
- }
- // read the trailer dictionary
- dict = parser.getObj();
- if (!isDict(dict)) {
- continue;
- }
- // taking the first one with 'ID'
- if (dict.has('ID')) {
- return dict;
- }
- }
- // no tailer with 'ID', taking last one (if exists)
- if (dict) {
- return dict;
- }
- // nothing helps
- // calling error() would reject worker with an UnknownErrorException.
- throw new InvalidPDFException('Invalid PDF structure');
- },
- readXRef: function XRef_readXRef(recoveryMode) {
- var stream = this.stream;
- try {
- while (this.startXRefQueue.length) {
- var startXRef = this.startXRefQueue[0];
- stream.pos = startXRef + stream.start;
- var parser = new Parser(new Lexer(stream), true, this);
- var obj = parser.getObj();
- var dict;
- // Get dictionary
- if (isCmd(obj, 'xref')) {
- // Parse end-of-file XRef
- dict = this.processXRefTable(parser);
- if (!this.topDict) {
- this.topDict = dict;
- }
- // Recursively get other XRefs 'XRefStm', if any
- obj = dict.get('XRefStm');
- if (isInt(obj)) {
- var pos = obj;
- // ignore previously loaded xref streams
- // (possible infinite recursion)
- if (!(pos in this.xrefstms)) {
- this.xrefstms[pos] = 1;
- this.startXRefQueue.push(pos);
- }
- }
- } else if (isInt(obj)) {
- // Parse in-stream XRef
- if (!isInt(parser.getObj()) || !isCmd(parser.getObj(), 'obj') || !isStream(obj = parser.getObj())) {
- error('Invalid XRef stream');
- }
- dict = this.processXRefStream(obj);
- if (!this.topDict) {
- this.topDict = dict;
- }
- if (!dict) {
- error('Failed to read XRef stream');
- }
- } else {
- error('Invalid XRef stream header');
- }
- // Recursively get previous dictionary, if any
- obj = dict.get('Prev');
- if (isInt(obj)) {
- this.startXRefQueue.push(obj);
- } else if (isRef(obj)) {
- // The spec says Prev must not be a reference, i.e. "/Prev NNN"
- // This is a fallback for non-compliant PDFs, i.e. "/Prev NNN 0 R"
- this.startXRefQueue.push(obj.num);
- }
- this.startXRefQueue.shift();
- }
- return this.topDict;
- } catch (e) {
- if (e instanceof MissingDataException) {
- throw e;
- }
- info('(while reading XRef): ' + e);
- }
- if (recoveryMode) {
- return;
- }
- throw new XRefParseException();
- },
- getEntry: function XRef_getEntry(i) {
- var xrefEntry = this.entries[i];
- if (xrefEntry && !xrefEntry.free && xrefEntry.offset) {
- return xrefEntry;
- }
- return null;
- },
- fetchIfRef: function XRef_fetchIfRef(obj, suppressEncryption) {
- if (!isRef(obj)) {
- return obj;
- }
- return this.fetch(obj, suppressEncryption);
- },
- fetch: function XRef_fetch(ref, suppressEncryption) {
- assert(isRef(ref), 'ref object is not a reference');
- var num = ref.num;
- if (num in this.cache) {
- var cacheEntry = this.cache[num];
- return cacheEntry;
- }
- var xrefEntry = this.getEntry(num);
- // the referenced entry can be free
- if (xrefEntry === null) {
- return this.cache[num] = null;
- }
- if (xrefEntry.uncompressed) {
- xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption);
- } else {
- xrefEntry = this.fetchCompressed(xrefEntry, suppressEncryption);
- }
- if (isDict(xrefEntry)) {
- xrefEntry.objId = ref.toString();
- } else if (isStream(xrefEntry)) {
- xrefEntry.dict.objId = ref.toString();
- }
- return xrefEntry;
- },
- fetchUncompressed: function XRef_fetchUncompressed(ref, xrefEntry, suppressEncryption) {
- var gen = ref.gen;
- var num = ref.num;
- if (xrefEntry.gen !== gen) {
- error('inconsistent generation in XRef');
- }
- var stream = this.stream.makeSubStream(xrefEntry.offset + this.stream.start);
- var parser = new Parser(new Lexer(stream), true, this);
- var obj1 = parser.getObj();
- var obj2 = parser.getObj();
- var obj3 = parser.getObj();
- if (!isInt(obj1) || parseInt(obj1, 10) !== num || !isInt(obj2) || parseInt(obj2, 10) !== gen || !isCmd(obj3)) {
- error('bad XRef entry');
- }
- if (!isCmd(obj3, 'obj')) {
- // some bad PDFs use "obj1234" and really mean 1234
- if (obj3.cmd.indexOf('obj') === 0) {
- num = parseInt(obj3.cmd.substring(3), 10);
- if (!isNaN(num)) {
- return num;
- }
- }
- error('bad XRef entry');
- }
- if (this.encrypt && !suppressEncryption) {
- xrefEntry = parser.getObj(this.encrypt.createCipherTransform(num, gen));
- } else {
- xrefEntry = parser.getObj();
- }
- if (!isStream(xrefEntry)) {
- this.cache[num] = xrefEntry;
- }
- return xrefEntry;
- },
- fetchCompressed: function XRef_fetchCompressed(xrefEntry, suppressEncryption) {
- var tableOffset = xrefEntry.offset;
- var stream = this.fetch(new Ref(tableOffset, 0));
- if (!isStream(stream)) {
- error('bad ObjStm stream');
- }
- var first = stream.dict.get('First');
- var n = stream.dict.get('N');
- if (!isInt(first) || !isInt(n)) {
- error('invalid first and n parameters for ObjStm stream');
- }
- var parser = new Parser(new Lexer(stream), false, this);
- parser.allowStreams = true;
- var i, entries = [], num, nums = [];
- // read the object numbers to populate cache
- for (i = 0; i < n; ++i) {
- num = parser.getObj();
- if (!isInt(num)) {
- error('invalid object number in the ObjStm stream: ' + num);
- }
- nums.push(num);
- var offset = parser.getObj();
- if (!isInt(offset)) {
- error('invalid object offset in the ObjStm stream: ' + offset);
- }
- }
- // read stream objects for cache
- for (i = 0; i < n; ++i) {
- entries.push(parser.getObj());
- // The ObjStm should not contain 'endobj'. If it's present, skip over it
- // to support corrupt PDFs (fixes issue 5241, bug 898610, bug 1037816).
- if (isCmd(parser.buf1, 'endobj')) {
- parser.shift();
- }
- num = nums[i];
- var entry = this.entries[num];
- if (entry && entry.offset === tableOffset && entry.gen === i) {
- this.cache[num] = entries[i];
- }
- }
- xrefEntry = entries[xrefEntry.gen];
- if (xrefEntry === undefined) {
- error('bad XRef entry for compressed object');
- }
- return xrefEntry;
- },
- fetchIfRefAsync: function XRef_fetchIfRefAsync(obj, suppressEncryption) {
- if (!isRef(obj)) {
- return Promise.resolve(obj);
- }
- return this.fetchAsync(obj, suppressEncryption);
- },
- fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) {
- var streamManager = this.stream.manager;
- var xref = this;
- return new Promise(function tryFetch(resolve, reject) {
- try {
- resolve(xref.fetch(ref, suppressEncryption));
- } catch (e) {
- if (e instanceof MissingDataException) {
- streamManager.requestRange(e.begin, e.end).then(function () {
- tryFetch(resolve, reject);
- }, reject);
- return;
- }
- reject(e);
- }
- });
- },
- getCatalogObj: function XRef_getCatalogObj() {
- return this.root;
- }
- };
- return XRef;
- }();
- /**
- * A NameTree/NumberTree is like a Dict but has some advantageous properties,
- * see the specification (7.9.6 and 7.9.7) for additional details.
- * TODO: implement all the Dict functions and make this more efficient.
- */
- var NameOrNumberTree = function NameOrNumberTreeClosure() {
- function NameOrNumberTree(root, xref) {
- throw new Error('Cannot initialize NameOrNumberTree.');
- }
- NameOrNumberTree.prototype = {
- getAll: function NameOrNumberTree_getAll() {
- var dict = Object.create(null);
- if (!this.root) {
- return dict;
- }
- var xref = this.xref;
- // Reading Name/Number tree.
- var processed = new RefSet();
- processed.put(this.root);
- var queue = [this.root];
- while (queue.length > 0) {
- var i, n;
- var obj = xref.fetchIfRef(queue.shift());
- if (!isDict(obj)) {
- continue;
- }
- if (obj.has('Kids')) {
- var kids = obj.get('Kids');
- for (i = 0, n = kids.length; i < n; i++) {
- var kid = kids[i];
- assert(!processed.has(kid), 'Duplicate entry in "' + this._type + '" tree.');
- queue.push(kid);
- processed.put(kid);
- }
- continue;
- }
- var entries = obj.get(this._type);
- if (isArray(entries)) {
- for (i = 0, n = entries.length; i < n; i += 2) {
- dict[xref.fetchIfRef(entries[i])] = xref.fetchIfRef(entries[i + 1]);
- }
- }
- }
- return dict;
- },
- get: function NameOrNumberTree_get(key) {
- if (!this.root) {
- return null;
- }
- var xref = this.xref;
- var kidsOrEntries = xref.fetchIfRef(this.root);
- var loopCount = 0;
- var MAX_LEVELS = 10;
- var l, r, m;
- // Perform a binary search to quickly find the entry that
- // contains the key we are looking for.
- while (kidsOrEntries.has('Kids')) {
- if (++loopCount > MAX_LEVELS) {
- warn('Search depth limit reached for "' + this._type + '" tree.');
- return null;
- }
- var kids = kidsOrEntries.get('Kids');
- if (!isArray(kids)) {
- return null;
- }
- l = 0;
- r = kids.length - 1;
- while (l <= r) {
- m = l + r >> 1;
- var kid = xref.fetchIfRef(kids[m]);
- var limits = kid.get('Limits');
- if (key < xref.fetchIfRef(limits[0])) {
- r = m - 1;
- } else if (key > xref.fetchIfRef(limits[1])) {
- l = m + 1;
- } else {
- kidsOrEntries = xref.fetchIfRef(kids[m]);
- break;
- }
- }
- if (l > r) {
- return null;
- }
- }
- // If we get here, then we have found the right entry. Now go through the
- // entries in the dictionary until we find the key we're looking for.
- var entries = kidsOrEntries.get(this._type);
- if (isArray(entries)) {
- // Perform a binary search to reduce the lookup time.
- l = 0;
- r = entries.length - 2;
- while (l <= r) {
- // Check only even indices (0, 2, 4, ...) because the
- // odd indices contain the actual data.
- m = l + r & ~1;
- var currentKey = xref.fetchIfRef(entries[m]);
- if (key < currentKey) {
- r = m - 2;
- } else if (key > currentKey) {
- l = m + 2;
- } else {
- return xref.fetchIfRef(entries[m + 1]);
- }
- }
- }
- return null;
- }
- };
- return NameOrNumberTree;
- }();
- var NameTree = function NameTreeClosure() {
- function NameTree(root, xref) {
- this.root = root;
- this.xref = xref;
- this._type = 'Names';
- }
- Util.inherit(NameTree, NameOrNumberTree, {});
- return NameTree;
- }();
- var NumberTree = function NumberTreeClosure() {
- function NumberTree(root, xref) {
- this.root = root;
- this.xref = xref;
- this._type = 'Nums';
- }
- Util.inherit(NumberTree, NameOrNumberTree, {});
- return NumberTree;
- }();
- /**
- * "A PDF file can refer to the contents of another file by using a File
- * Specification (PDF 1.1)", see the spec (7.11) for more details.
- * NOTE: Only embedded files are supported (as part of the attachments support)
- * TODO: support the 'URL' file system (with caching if !/V), portable
- * collections attributes and related files (/RF)
- */
- var FileSpec = function FileSpecClosure() {
- function FileSpec(root, xref) {
- if (!root || !isDict(root)) {
- return;
- }
- this.xref = xref;
- this.root = root;
- if (root.has('FS')) {
- this.fs = root.get('FS');
- }
- this.description = root.has('Desc') ? stringToPDFString(root.get('Desc')) : '';
- if (root.has('RF')) {
- warn('Related file specifications are not supported');
- }
- this.contentAvailable = true;
- if (!root.has('EF')) {
- this.contentAvailable = false;
- warn('Non-embedded file specifications are not supported');
- }
- }
- function pickPlatformItem(dict) {
- // Look for the filename in this order:
- // UF, F, Unix, Mac, DOS
- if (dict.has('UF')) {
- return dict.get('UF');
- } else if (dict.has('F')) {
- return dict.get('F');
- } else if (dict.has('Unix')) {
- return dict.get('Unix');
- } else if (dict.has('Mac')) {
- return dict.get('Mac');
- } else if (dict.has('DOS')) {
- return dict.get('DOS');
- } else {
- return null;
- }
- }
- FileSpec.prototype = {
- get filename() {
- if (!this._filename && this.root) {
- var filename = pickPlatformItem(this.root) || 'unnamed';
- this._filename = stringToPDFString(filename).replace(/\\\\/g, '\\').replace(/\\\//g, '/').replace(/\\/g, '/');
- }
- return this._filename;
- },
- get content() {
- if (!this.contentAvailable) {
- return null;
- }
- if (!this.contentRef && this.root) {
- this.contentRef = pickPlatformItem(this.root.get('EF'));
- }
- var content = null;
- if (this.contentRef) {
- var xref = this.xref;
- var fileObj = xref.fetchIfRef(this.contentRef);
- if (fileObj && isStream(fileObj)) {
- content = fileObj.getBytes();
- } else {
- warn('Embedded file specification points to non-existing/invalid ' + 'content');
- }
- } else {
- warn('Embedded file specification does not have a content');
- }
- return content;
- },
- get serializable() {
- return {
- filename: this.filename,
- content: this.content
- };
- }
- };
- return FileSpec;
- }();
- /**
- * A helper for loading missing data in object graphs. It traverses the graph
- * depth first and queues up any objects that have missing data. Once it has
- * has traversed as many objects that are available it attempts to bundle the
- * missing data requests and then resume from the nodes that weren't ready.
- *
- * NOTE: It provides protection from circular references by keeping track of
- * of loaded references. However, you must be careful not to load any graphs
- * that have references to the catalog or other pages since that will cause the
- * entire PDF document object graph to be traversed.
- */
- var ObjectLoader = function () {
- function mayHaveChildren(value) {
- return isRef(value) || isDict(value) || isArray(value) || isStream(value);
- }
- function addChildren(node, nodesToVisit) {
- var value;
- if (isDict(node) || isStream(node)) {
- var map;
- if (isDict(node)) {
- map = node.map;
- } else {
- map = node.dict.map;
- }
- for (var key in map) {
- value = map[key];
- if (mayHaveChildren(value)) {
- nodesToVisit.push(value);
- }
- }
- } else if (isArray(node)) {
- for (var i = 0, ii = node.length; i < ii; i++) {
- value = node[i];
- if (mayHaveChildren(value)) {
- nodesToVisit.push(value);
- }
- }
- }
- }
- function ObjectLoader(obj, keys, xref) {
- this.obj = obj;
- this.keys = keys;
- this.xref = xref;
- this.refSet = null;
- this.capability = null;
- }
- ObjectLoader.prototype = {
- load: function ObjectLoader_load() {
- var keys = this.keys;
- this.capability = createPromiseCapability();
- // Don't walk the graph if all the data is already loaded.
- if (!(this.xref.stream instanceof ChunkedStream) || this.xref.stream.getMissingChunks().length === 0) {
- this.capability.resolve();
- return this.capability.promise;
- }
- this.refSet = new RefSet();
- // Setup the initial nodes to visit.
- var nodesToVisit = [];
- for (var i = 0; i < keys.length; i++) {
- nodesToVisit.push(this.obj[keys[i]]);
- }
- this._walk(nodesToVisit);
- return this.capability.promise;
- },
- _walk: function ObjectLoader_walk(nodesToVisit) {
- var nodesToRevisit = [];
- var pendingRequests = [];
- // DFS walk of the object graph.
- while (nodesToVisit.length) {
- var currentNode = nodesToVisit.pop();
- // Only references or chunked streams can cause missing data exceptions.
- if (isRef(currentNode)) {
- // Skip nodes that have already been visited.
- if (this.refSet.has(currentNode)) {
- continue;
- }
- try {
- var ref = currentNode;
- this.refSet.put(ref);
- currentNode = this.xref.fetch(currentNode);
- } catch (e) {
- if (!(e instanceof MissingDataException)) {
- throw e;
- }
- nodesToRevisit.push(currentNode);
- pendingRequests.push({
- begin: e.begin,
- end: e.end
- });
- }
- }
- if (currentNode && currentNode.getBaseStreams) {
- var baseStreams = currentNode.getBaseStreams();
- var foundMissingData = false;
- for (var i = 0; i < baseStreams.length; i++) {
- var stream = baseStreams[i];
- if (stream.getMissingChunks && stream.getMissingChunks().length) {
- foundMissingData = true;
- pendingRequests.push({
- begin: stream.start,
- end: stream.end
- });
- }
- }
- if (foundMissingData) {
- nodesToRevisit.push(currentNode);
- }
- }
- addChildren(currentNode, nodesToVisit);
- }
- if (pendingRequests.length) {
- this.xref.stream.manager.requestRanges(pendingRequests).then(function pendingRequestCallback() {
- nodesToVisit = nodesToRevisit;
- for (var i = 0; i < nodesToRevisit.length; i++) {
- var node = nodesToRevisit[i];
- // Remove any reference nodes from the currrent refset so they
- // aren't skipped when we revist them.
- if (isRef(node)) {
- this.refSet.remove(node);
- }
- }
- this._walk(nodesToVisit);
- }.bind(this), this.capability.reject);
- return;
- }
- // Everything is loaded.
- this.refSet = null;
- this.capability.resolve();
- }
- };
- return ObjectLoader;
- }();
- exports.Catalog = Catalog;
- exports.ObjectLoader = ObjectLoader;
- exports.XRef = XRef;
- exports.FileSpec = FileSpec;
- }));
- (function (root, factory) {
- factory(root.pdfjsCorePattern = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreFunction, root.pdfjsCoreColorSpace);
- }(this, function (exports, sharedUtil, corePrimitives, coreFunction, coreColorSpace) {
- var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES;
- var MissingDataException = sharedUtil.MissingDataException;
- var Util = sharedUtil.Util;
- var assert = sharedUtil.assert;
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var warn = sharedUtil.warn;
- var isStream = corePrimitives.isStream;
- var PDFFunction = coreFunction.PDFFunction;
- var ColorSpace = coreColorSpace.ColorSpace;
- var ShadingType = {
- FUNCTION_BASED: 1,
- AXIAL: 2,
- RADIAL: 3,
- FREE_FORM_MESH: 4,
- LATTICE_FORM_MESH: 5,
- COONS_PATCH_MESH: 6,
- TENSOR_PATCH_MESH: 7
- };
- var Pattern = function PatternClosure() {
- // Constructor should define this.getPattern
- function Pattern() {
- error('should not call Pattern constructor');
- }
- Pattern.prototype = {
- // Input: current Canvas context
- // Output: the appropriate fillStyle or strokeStyle
- getPattern: function Pattern_getPattern(ctx) {
- error('Should not call Pattern.getStyle: ' + ctx);
- }
- };
- Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref, res, handler) {
- var dict = isStream(shading) ? shading.dict : shading;
- var type = dict.get('ShadingType');
- try {
- switch (type) {
- case ShadingType.AXIAL:
- case ShadingType.RADIAL:
- // Both radial and axial shadings are handled by RadialAxial shading.
- return new Shadings.RadialAxial(dict, matrix, xref, res);
- case ShadingType.FREE_FORM_MESH:
- case ShadingType.LATTICE_FORM_MESH:
- case ShadingType.COONS_PATCH_MESH:
- case ShadingType.TENSOR_PATCH_MESH:
- return new Shadings.Mesh(shading, matrix, xref, res);
- default:
- throw new Error('Unsupported ShadingType: ' + type);
- }
- } catch (ex) {
- if (ex instanceof MissingDataException) {
- throw ex;
- }
- handler.send('UnsupportedFeature', { featureId: UNSUPPORTED_FEATURES.shadingPattern });
- warn(ex);
- return new Shadings.Dummy();
- }
- };
- return Pattern;
- }();
- var Shadings = {};
- // A small number to offset the first/last color stops so we can insert ones to
- // support extend. Number.MIN_VALUE is too small and breaks the extend.
- Shadings.SMALL_NUMBER = 1e-6;
- // Radial and axial shading have very similar implementations
- // If needed, the implementations can be broken into two classes
- Shadings.RadialAxial = function RadialAxialClosure() {
- function RadialAxial(dict, matrix, xref, res) {
- this.matrix = matrix;
- this.coordsArr = dict.getArray('Coords');
- this.shadingType = dict.get('ShadingType');
- this.type = 'Pattern';
- var cs = dict.get('ColorSpace', 'CS');
- cs = ColorSpace.parse(cs, xref, res);
- this.cs = cs;
- var t0 = 0.0, t1 = 1.0;
- if (dict.has('Domain')) {
- var domainArr = dict.getArray('Domain');
- t0 = domainArr[0];
- t1 = domainArr[1];
- }
- var extendStart = false, extendEnd = false;
- if (dict.has('Extend')) {
- var extendArr = dict.getArray('Extend');
- extendStart = extendArr[0];
- extendEnd = extendArr[1];
- }
- if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) {
- // Radial gradient only currently works if either circle is fully within
- // the other circle.
- var x1 = this.coordsArr[0];
- var y1 = this.coordsArr[1];
- var r1 = this.coordsArr[2];
- var x2 = this.coordsArr[3];
- var y2 = this.coordsArr[4];
- var r2 = this.coordsArr[5];
- var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
- if (r1 <= r2 + distance && r2 <= r1 + distance) {
- warn('Unsupported radial gradient.');
- }
- }
- this.extendStart = extendStart;
- this.extendEnd = extendEnd;
- var fnObj = dict.get('Function');
- var fn = PDFFunction.parseArray(xref, fnObj);
- // 10 samples seems good enough for now, but probably won't work
- // if there are sharp color changes. Ideally, we would implement
- // the spec faithfully and add lossless optimizations.
- var diff = t1 - t0;
- var step = diff / 10;
- var colorStops = this.colorStops = [];
- // Protect against bad domains so we don't end up in an infinte loop below.
- if (t0 >= t1 || step <= 0) {
- // Acrobat doesn't seem to handle these cases so we'll ignore for
- // now.
- info('Bad shading domain.');
- return;
- }
- var color = new Float32Array(cs.numComps), ratio = new Float32Array(1);
- var rgbColor;
- for (var i = t0; i <= t1; i += step) {
- ratio[0] = i;
- fn(ratio, 0, color, 0);
- rgbColor = cs.getRgb(color, 0);
- var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
- colorStops.push([
- (i - t0) / diff,
- cssColor
- ]);
- }
- var background = 'transparent';
- if (dict.has('Background')) {
- rgbColor = cs.getRgb(dict.get('Background'), 0);
- background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
- }
- if (!extendStart) {
- // Insert a color stop at the front and offset the first real color stop
- // so it doesn't conflict with the one we insert.
- colorStops.unshift([
- 0,
- background
- ]);
- colorStops[1][0] += Shadings.SMALL_NUMBER;
- }
- if (!extendEnd) {
- // Same idea as above in extendStart but for the end.
- colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER;
- colorStops.push([
- 1,
- background
- ]);
- }
- this.colorStops = colorStops;
- }
- RadialAxial.prototype = {
- getIR: function RadialAxial_getIR() {
- var coordsArr = this.coordsArr;
- var shadingType = this.shadingType;
- var type, p0, p1, r0, r1;
- if (shadingType === ShadingType.AXIAL) {
- p0 = [
- coordsArr[0],
- coordsArr[1]
- ];
- p1 = [
- coordsArr[2],
- coordsArr[3]
- ];
- r0 = null;
- r1 = null;
- type = 'axial';
- } else if (shadingType === ShadingType.RADIAL) {
- p0 = [
- coordsArr[0],
- coordsArr[1]
- ];
- p1 = [
- coordsArr[3],
- coordsArr[4]
- ];
- r0 = coordsArr[2];
- r1 = coordsArr[5];
- type = 'radial';
- } else {
- error('getPattern type unknown: ' + shadingType);
- }
- var matrix = this.matrix;
- if (matrix) {
- p0 = Util.applyTransform(p0, matrix);
- p1 = Util.applyTransform(p1, matrix);
- if (shadingType === ShadingType.RADIAL) {
- var scale = Util.singularValueDecompose2dScale(matrix);
- r0 *= scale[0];
- r1 *= scale[1];
- }
- }
- return [
- 'RadialAxial',
- type,
- this.colorStops,
- p0,
- p1,
- r0,
- r1
- ];
- }
- };
- return RadialAxial;
- }();
- // All mesh shading. For now, they will be presented as set of the triangles
- // to be drawn on the canvas and rgb color for each vertex.
- Shadings.Mesh = function MeshClosure() {
- function MeshStreamReader(stream, context) {
- this.stream = stream;
- this.context = context;
- this.buffer = 0;
- this.bufferLength = 0;
- var numComps = context.numComps;
- this.tmpCompsBuf = new Float32Array(numComps);
- var csNumComps = context.colorSpace.numComps;
- this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
- }
- MeshStreamReader.prototype = {
- get hasData() {
- if (this.stream.end) {
- return this.stream.pos < this.stream.end;
- }
- if (this.bufferLength > 0) {
- return true;
- }
- var nextByte = this.stream.getByte();
- if (nextByte < 0) {
- return false;
- }
- this.buffer = nextByte;
- this.bufferLength = 8;
- return true;
- },
- readBits: function MeshStreamReader_readBits(n) {
- var buffer = this.buffer;
- var bufferLength = this.bufferLength;
- if (n === 32) {
- if (bufferLength === 0) {
- return (this.stream.getByte() << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte()) >>> 0;
- }
- buffer = buffer << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte();
- var nextByte = this.stream.getByte();
- this.buffer = nextByte & (1 << bufferLength) - 1;
- return (buffer << 8 - bufferLength | (nextByte & 0xFF) >> bufferLength) >>> 0;
- }
- if (n === 8 && bufferLength === 0) {
- return this.stream.getByte();
- }
- while (bufferLength < n) {
- buffer = buffer << 8 | this.stream.getByte();
- bufferLength += 8;
- }
- bufferLength -= n;
- this.bufferLength = bufferLength;
- this.buffer = buffer & (1 << bufferLength) - 1;
- return buffer >> bufferLength;
- },
- align: function MeshStreamReader_align() {
- this.buffer = 0;
- this.bufferLength = 0;
- },
- readFlag: function MeshStreamReader_readFlag() {
- return this.readBits(this.context.bitsPerFlag);
- },
- readCoordinate: function MeshStreamReader_readCoordinate() {
- var bitsPerCoordinate = this.context.bitsPerCoordinate;
- var xi = this.readBits(bitsPerCoordinate);
- var yi = this.readBits(bitsPerCoordinate);
- var decode = this.context.decode;
- var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 2.3283064365386963e-10;
- // 2 ^ -32
- return [
- xi * scale * (decode[1] - decode[0]) + decode[0],
- yi * scale * (decode[3] - decode[2]) + decode[2]
- ];
- },
- readComponents: function MeshStreamReader_readComponents() {
- var numComps = this.context.numComps;
- var bitsPerComponent = this.context.bitsPerComponent;
- var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 2.3283064365386963e-10;
- // 2 ^ -32
- var decode = this.context.decode;
- var components = this.tmpCompsBuf;
- for (var i = 0, j = 4; i < numComps; i++, j += 2) {
- var ci = this.readBits(bitsPerComponent);
- components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
- }
- var color = this.tmpCsCompsBuf;
- if (this.context.colorFn) {
- this.context.colorFn(components, 0, color, 0);
- }
- return this.context.colorSpace.getRgb(color, 0);
- }
- };
- function decodeType4Shading(mesh, reader) {
- var coords = mesh.coords;
- var colors = mesh.colors;
- var operators = [];
- var ps = [];
- // not maintaining cs since that will match ps
- var verticesLeft = 0;
- // assuming we have all data to start a new triangle
- while (reader.hasData) {
- var f = reader.readFlag();
- var coord = reader.readCoordinate();
- var color = reader.readComponents();
- if (verticesLeft === 0) {
- // ignoring flags if we started a triangle
- assert(0 <= f && f <= 2, 'Unknown type4 flag');
- switch (f) {
- case 0:
- verticesLeft = 3;
- break;
- case 1:
- ps.push(ps[ps.length - 2], ps[ps.length - 1]);
- verticesLeft = 1;
- break;
- case 2:
- ps.push(ps[ps.length - 3], ps[ps.length - 1]);
- verticesLeft = 1;
- break;
- }
- operators.push(f);
- }
- ps.push(coords.length);
- coords.push(coord);
- colors.push(color);
- verticesLeft--;
- reader.align();
- }
- mesh.figures.push({
- type: 'triangles',
- coords: new Int32Array(ps),
- colors: new Int32Array(ps)
- });
- }
- function decodeType5Shading(mesh, reader, verticesPerRow) {
- var coords = mesh.coords;
- var colors = mesh.colors;
- var ps = [];
- // not maintaining cs since that will match ps
- while (reader.hasData) {
- var coord = reader.readCoordinate();
- var color = reader.readComponents();
- ps.push(coords.length);
- coords.push(coord);
- colors.push(color);
- }
- mesh.figures.push({
- type: 'lattice',
- coords: new Int32Array(ps),
- colors: new Int32Array(ps),
- verticesPerRow: verticesPerRow
- });
- }
- var MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
- var MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
- var TRIANGLE_DENSITY = 20;
- // count of triangles per entire mesh bounds
- var getB = function getBClosure() {
- function buildB(count) {
- var lut = [];
- for (var i = 0; i <= count; i++) {
- var t = i / count, t_ = 1 - t;
- lut.push(new Float32Array([
- t_ * t_ * t_,
- 3 * t * t_ * t_,
- 3 * t * t * t_,
- t * t * t
- ]));
- }
- return lut;
- }
- var cache = [];
- return function getB(count) {
- if (!cache[count]) {
- cache[count] = buildB(count);
- }
- return cache[count];
- };
- }();
- function buildFigureFromPatch(mesh, index) {
- var figure = mesh.figures[index];
- assert(figure.type === 'patch', 'Unexpected patch mesh figure');
- var coords = mesh.coords, colors = mesh.colors;
- var pi = figure.coords;
- var ci = figure.colors;
- var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
- var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
- var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
- var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
- var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY / (mesh.bounds[2] - mesh.bounds[0]));
- splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy));
- var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY / (mesh.bounds[3] - mesh.bounds[1]));
- splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy));
- var verticesPerRow = splitXBy + 1;
- var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
- var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
- var k = 0;
- var cl = new Uint8Array(3), cr = new Uint8Array(3);
- var c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]];
- var bRow = getB(splitYBy), bCol = getB(splitXBy);
- for (var row = 0; row <= splitYBy; row++) {
- cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
- cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
- cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
- cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
- cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
- cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
- for (var col = 0; col <= splitXBy; col++, k++) {
- if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
- continue;
- }
- var x = 0, y = 0;
- var q = 0;
- for (var i = 0; i <= 3; i++) {
- for (var j = 0; j <= 3; j++, q++) {
- var m = bRow[row][i] * bCol[col][j];
- x += coords[pi[q]][0] * m;
- y += coords[pi[q]][1] * m;
- }
- }
- figureCoords[k] = coords.length;
- coords.push([
- x,
- y
- ]);
- figureColors[k] = colors.length;
- var newColor = new Uint8Array(3);
- newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
- newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
- newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
- colors.push(newColor);
- }
- }
- figureCoords[0] = pi[0];
- figureColors[0] = ci[0];
- figureCoords[splitXBy] = pi[3];
- figureColors[splitXBy] = ci[1];
- figureCoords[verticesPerRow * splitYBy] = pi[12];
- figureColors[verticesPerRow * splitYBy] = ci[2];
- figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
- figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
- mesh.figures[index] = {
- type: 'lattice',
- coords: figureCoords,
- colors: figureColors,
- verticesPerRow: verticesPerRow
- };
- }
- function decodeType6Shading(mesh, reader) {
- // A special case of Type 7. The p11, p12, p21, p22 automatically filled
- var coords = mesh.coords;
- var colors = mesh.colors;
- var ps = new Int32Array(16);
- // p00, p10, ..., p30, p01, ..., p33
- var cs = new Int32Array(4);
- // c00, c30, c03, c33
- while (reader.hasData) {
- var f = reader.readFlag();
- assert(0 <= f && f <= 3, 'Unknown type6 flag');
- var i, ii;
- var pi = coords.length;
- for (i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
- coords.push(reader.readCoordinate());
- }
- var ci = colors.length;
- for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
- colors.push(reader.readComponents());
- }
- var tmp1, tmp2, tmp3, tmp4;
- switch (f) {
- case 0:
- ps[12] = pi + 3;
- ps[13] = pi + 4;
- ps[14] = pi + 5;
- ps[15] = pi + 6;
- ps[8] = pi + 2;
- /* values for 5, 6, 9, 10 are */
- ps[11] = pi + 7;
- ps[4] = pi + 1;
- /* calculated below */
- ps[7] = pi + 8;
- ps[0] = pi;
- ps[1] = pi + 11;
- ps[2] = pi + 10;
- ps[3] = pi + 9;
- cs[2] = ci + 1;
- cs[3] = ci + 2;
- cs[0] = ci;
- cs[1] = ci + 3;
- break;
- case 1:
- tmp1 = ps[12];
- tmp2 = ps[13];
- tmp3 = ps[14];
- tmp4 = ps[15];
- ps[12] = tmp4;
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = tmp3;
- /* values for 5, 6, 9, 10 are */
- ps[11] = pi + 3;
- ps[4] = tmp2;
- /* calculated below */
- ps[7] = pi + 4;
- ps[0] = tmp1;
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- tmp1 = cs[2];
- tmp2 = cs[3];
- cs[2] = tmp2;
- cs[3] = ci;
- cs[0] = tmp1;
- cs[1] = ci + 1;
- break;
- case 2:
- tmp1 = ps[15];
- tmp2 = ps[11];
- ps[12] = ps[3];
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = ps[7];
- /* values for 5, 6, 9, 10 are */
- ps[11] = pi + 3;
- ps[4] = tmp2;
- /* calculated below */
- ps[7] = pi + 4;
- ps[0] = tmp1;
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- tmp1 = cs[3];
- cs[2] = cs[1];
- cs[3] = ci;
- cs[0] = tmp1;
- cs[1] = ci + 1;
- break;
- case 3:
- ps[12] = ps[0];
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = ps[1];
- /* values for 5, 6, 9, 10 are */
- ps[11] = pi + 3;
- ps[4] = ps[2];
- /* calculated below */
- ps[7] = pi + 4;
- ps[0] = ps[3];
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- cs[2] = cs[0];
- cs[3] = ci;
- cs[0] = cs[1];
- cs[1] = ci + 1;
- break;
- }
- // set p11, p12, p21, p22
- ps[5] = coords.length;
- coords.push([
- (-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9,
- (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9
- ]);
- ps[6] = coords.length;
- coords.push([
- (-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9,
- (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9
- ]);
- ps[9] = coords.length;
- coords.push([
- (-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9,
- (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9
- ]);
- ps[10] = coords.length;
- coords.push([
- (-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9,
- (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9
- ]);
- mesh.figures.push({
- type: 'patch',
- coords: new Int32Array(ps),
- // making copies of ps and cs
- colors: new Int32Array(cs)
- });
- }
- }
- function decodeType7Shading(mesh, reader) {
- var coords = mesh.coords;
- var colors = mesh.colors;
- var ps = new Int32Array(16);
- // p00, p10, ..., p30, p01, ..., p33
- var cs = new Int32Array(4);
- // c00, c30, c03, c33
- while (reader.hasData) {
- var f = reader.readFlag();
- assert(0 <= f && f <= 3, 'Unknown type7 flag');
- var i, ii;
- var pi = coords.length;
- for (i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
- coords.push(reader.readCoordinate());
- }
- var ci = colors.length;
- for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
- colors.push(reader.readComponents());
- }
- var tmp1, tmp2, tmp3, tmp4;
- switch (f) {
- case 0:
- ps[12] = pi + 3;
- ps[13] = pi + 4;
- ps[14] = pi + 5;
- ps[15] = pi + 6;
- ps[8] = pi + 2;
- ps[9] = pi + 13;
- ps[10] = pi + 14;
- ps[11] = pi + 7;
- ps[4] = pi + 1;
- ps[5] = pi + 12;
- ps[6] = pi + 15;
- ps[7] = pi + 8;
- ps[0] = pi;
- ps[1] = pi + 11;
- ps[2] = pi + 10;
- ps[3] = pi + 9;
- cs[2] = ci + 1;
- cs[3] = ci + 2;
- cs[0] = ci;
- cs[1] = ci + 3;
- break;
- case 1:
- tmp1 = ps[12];
- tmp2 = ps[13];
- tmp3 = ps[14];
- tmp4 = ps[15];
- ps[12] = tmp4;
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = tmp3;
- ps[9] = pi + 9;
- ps[10] = pi + 10;
- ps[11] = pi + 3;
- ps[4] = tmp2;
- ps[5] = pi + 8;
- ps[6] = pi + 11;
- ps[7] = pi + 4;
- ps[0] = tmp1;
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- tmp1 = cs[2];
- tmp2 = cs[3];
- cs[2] = tmp2;
- cs[3] = ci;
- cs[0] = tmp1;
- cs[1] = ci + 1;
- break;
- case 2:
- tmp1 = ps[15];
- tmp2 = ps[11];
- ps[12] = ps[3];
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = ps[7];
- ps[9] = pi + 9;
- ps[10] = pi + 10;
- ps[11] = pi + 3;
- ps[4] = tmp2;
- ps[5] = pi + 8;
- ps[6] = pi + 11;
- ps[7] = pi + 4;
- ps[0] = tmp1;
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- tmp1 = cs[3];
- cs[2] = cs[1];
- cs[3] = ci;
- cs[0] = tmp1;
- cs[1] = ci + 1;
- break;
- case 3:
- ps[12] = ps[0];
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = ps[1];
- ps[9] = pi + 9;
- ps[10] = pi + 10;
- ps[11] = pi + 3;
- ps[4] = ps[2];
- ps[5] = pi + 8;
- ps[6] = pi + 11;
- ps[7] = pi + 4;
- ps[0] = ps[3];
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- cs[2] = cs[0];
- cs[3] = ci;
- cs[0] = cs[1];
- cs[1] = ci + 1;
- break;
- }
- mesh.figures.push({
- type: 'patch',
- coords: new Int32Array(ps),
- // making copies of ps and cs
- colors: new Int32Array(cs)
- });
- }
- }
- function updateBounds(mesh) {
- var minX = mesh.coords[0][0], minY = mesh.coords[0][1], maxX = minX, maxY = minY;
- for (var i = 1, ii = mesh.coords.length; i < ii; i++) {
- var x = mesh.coords[i][0], y = mesh.coords[i][1];
- minX = minX > x ? x : minX;
- minY = minY > y ? y : minY;
- maxX = maxX < x ? x : maxX;
- maxY = maxY < y ? y : maxY;
- }
- mesh.bounds = [
- minX,
- minY,
- maxX,
- maxY
- ];
- }
- function packData(mesh) {
- var i, ii, j, jj;
- var coords = mesh.coords;
- var coordsPacked = new Float32Array(coords.length * 2);
- for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
- var xy = coords[i];
- coordsPacked[j++] = xy[0];
- coordsPacked[j++] = xy[1];
- }
- mesh.coords = coordsPacked;
- var colors = mesh.colors;
- var colorsPacked = new Uint8Array(colors.length * 3);
- for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
- var c = colors[i];
- colorsPacked[j++] = c[0];
- colorsPacked[j++] = c[1];
- colorsPacked[j++] = c[2];
- }
- mesh.colors = colorsPacked;
- var figures = mesh.figures;
- for (i = 0, ii = figures.length; i < ii; i++) {
- var figure = figures[i], ps = figure.coords, cs = figure.colors;
- for (j = 0, jj = ps.length; j < jj; j++) {
- ps[j] *= 2;
- cs[j] *= 3;
- }
- }
- }
- function Mesh(stream, matrix, xref, res) {
- assert(isStream(stream), 'Mesh data is not a stream');
- var dict = stream.dict;
- this.matrix = matrix;
- this.shadingType = dict.get('ShadingType');
- this.type = 'Pattern';
- this.bbox = dict.getArray('BBox');
- var cs = dict.get('ColorSpace', 'CS');
- cs = ColorSpace.parse(cs, xref, res);
- this.cs = cs;
- this.background = dict.has('Background') ? cs.getRgb(dict.get('Background'), 0) : null;
- var fnObj = dict.get('Function');
- var fn = fnObj ? PDFFunction.parseArray(xref, fnObj) : null;
- this.coords = [];
- this.colors = [];
- this.figures = [];
- var decodeContext = {
- bitsPerCoordinate: dict.get('BitsPerCoordinate'),
- bitsPerComponent: dict.get('BitsPerComponent'),
- bitsPerFlag: dict.get('BitsPerFlag'),
- decode: dict.getArray('Decode'),
- colorFn: fn,
- colorSpace: cs,
- numComps: fn ? 1 : cs.numComps
- };
- var reader = new MeshStreamReader(stream, decodeContext);
- var patchMesh = false;
- switch (this.shadingType) {
- case ShadingType.FREE_FORM_MESH:
- decodeType4Shading(this, reader);
- break;
- case ShadingType.LATTICE_FORM_MESH:
- var verticesPerRow = dict.get('VerticesPerRow') | 0;
- assert(verticesPerRow >= 2, 'Invalid VerticesPerRow');
- decodeType5Shading(this, reader, verticesPerRow);
- break;
- case ShadingType.COONS_PATCH_MESH:
- decodeType6Shading(this, reader);
- patchMesh = true;
- break;
- case ShadingType.TENSOR_PATCH_MESH:
- decodeType7Shading(this, reader);
- patchMesh = true;
- break;
- default:
- error('Unsupported mesh type.');
- break;
- }
- if (patchMesh) {
- // dirty bounds calculation for determining, how dense shall be triangles
- updateBounds(this);
- for (var i = 0, ii = this.figures.length; i < ii; i++) {
- buildFigureFromPatch(this, i);
- }
- }
- // calculate bounds
- updateBounds(this);
- packData(this);
- }
- Mesh.prototype = {
- getIR: function Mesh_getIR() {
- return [
- 'Mesh',
- this.shadingType,
- this.coords,
- this.colors,
- this.figures,
- this.bounds,
- this.matrix,
- this.bbox,
- this.background
- ];
- }
- };
- return Mesh;
- }();
- Shadings.Dummy = function DummyClosure() {
- function Dummy() {
- this.type = 'Pattern';
- }
- Dummy.prototype = {
- getIR: function Dummy_getIR() {
- return ['Dummy'];
- }
- };
- return Dummy;
- }();
- function getTilingPatternIR(operatorList, dict, args) {
- var matrix = dict.getArray('Matrix');
- var bbox = dict.getArray('BBox');
- var xstep = dict.get('XStep');
- var ystep = dict.get('YStep');
- var paintType = dict.get('PaintType');
- var tilingType = dict.get('TilingType');
- return [
- 'TilingPattern',
- args,
- operatorList,
- matrix,
- bbox,
- xstep,
- ystep,
- paintType,
- tilingType
- ];
- }
- exports.Pattern = Pattern;
- exports.getTilingPatternIR = getTilingPatternIR;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreEvaluator = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreStream, root.pdfjsCoreParser, root.pdfjsCoreImage, root.pdfjsCoreColorSpace, root.pdfjsCoreMurmurHash3, root.pdfjsCoreFonts, root.pdfjsCoreFunction, root.pdfjsCorePattern, root.pdfjsCoreCMap, root.pdfjsCoreMetrics, root.pdfjsCoreBidi, root.pdfjsCoreEncodings, root.pdfjsCoreStandardFonts, root.pdfjsCoreUnicode, root.pdfjsCoreGlyphList);
- }(this, function (exports, sharedUtil, corePrimitives, coreStream, coreParser, coreImage, coreColorSpace, coreMurmurHash3, coreFonts, coreFunction, corePattern, coreCMap, coreMetrics, coreBidi, coreEncodings, coreStandardFonts, coreUnicode, coreGlyphList) {
- var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX;
- var IDENTITY_MATRIX = sharedUtil.IDENTITY_MATRIX;
- var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES;
- var ImageKind = sharedUtil.ImageKind;
- var OPS = sharedUtil.OPS;
- var TextRenderingMode = sharedUtil.TextRenderingMode;
- var Util = sharedUtil.Util;
- var assert = sharedUtil.assert;
- var createPromiseCapability = sharedUtil.createPromiseCapability;
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var isArray = sharedUtil.isArray;
- var isNum = sharedUtil.isNum;
- var isString = sharedUtil.isString;
- var getLookupTableFactory = sharedUtil.getLookupTableFactory;
- var warn = sharedUtil.warn;
- var Dict = corePrimitives.Dict;
- var Name = corePrimitives.Name;
- var isCmd = corePrimitives.isCmd;
- var isDict = corePrimitives.isDict;
- var isName = corePrimitives.isName;
- var isRef = corePrimitives.isRef;
- var isStream = corePrimitives.isStream;
- var DecodeStream = coreStream.DecodeStream;
- var JpegStream = coreStream.JpegStream;
- var Stream = coreStream.Stream;
- var Lexer = coreParser.Lexer;
- var Parser = coreParser.Parser;
- var isEOF = coreParser.isEOF;
- var PDFImage = coreImage.PDFImage;
- var ColorSpace = coreColorSpace.ColorSpace;
- var MurmurHash3_64 = coreMurmurHash3.MurmurHash3_64;
- var ErrorFont = coreFonts.ErrorFont;
- var FontFlags = coreFonts.FontFlags;
- var Font = coreFonts.Font;
- var IdentityToUnicodeMap = coreFonts.IdentityToUnicodeMap;
- var ToUnicodeMap = coreFonts.ToUnicodeMap;
- var getFontType = coreFonts.getFontType;
- var isPDFFunction = coreFunction.isPDFFunction;
- var PDFFunction = coreFunction.PDFFunction;
- var Pattern = corePattern.Pattern;
- var getTilingPatternIR = corePattern.getTilingPatternIR;
- var CMapFactory = coreCMap.CMapFactory;
- var IdentityCMap = coreCMap.IdentityCMap;
- var getMetrics = coreMetrics.getMetrics;
- var bidi = coreBidi.bidi;
- var WinAnsiEncoding = coreEncodings.WinAnsiEncoding;
- var StandardEncoding = coreEncodings.StandardEncoding;
- var MacRomanEncoding = coreEncodings.MacRomanEncoding;
- var SymbolSetEncoding = coreEncodings.SymbolSetEncoding;
- var ZapfDingbatsEncoding = coreEncodings.ZapfDingbatsEncoding;
- var getEncoding = coreEncodings.getEncoding;
- var getStdFontMap = coreStandardFonts.getStdFontMap;
- var getSerifFonts = coreStandardFonts.getSerifFonts;
- var getSymbolsFonts = coreStandardFonts.getSymbolsFonts;
- var getNormalizedUnicodes = coreUnicode.getNormalizedUnicodes;
- var reverseIfRtl = coreUnicode.reverseIfRtl;
- var getUnicodeForGlyph = coreUnicode.getUnicodeForGlyph;
- var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode;
- var PartialEvaluator = function PartialEvaluatorClosure() {
- var DefaultPartialEvaluatorOptions = {
- forceDataSchema: false,
- maxImageSize: -1,
- disableFontFace: false,
- cMapOptions: {
- url: null,
- packed: false
- }
- };
- function NativeImageDecoder(xref, resources, handler, forceDataSchema) {
- this.xref = xref;
- this.resources = resources;
- this.handler = handler;
- this.forceDataSchema = forceDataSchema;
- }
- NativeImageDecoder.prototype = {
- canDecode: function (image) {
- return image instanceof JpegStream && NativeImageDecoder.isDecodable(image, this.xref, this.resources);
- },
- decode: function (image) {
- // For natively supported JPEGs send them to the main thread for decoding.
- var dict = image.dict;
- var colorSpace = dict.get('ColorSpace', 'CS');
- colorSpace = ColorSpace.parse(colorSpace, this.xref, this.resources);
- var numComps = colorSpace.numComps;
- var decodePromise = this.handler.sendWithPromise('JpegDecode', [
- image.getIR(this.forceDataSchema),
- numComps
- ]);
- return decodePromise.then(function (message) {
- var data = message.data;
- return new Stream(data, 0, data.length, image.dict);
- });
- }
- };
- /**
- * Checks if the image can be decoded and displayed by the browser without any
- * further processing such as color space conversions.
- */
- NativeImageDecoder.isSupported = function NativeImageDecoder_isSupported(image, xref, res) {
- var dict = image.dict;
- if (dict.has('DecodeParms') || dict.has('DP')) {
- return false;
- }
- var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res);
- return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') && cs.isDefaultDecode(dict.getArray('Decode', 'D'));
- };
- /**
- * Checks if the image can be decoded by the browser.
- */
- NativeImageDecoder.isDecodable = function NativeImageDecoder_isDecodable(image, xref, res) {
- var dict = image.dict;
- if (dict.has('DecodeParms') || dict.has('DP')) {
- return false;
- }
- var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res);
- return (cs.numComps === 1 || cs.numComps === 3) && cs.isDefaultDecode(dict.getArray('Decode', 'D'));
- };
- function PartialEvaluator(pdfManager, xref, handler, pageIndex, uniquePrefix, idCounters, fontCache, options) {
- this.pdfManager = pdfManager;
- this.xref = xref;
- this.handler = handler;
- this.pageIndex = pageIndex;
- this.uniquePrefix = uniquePrefix;
- this.idCounters = idCounters;
- this.fontCache = fontCache;
- this.options = options || DefaultPartialEvaluatorOptions;
- }
- // Trying to minimize Date.now() usage and check every 100 time
- var TIME_SLOT_DURATION_MS = 20;
- var CHECK_TIME_EVERY = 100;
- function TimeSlotManager() {
- this.reset();
- }
- TimeSlotManager.prototype = {
- check: function TimeSlotManager_check() {
- if (++this.checked < CHECK_TIME_EVERY) {
- return false;
- }
- this.checked = 0;
- return this.endTime <= Date.now();
- },
- reset: function TimeSlotManager_reset() {
- this.endTime = Date.now() + TIME_SLOT_DURATION_MS;
- this.checked = 0;
- }
- };
- var deferred = Promise.resolve();
- var TILING_PATTERN = 1, SHADING_PATTERN = 2;
- PartialEvaluator.prototype = {
- hasBlendModes: function PartialEvaluator_hasBlendModes(resources) {
- if (!isDict(resources)) {
- return false;
- }
- var processed = Object.create(null);
- if (resources.objId) {
- processed[resources.objId] = true;
- }
- var nodes = [resources], xref = this.xref;
- while (nodes.length) {
- var key, i, ii;
- var node = nodes.shift();
- // First check the current resources for blend modes.
- var graphicStates = node.get('ExtGState');
- if (isDict(graphicStates)) {
- var graphicStatesKeys = graphicStates.getKeys();
- for (i = 0, ii = graphicStatesKeys.length; i < ii; i++) {
- key = graphicStatesKeys[i];
- var graphicState = graphicStates.get(key);
- var bm = graphicState.get('BM');
- if (isName(bm) && bm.name !== 'Normal') {
- return true;
- }
- }
- }
- // Descend into the XObjects to look for more resources and blend modes.
- var xObjects = node.get('XObject');
- if (!isDict(xObjects)) {
- continue;
- }
- var xObjectsKeys = xObjects.getKeys();
- for (i = 0, ii = xObjectsKeys.length; i < ii; i++) {
- key = xObjectsKeys[i];
- var xObject = xObjects.getRaw(key);
- if (isRef(xObject)) {
- if (processed[xObject.toString()]) {
- // The XObject has already been processed, and by avoiding a
- // redundant `xref.fetch` we can *significantly* reduce the load
- // time for badly generated PDF files (fixes issue6961.pdf).
- continue;
- }
- xObject = xref.fetch(xObject);
- }
- if (!isStream(xObject)) {
- continue;
- }
- if (xObject.dict.objId) {
- if (processed[xObject.dict.objId]) {
- // stream has objId and is processed already
- continue;
- }
- processed[xObject.dict.objId] = true;
- }
- var xResources = xObject.dict.get('Resources');
- // Checking objId to detect an infinite loop.
- if (isDict(xResources) && (!xResources.objId || !processed[xResources.objId])) {
- nodes.push(xResources);
- if (xResources.objId) {
- processed[xResources.objId] = true;
- }
- }
- }
- }
- return false;
- },
- buildFormXObject: function PartialEvaluator_buildFormXObject(resources, xobj, smask, operatorList, task, initialState) {
- var matrix = xobj.dict.getArray('Matrix');
- var bbox = xobj.dict.getArray('BBox');
- var group = xobj.dict.get('Group');
- if (group) {
- var groupOptions = {
- matrix: matrix,
- bbox: bbox,
- smask: smask,
- isolated: false,
- knockout: false
- };
- var groupSubtype = group.get('S');
- var colorSpace;
- if (isName(groupSubtype, 'Transparency')) {
- groupOptions.isolated = group.get('I') || false;
- groupOptions.knockout = group.get('K') || false;
- colorSpace = group.has('CS') ? ColorSpace.parse(group.get('CS'), this.xref, resources) : null;
- }
- if (smask && smask.backdrop) {
- colorSpace = colorSpace || ColorSpace.singletons.rgb;
- smask.backdrop = colorSpace.getRgb(smask.backdrop, 0);
- }
- operatorList.addOp(OPS.beginGroup, [groupOptions]);
- }
- operatorList.addOp(OPS.paintFormXObjectBegin, [
- matrix,
- bbox
- ]);
- return this.getOperatorList(xobj, task, xobj.dict.get('Resources') || resources, operatorList, initialState).then(function () {
- operatorList.addOp(OPS.paintFormXObjectEnd, []);
- if (group) {
- operatorList.addOp(OPS.endGroup, [groupOptions]);
- }
- });
- },
- buildPaintImageXObject: function PartialEvaluator_buildPaintImageXObject(resources, image, inline, operatorList, cacheKey, imageCache) {
- var self = this;
- var dict = image.dict;
- var w = dict.get('Width', 'W');
- var h = dict.get('Height', 'H');
- if (!(w && isNum(w)) || !(h && isNum(h))) {
- warn('Image dimensions are missing, or not numbers.');
- return;
- }
- var maxImageSize = this.options.maxImageSize;
- if (maxImageSize !== -1 && w * h > maxImageSize) {
- warn('Image exceeded maximum allowed size and was removed.');
- return;
- }
- var imageMask = dict.get('ImageMask', 'IM') || false;
- var imgData, args;
- if (imageMask) {
- // This depends on a tmpCanvas being filled with the
- // current fillStyle, such that processing the pixel
- // data can't be done here. Instead of creating a
- // complete PDFImage, only read the information needed
- // for later.
- var width = dict.get('Width', 'W');
- var height = dict.get('Height', 'H');
- var bitStrideLength = width + 7 >> 3;
- var imgArray = image.getBytes(bitStrideLength * height);
- var decode = dict.getArray('Decode', 'D');
- var inverseDecode = !!decode && decode[0] > 0;
- imgData = PDFImage.createMask(imgArray, width, height, image instanceof DecodeStream, inverseDecode);
- imgData.cached = true;
- args = [imgData];
- operatorList.addOp(OPS.paintImageMaskXObject, args);
- if (cacheKey) {
- imageCache[cacheKey] = {
- fn: OPS.paintImageMaskXObject,
- args: args
- };
- }
- return;
- }
- var softMask = dict.get('SMask', 'SM') || false;
- var mask = dict.get('Mask') || false;
- var SMALL_IMAGE_DIMENSIONS = 200;
- // Inlining small images into the queue as RGB data
- if (inline && !softMask && !mask && !(image instanceof JpegStream) && w + h < SMALL_IMAGE_DIMENSIONS) {
- var imageObj = new PDFImage(this.xref, resources, image, inline, null, null);
- // We force the use of RGBA_32BPP images here, because we can't handle
- // any other kind.
- imgData = imageObj.createImageData(/* forceRGBA = */
- true);
- operatorList.addOp(OPS.paintInlineImageXObject, [imgData]);
- return;
- }
- // If there is no imageMask, create the PDFImage and a lot
- // of image processing can be done here.
- var uniquePrefix = this.uniquePrefix || '';
- var objId = 'img_' + uniquePrefix + ++this.idCounters.obj;
- operatorList.addDependency(objId);
- args = [
- objId,
- w,
- h
- ];
- if (!softMask && !mask && image instanceof JpegStream && NativeImageDecoder.isSupported(image, this.xref, resources)) {
- // These JPEGs don't need any more processing so we can just send it.
- operatorList.addOp(OPS.paintJpegXObject, args);
- this.handler.send('obj', [
- objId,
- this.pageIndex,
- 'JpegStream',
- image.getIR(this.options.forceDataSchema)
- ]);
- return;
- }
- // Creates native image decoder only if a JPEG image or mask is present.
- var nativeImageDecoder = null;
- if (image instanceof JpegStream || mask instanceof JpegStream || softMask instanceof JpegStream) {
- nativeImageDecoder = new NativeImageDecoder(self.xref, resources, self.handler, self.options.forceDataSchema);
- }
- PDFImage.buildImage(self.handler, self.xref, resources, image, inline, nativeImageDecoder).then(function (imageObj) {
- var imgData = imageObj.createImageData(/* forceRGBA = */
- false);
- self.handler.send('obj', [
- objId,
- self.pageIndex,
- 'Image',
- imgData
- ], [imgData.data.buffer]);
- }).then(undefined, function (reason) {
- warn('Unable to decode image: ' + reason);
- self.handler.send('obj', [
- objId,
- self.pageIndex,
- 'Image',
- null
- ]);
- });
- operatorList.addOp(OPS.paintImageXObject, args);
- if (cacheKey) {
- imageCache[cacheKey] = {
- fn: OPS.paintImageXObject,
- args: args
- };
- }
- },
- handleSMask: function PartialEvaluator_handleSmask(smask, resources, operatorList, task, stateManager) {
- var smaskContent = smask.get('G');
- var smaskOptions = {
- subtype: smask.get('S').name,
- backdrop: smask.get('BC')
- };
- // The SMask might have a alpha/luminosity value transfer function --
- // we will build a map of integer values in range 0..255 to be fast.
- var transferObj = smask.get('TR');
- if (isPDFFunction(transferObj)) {
- var transferFn = PDFFunction.parse(this.xref, transferObj);
- var transferMap = new Uint8Array(256);
- var tmp = new Float32Array(1);
- for (var i = 0; i < 256; i++) {
- tmp[0] = i / 255;
- transferFn(tmp, 0, tmp, 0);
- transferMap[i] = tmp[0] * 255 | 0;
- }
- smaskOptions.transferMap = transferMap;
- }
- return this.buildFormXObject(resources, smaskContent, smaskOptions, operatorList, task, stateManager.state.clone());
- },
- handleTilingType: function PartialEvaluator_handleTilingType(fn, args, resources, pattern, patternDict, operatorList, task) {
- // Create an IR of the pattern code.
- var tilingOpList = new OperatorList();
- // Merge the available resources, to prevent issues when the patternDict
- // is missing some /Resources entries (fixes issue6541.pdf).
- var resourcesArray = [
- patternDict.get('Resources'),
- resources
- ];
- var patternResources = Dict.merge(this.xref, resourcesArray);
- return this.getOperatorList(pattern, task, patternResources, tilingOpList).then(function () {
- // Add the dependencies to the parent operator list so they are
- // resolved before sub operator list is executed synchronously.
- operatorList.addDependencies(tilingOpList.dependencies);
- operatorList.addOp(fn, getTilingPatternIR({
- fnArray: tilingOpList.fnArray,
- argsArray: tilingOpList.argsArray
- }, patternDict, args));
- });
- },
- handleSetFont: function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef, operatorList, task, state) {
- // TODO(mack): Not needed?
- var fontName;
- if (fontArgs) {
- fontArgs = fontArgs.slice();
- fontName = fontArgs[0].name;
- }
- var self = this;
- return this.loadFont(fontName, fontRef, this.xref, resources).then(function (translated) {
- if (!translated.font.isType3Font) {
- return translated;
- }
- return translated.loadType3Data(self, resources, operatorList, task).then(function () {
- return translated;
- }, function (reason) {
- // Error in the font data -- sending unsupported feature notification.
- self.handler.send('UnsupportedFeature', { featureId: UNSUPPORTED_FEATURES.font });
- return new TranslatedFont('g_font_error', new ErrorFont('Type3 font load error: ' + reason), translated.font);
- });
- }).then(function (translated) {
- state.font = translated.font;
- translated.send(self.handler);
- return translated.loadedName;
- });
- },
- handleText: function PartialEvaluator_handleText(chars, state) {
- var font = state.font;
- var glyphs = font.charsToGlyphs(chars);
- var isAddToPathSet = !!(state.textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG);
- if (font.data && (isAddToPathSet || this.options.disableFontFace)) {
- var buildPath = function (fontChar) {
- if (!font.renderer.hasBuiltPath(fontChar)) {
- var path = font.renderer.getPathJs(fontChar);
- this.handler.send('commonobj', [
- font.loadedName + '_path_' + fontChar,
- 'FontPath',
- path
- ]);
- }
- }.bind(this);
- for (var i = 0, ii = glyphs.length; i < ii; i++) {
- var glyph = glyphs[i];
- buildPath(glyph.fontChar);
- // If the glyph has an accent we need to build a path for its
- // fontChar too, otherwise CanvasGraphics_paintChar will fail.
- var accent = glyph.accent;
- if (accent && accent.fontChar) {
- buildPath(accent.fontChar);
- }
- }
- }
- return glyphs;
- },
- setGState: function PartialEvaluator_setGState(resources, gState, operatorList, task, xref, stateManager) {
- // This array holds the converted/processed state data.
- var gStateObj = [];
- var gStateKeys = gState.getKeys();
- var self = this;
- var promise = Promise.resolve();
- for (var i = 0, ii = gStateKeys.length; i < ii; i++) {
- var key = gStateKeys[i];
- var value = gState.get(key);
- switch (key) {
- case 'Type':
- break;
- case 'LW':
- case 'LC':
- case 'LJ':
- case 'ML':
- case 'D':
- case 'RI':
- case 'FL':
- case 'CA':
- case 'ca':
- gStateObj.push([
- key,
- value
- ]);
- break;
- case 'Font':
- promise = promise.then(function () {
- return self.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) {
- operatorList.addDependency(loadedName);
- gStateObj.push([
- key,
- [
- loadedName,
- value[1]
- ]
- ]);
- });
- });
- break;
- case 'BM':
- gStateObj.push([
- key,
- value
- ]);
- break;
- case 'SMask':
- if (isName(value, 'None')) {
- gStateObj.push([
- key,
- false
- ]);
- break;
- }
- if (isDict(value)) {
- promise = promise.then(function (dict) {
- return self.handleSMask(dict, resources, operatorList, task, stateManager);
- }.bind(this, value));
- gStateObj.push([
- key,
- true
- ]);
- } else {
- warn('Unsupported SMask type');
- }
- break;
- // Only generate info log messages for the following since
- // they are unlikely to have a big impact on the rendering.
- case 'OP':
- case 'op':
- case 'OPM':
- case 'BG':
- case 'BG2':
- case 'UCR':
- case 'UCR2':
- case 'TR':
- case 'TR2':
- case 'HT':
- case 'SM':
- case 'SA':
- case 'AIS':
- case 'TK':
- // TODO implement these operators.
- info('graphic state operator ' + key);
- break;
- default:
- info('Unknown graphic state operator ' + key);
- break;
- }
- }
- return promise.then(function () {
- if (gStateObj.length > 0) {
- operatorList.addOp(OPS.setGState, [gStateObj]);
- }
- });
- },
- loadFont: function PartialEvaluator_loadFont(fontName, font, xref, resources) {
- function errorFont() {
- return Promise.resolve(new TranslatedFont('g_font_error', new ErrorFont('Font ' + fontName + ' is not available'), font));
- }
- var fontRef;
- if (font) {
- // Loading by ref.
- assert(isRef(font));
- fontRef = font;
- } else {
- // Loading by name.
- var fontRes = resources.get('Font');
- if (fontRes) {
- fontRef = fontRes.getRaw(fontName);
- } else {
- warn('fontRes not available');
- return errorFont();
- }
- }
- if (!fontRef) {
- warn('fontRef not available');
- return errorFont();
- }
- if (this.fontCache.has(fontRef)) {
- return this.fontCache.get(fontRef);
- }
- font = xref.fetchIfRef(fontRef);
- if (!isDict(font)) {
- return errorFont();
- }
- // We are holding `font.translated` references just for `fontRef`s that
- // are not actually `Ref`s, but rather `Dict`s. See explanation below.
- if (font.translated) {
- return font.translated;
- }
- var fontCapability = createPromiseCapability();
- var preEvaluatedFont = this.preEvaluateFont(font, xref);
- var descriptor = preEvaluatedFont.descriptor;
- var fontRefIsRef = isRef(fontRef), fontID;
- if (fontRefIsRef) {
- fontID = fontRef.toString();
- }
- if (isDict(descriptor)) {
- if (!descriptor.fontAliases) {
- descriptor.fontAliases = Object.create(null);
- }
- var fontAliases = descriptor.fontAliases;
- var hash = preEvaluatedFont.hash;
- if (fontAliases[hash]) {
- var aliasFontRef = fontAliases[hash].aliasRef;
- if (fontRefIsRef && aliasFontRef && this.fontCache.has(aliasFontRef)) {
- this.fontCache.putAlias(fontRef, aliasFontRef);
- return this.fontCache.get(fontRef);
- }
- } else {
- fontAliases[hash] = { fontID: Font.getFontID() };
- }
- if (fontRefIsRef) {
- fontAliases[hash].aliasRef = fontRef;
- }
- fontID = fontAliases[hash].fontID;
- }
- // Workaround for bad PDF generators that reference fonts incorrectly,
- // where `fontRef` is a `Dict` rather than a `Ref` (fixes bug946506.pdf).
- // In this case we should not put the font into `this.fontCache` (which is
- // a `RefSetCache`), since it's not meaningful to use a `Dict` as a key.
- //
- // However, if we don't cache the font it's not possible to remove it
- // when `cleanup` is triggered from the API, which causes issues on
- // subsequent rendering operations (see issue7403.pdf).
- // A simple workaround would be to just not hold `font.translated`
- // references in this case, but this would force us to unnecessarily load
- // the same fonts over and over.
- //
- // Instead, we cheat a bit by attempting to use a modified `fontID` as a
- // key in `this.fontCache`, to allow the font to be cached.
- // NOTE: This works because `RefSetCache` calls `toString()` on provided
- // keys. Also, since `fontRef` is used when getting cached fonts,
- // we'll not accidentally match fonts cached with the `fontID`.
- if (fontRefIsRef) {
- this.fontCache.put(fontRef, fontCapability.promise);
- } else {
- if (!fontID) {
- fontID = (this.uniquePrefix || 'F_') + ++this.idCounters.obj;
- }
- this.fontCache.put('id_' + fontID, fontCapability.promise);
- }
- assert(fontID, 'The "fontID" must be defined.');
- // Keep track of each font we translated so the caller can
- // load them asynchronously before calling display on a page.
- font.loadedName = 'g_' + this.pdfManager.docId + '_f' + fontID;
- font.translated = fontCapability.promise;
- // TODO move promises into translate font
- var translatedPromise;
- try {
- translatedPromise = this.translateFont(preEvaluatedFont, xref);
- } catch (e) {
- translatedPromise = Promise.reject(e);
- }
- var self = this;
- translatedPromise.then(function (translatedFont) {
- if (translatedFont.fontType !== undefined) {
- var xrefFontStats = xref.stats.fontTypes;
- xrefFontStats[translatedFont.fontType] = true;
- }
- fontCapability.resolve(new TranslatedFont(font.loadedName, translatedFont, font));
- }, function (reason) {
- // TODO fontCapability.reject?
- // Error in the font data -- sending unsupported feature notification.
- self.handler.send('UnsupportedFeature', { featureId: UNSUPPORTED_FEATURES.font });
- try {
- // error, but it's still nice to have font type reported
- var descriptor = preEvaluatedFont.descriptor;
- var fontFile3 = descriptor && descriptor.get('FontFile3');
- var subtype = fontFile3 && fontFile3.get('Subtype');
- var fontType = getFontType(preEvaluatedFont.type, subtype && subtype.name);
- var xrefFontStats = xref.stats.fontTypes;
- xrefFontStats[fontType] = true;
- } catch (ex) {
- }
- fontCapability.resolve(new TranslatedFont(font.loadedName, new ErrorFont(reason instanceof Error ? reason.message : reason), font));
- });
- return fontCapability.promise;
- },
- buildPath: function PartialEvaluator_buildPath(operatorList, fn, args) {
- var lastIndex = operatorList.length - 1;
- if (!args) {
- args = [];
- }
- if (lastIndex < 0 || operatorList.fnArray[lastIndex] !== OPS.constructPath) {
- operatorList.addOp(OPS.constructPath, [
- [fn],
- args
- ]);
- } else {
- var opArgs = operatorList.argsArray[lastIndex];
- opArgs[0].push(fn);
- Array.prototype.push.apply(opArgs[1], args);
- }
- },
- handleColorN: function PartialEvaluator_handleColorN(operatorList, fn, args, cs, patterns, resources, task, xref) {
- // compile tiling patterns
- var patternName = args[args.length - 1];
- // SCN/scn applies patterns along with normal colors
- var pattern;
- if (isName(patternName) && (pattern = patterns.get(patternName.name))) {
- var dict = isStream(pattern) ? pattern.dict : pattern;
- var typeNum = dict.get('PatternType');
- if (typeNum === TILING_PATTERN) {
- var color = cs.base ? cs.base.getRgb(args, 0) : null;
- return this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task);
- } else if (typeNum === SHADING_PATTERN) {
- var shading = dict.get('Shading');
- var matrix = dict.getArray('Matrix');
- pattern = Pattern.parseShading(shading, matrix, xref, resources, this.handler);
- operatorList.addOp(fn, pattern.getIR());
- return Promise.resolve();
- } else {
- return Promise.reject('Unknown PatternType: ' + typeNum);
- }
- }
- // TODO shall we fail here?
- operatorList.addOp(fn, args);
- return Promise.resolve();
- },
- getOperatorList: function PartialEvaluator_getOperatorList(stream, task, resources, operatorList, initialState) {
- var self = this;
- var xref = this.xref;
- var imageCache = Object.create(null);
- assert(operatorList);
- resources = resources || Dict.empty;
- var xobjs = resources.get('XObject') || Dict.empty;
- var patterns = resources.get('Pattern') || Dict.empty;
- var stateManager = new StateManager(initialState || new EvalState());
- var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
- var timeSlotManager = new TimeSlotManager();
- return new Promise(function promiseBody(resolve, reject) {
- var next = function (promise) {
- promise.then(function () {
- try {
- promiseBody(resolve, reject);
- } catch (ex) {
- reject(ex);
- }
- }, reject);
- };
- task.ensureNotTerminated();
- timeSlotManager.reset();
- var stop, operation = {}, i, ii, cs;
- while (!(stop = timeSlotManager.check())) {
- // The arguments parsed by read() are used beyond this loop, so we
- // cannot reuse the same array on each iteration. Therefore we pass
- // in |null| as the initial value (see the comment on
- // EvaluatorPreprocessor_read() for why).
- operation.args = null;
- if (!preprocessor.read(operation)) {
- break;
- }
- var args = operation.args;
- var fn = operation.fn;
- switch (fn | 0) {
- case OPS.paintXObject:
- if (args[0].code) {
- break;
- }
- // eagerly compile XForm objects
- var name = args[0].name;
- if (!name) {
- warn('XObject must be referred to by name.');
- continue;
- }
- if (imageCache[name] !== undefined) {
- operatorList.addOp(imageCache[name].fn, imageCache[name].args);
- args = null;
- continue;
- }
- var xobj = xobjs.get(name);
- if (xobj) {
- assert(isStream(xobj), 'XObject should be a stream');
- var type = xobj.dict.get('Subtype');
- assert(isName(type), 'XObject should have a Name subtype');
- if (type.name === 'Form') {
- stateManager.save();
- next(self.buildFormXObject(resources, xobj, null, operatorList, task, stateManager.state.clone()).then(function () {
- stateManager.restore();
- }));
- return;
- } else if (type.name === 'Image') {
- self.buildPaintImageXObject(resources, xobj, false, operatorList, name, imageCache);
- args = null;
- continue;
- } else if (type.name === 'PS') {
- // PostScript XObjects are unused when viewing documents.
- // See section 4.7.1 of Adobe's PDF reference.
- info('Ignored XObject subtype PS');
- continue;
- } else {
- error('Unhandled XObject subtype ' + type.name);
- }
- }
- break;
- case OPS.setFont:
- var fontSize = args[1];
- // eagerly collect all fonts
- next(self.handleSetFont(resources, args, null, operatorList, task, stateManager.state).then(function (loadedName) {
- operatorList.addDependency(loadedName);
- operatorList.addOp(OPS.setFont, [
- loadedName,
- fontSize
- ]);
- }));
- return;
- case OPS.endInlineImage:
- var cacheKey = args[0].cacheKey;
- if (cacheKey) {
- var cacheEntry = imageCache[cacheKey];
- if (cacheEntry !== undefined) {
- operatorList.addOp(cacheEntry.fn, cacheEntry.args);
- args = null;
- continue;
- }
- }
- self.buildPaintImageXObject(resources, args[0], true, operatorList, cacheKey, imageCache);
- args = null;
- continue;
- case OPS.showText:
- args[0] = self.handleText(args[0], stateManager.state);
- break;
- case OPS.showSpacedText:
- var arr = args[0];
- var combinedGlyphs = [];
- var arrLength = arr.length;
- var state = stateManager.state;
- for (i = 0; i < arrLength; ++i) {
- var arrItem = arr[i];
- if (isString(arrItem)) {
- Array.prototype.push.apply(combinedGlyphs, self.handleText(arrItem, state));
- } else if (isNum(arrItem)) {
- combinedGlyphs.push(arrItem);
- }
- }
- args[0] = combinedGlyphs;
- fn = OPS.showText;
- break;
- case OPS.nextLineShowText:
- operatorList.addOp(OPS.nextLine);
- args[0] = self.handleText(args[0], stateManager.state);
- fn = OPS.showText;
- break;
- case OPS.nextLineSetSpacingShowText:
- operatorList.addOp(OPS.nextLine);
- operatorList.addOp(OPS.setWordSpacing, [args.shift()]);
- operatorList.addOp(OPS.setCharSpacing, [args.shift()]);
- args[0] = self.handleText(args[0], stateManager.state);
- fn = OPS.showText;
- break;
- case OPS.setTextRenderingMode:
- stateManager.state.textRenderingMode = args[0];
- break;
- case OPS.setFillColorSpace:
- stateManager.state.fillColorSpace = ColorSpace.parse(args[0], xref, resources);
- continue;
- case OPS.setStrokeColorSpace:
- stateManager.state.strokeColorSpace = ColorSpace.parse(args[0], xref, resources);
- continue;
- case OPS.setFillColor:
- cs = stateManager.state.fillColorSpace;
- args = cs.getRgb(args, 0);
- fn = OPS.setFillRGBColor;
- break;
- case OPS.setStrokeColor:
- cs = stateManager.state.strokeColorSpace;
- args = cs.getRgb(args, 0);
- fn = OPS.setStrokeRGBColor;
- break;
- case OPS.setFillGray:
- stateManager.state.fillColorSpace = ColorSpace.singletons.gray;
- args = ColorSpace.singletons.gray.getRgb(args, 0);
- fn = OPS.setFillRGBColor;
- break;
- case OPS.setStrokeGray:
- stateManager.state.strokeColorSpace = ColorSpace.singletons.gray;
- args = ColorSpace.singletons.gray.getRgb(args, 0);
- fn = OPS.setStrokeRGBColor;
- break;
- case OPS.setFillCMYKColor:
- stateManager.state.fillColorSpace = ColorSpace.singletons.cmyk;
- args = ColorSpace.singletons.cmyk.getRgb(args, 0);
- fn = OPS.setFillRGBColor;
- break;
- case OPS.setStrokeCMYKColor:
- stateManager.state.strokeColorSpace = ColorSpace.singletons.cmyk;
- args = ColorSpace.singletons.cmyk.getRgb(args, 0);
- fn = OPS.setStrokeRGBColor;
- break;
- case OPS.setFillRGBColor:
- stateManager.state.fillColorSpace = ColorSpace.singletons.rgb;
- args = ColorSpace.singletons.rgb.getRgb(args, 0);
- break;
- case OPS.setStrokeRGBColor:
- stateManager.state.strokeColorSpace = ColorSpace.singletons.rgb;
- args = ColorSpace.singletons.rgb.getRgb(args, 0);
- break;
- case OPS.setFillColorN:
- cs = stateManager.state.fillColorSpace;
- if (cs.name === 'Pattern') {
- next(self.handleColorN(operatorList, OPS.setFillColorN, args, cs, patterns, resources, task, xref));
- return;
- }
- args = cs.getRgb(args, 0);
- fn = OPS.setFillRGBColor;
- break;
- case OPS.setStrokeColorN:
- cs = stateManager.state.strokeColorSpace;
- if (cs.name === 'Pattern') {
- next(self.handleColorN(operatorList, OPS.setStrokeColorN, args, cs, patterns, resources, task, xref));
- return;
- }
- args = cs.getRgb(args, 0);
- fn = OPS.setStrokeRGBColor;
- break;
- case OPS.shadingFill:
- var shadingRes = resources.get('Shading');
- if (!shadingRes) {
- error('No shading resource found');
- }
- var shading = shadingRes.get(args[0].name);
- if (!shading) {
- error('No shading object found');
- }
- var shadingFill = Pattern.parseShading(shading, null, xref, resources, self.handler);
- var patternIR = shadingFill.getIR();
- args = [patternIR];
- fn = OPS.shadingFill;
- break;
- case OPS.setGState:
- var dictName = args[0];
- var extGState = resources.get('ExtGState');
- if (!isDict(extGState) || !extGState.has(dictName.name)) {
- break;
- }
- var gState = extGState.get(dictName.name);
- next(self.setGState(resources, gState, operatorList, task, xref, stateManager));
- return;
- case OPS.moveTo:
- case OPS.lineTo:
- case OPS.curveTo:
- case OPS.curveTo2:
- case OPS.curveTo3:
- case OPS.closePath:
- self.buildPath(operatorList, fn, args);
- continue;
- case OPS.rectangle:
- self.buildPath(operatorList, fn, args);
- continue;
- case OPS.markPoint:
- case OPS.markPointProps:
- case OPS.beginMarkedContent:
- case OPS.beginMarkedContentProps:
- case OPS.endMarkedContent:
- case OPS.beginCompat:
- case OPS.endCompat:
- // Ignore operators where the corresponding handlers are known to
- // be no-op in CanvasGraphics (display/canvas.js). This prevents
- // serialization errors and is also a bit more efficient.
- // We could also try to serialize all objects in a general way,
- // e.g. as done in https://github.com/mozilla/pdf.js/pull/6266,
- // but doing so is meaningless without knowing the semantics.
- continue;
- default:
- // Note: Ignore the operator if it has `Dict` arguments, since
- // those are non-serializable, otherwise postMessage will throw
- // "An object could not be cloned.".
- if (args !== null) {
- for (i = 0, ii = args.length; i < ii; i++) {
- if (args[i] instanceof Dict) {
- break;
- }
- }
- if (i < ii) {
- warn('getOperatorList - ignoring operator: ' + fn);
- continue;
- }
- }
- }
- operatorList.addOp(fn, args);
- }
- if (stop) {
- next(deferred);
- return;
- }
- // Some PDFs don't close all restores inside object/form.
- // Closing those for them.
- for (i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) {
- operatorList.addOp(OPS.restore, []);
- }
- resolve();
- });
- },
- getTextContent: function PartialEvaluator_getTextContent(stream, task, resources, stateManager, normalizeWhitespace, combineTextItems) {
- stateManager = stateManager || new StateManager(new TextState());
- var WhitespaceRegexp = /\s/g;
- var textContent = {
- items: [],
- styles: Object.create(null)
- };
- var textContentItem = {
- initialized: false,
- str: [],
- width: 0,
- height: 0,
- vertical: false,
- lastAdvanceWidth: 0,
- lastAdvanceHeight: 0,
- textAdvanceScale: 0,
- spaceWidth: 0,
- fakeSpaceMin: Infinity,
- fakeMultiSpaceMin: Infinity,
- fakeMultiSpaceMax: -0,
- textRunBreakAllowed: false,
- transform: null,
- fontName: null
- };
- var SPACE_FACTOR = 0.3;
- var MULTI_SPACE_FACTOR = 1.5;
- var MULTI_SPACE_FACTOR_MAX = 4;
- var self = this;
- var xref = this.xref;
- resources = xref.fetchIfRef(resources) || Dict.empty;
- // The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd.
- var xobjs = null;
- var xobjsCache = Object.create(null);
- var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
- var textState;
- function ensureTextContentItem() {
- if (textContentItem.initialized) {
- return textContentItem;
- }
- var font = textState.font;
- if (!(font.loadedName in textContent.styles)) {
- textContent.styles[font.loadedName] = {
- fontFamily: font.fallbackName,
- ascent: font.ascent,
- descent: font.descent,
- vertical: font.vertical
- };
- }
- textContentItem.fontName = font.loadedName;
- // 9.4.4 Text Space Details
- var tsm = [
- textState.fontSize * textState.textHScale,
- 0,
- 0,
- textState.fontSize,
- 0,
- textState.textRise
- ];
- if (font.isType3Font && textState.fontMatrix !== FONT_IDENTITY_MATRIX && textState.fontSize === 1) {
- var glyphHeight = font.bbox[3] - font.bbox[1];
- if (glyphHeight > 0) {
- glyphHeight = glyphHeight * textState.fontMatrix[3];
- tsm[3] *= glyphHeight;
- }
- }
- var trm = Util.transform(textState.ctm, Util.transform(textState.textMatrix, tsm));
- textContentItem.transform = trm;
- if (!font.vertical) {
- textContentItem.width = 0;
- textContentItem.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]);
- textContentItem.vertical = false;
- } else {
- textContentItem.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]);
- textContentItem.height = 0;
- textContentItem.vertical = true;
- }
- var a = textState.textLineMatrix[0];
- var b = textState.textLineMatrix[1];
- var scaleLineX = Math.sqrt(a * a + b * b);
- a = textState.ctm[0];
- b = textState.ctm[1];
- var scaleCtmX = Math.sqrt(a * a + b * b);
- textContentItem.textAdvanceScale = scaleCtmX * scaleLineX;
- textContentItem.lastAdvanceWidth = 0;
- textContentItem.lastAdvanceHeight = 0;
- var spaceWidth = font.spaceWidth / 1000 * textState.fontSize;
- if (spaceWidth) {
- textContentItem.spaceWidth = spaceWidth;
- textContentItem.fakeSpaceMin = spaceWidth * SPACE_FACTOR;
- textContentItem.fakeMultiSpaceMin = spaceWidth * MULTI_SPACE_FACTOR;
- textContentItem.fakeMultiSpaceMax = spaceWidth * MULTI_SPACE_FACTOR_MAX;
- // It's okay for monospace fonts to fake as much space as needed.
- textContentItem.textRunBreakAllowed = !font.isMonospace;
- } else {
- textContentItem.spaceWidth = 0;
- textContentItem.fakeSpaceMin = Infinity;
- textContentItem.fakeMultiSpaceMin = Infinity;
- textContentItem.fakeMultiSpaceMax = 0;
- textContentItem.textRunBreakAllowed = false;
- }
- textContentItem.initialized = true;
- return textContentItem;
- }
- function replaceWhitespace(str) {
- // Replaces all whitespaces with standard spaces (0x20), to avoid
- // alignment issues between the textLayer and the canvas if the text
- // contains e.g. tabs (fixes issue6612.pdf).
- var i = 0, ii = str.length, code;
- while (i < ii && (code = str.charCodeAt(i)) >= 0x20 && code <= 0x7F) {
- i++;
- }
- return i < ii ? str.replace(WhitespaceRegexp, ' ') : str;
- }
- function runBidiTransform(textChunk) {
- var str = textChunk.str.join('');
- var bidiResult = bidi(str, -1, textChunk.vertical);
- return {
- str: normalizeWhitespace ? replaceWhitespace(bidiResult.str) : bidiResult.str,
- dir: bidiResult.dir,
- width: textChunk.width,
- height: textChunk.height,
- transform: textChunk.transform,
- fontName: textChunk.fontName
- };
- }
- function handleSetFont(fontName, fontRef) {
- return self.loadFont(fontName, fontRef, xref, resources).then(function (translated) {
- textState.font = translated.font;
- textState.fontMatrix = translated.font.fontMatrix || FONT_IDENTITY_MATRIX;
- });
- }
- function buildTextContentItem(chars) {
- var font = textState.font;
- var textChunk = ensureTextContentItem();
- var width = 0;
- var height = 0;
- var glyphs = font.charsToGlyphs(chars);
- var defaultVMetrics = font.defaultVMetrics;
- for (var i = 0; i < glyphs.length; i++) {
- var glyph = glyphs[i];
- var vMetricX = null;
- var vMetricY = null;
- var glyphWidth = null;
- if (font.vertical) {
- if (glyph.vmetric) {
- glyphWidth = glyph.vmetric[0];
- vMetricX = glyph.vmetric[1];
- vMetricY = glyph.vmetric[2];
- } else {
- glyphWidth = glyph.width;
- vMetricX = glyph.width * 0.5;
- vMetricY = defaultVMetrics[2];
- }
- } else {
- glyphWidth = glyph.width;
- }
- var glyphUnicode = glyph.unicode;
- var NormalizedUnicodes = getNormalizedUnicodes();
- if (NormalizedUnicodes[glyphUnicode] !== undefined) {
- glyphUnicode = NormalizedUnicodes[glyphUnicode];
- }
- glyphUnicode = reverseIfRtl(glyphUnicode);
- // The following will calculate the x and y of the individual glyphs.
- // if (font.vertical) {
- // tsm[4] -= vMetricX * Math.abs(textState.fontSize) *
- // textState.fontMatrix[0];
- // tsm[5] -= vMetricY * textState.fontSize *
- // textState.fontMatrix[0];
- // }
- // var trm = Util.transform(textState.textMatrix, tsm);
- // var pt = Util.applyTransform([trm[4], trm[5]], textState.ctm);
- // var x = pt[0];
- // var y = pt[1];
- var charSpacing = textState.charSpacing;
- if (glyph.isSpace) {
- var wordSpacing = textState.wordSpacing;
- charSpacing += wordSpacing;
- if (wordSpacing > 0) {
- addFakeSpaces(wordSpacing, textChunk.str);
- }
- }
- var tx = 0;
- var ty = 0;
- if (!font.vertical) {
- var w0 = glyphWidth * textState.fontMatrix[0];
- tx = (w0 * textState.fontSize + charSpacing) * textState.textHScale;
- width += tx;
- } else {
- var w1 = glyphWidth * textState.fontMatrix[0];
- ty = w1 * textState.fontSize + charSpacing;
- height += ty;
- }
- textState.translateTextMatrix(tx, ty);
- textChunk.str.push(glyphUnicode);
- }
- if (!font.vertical) {
- textChunk.lastAdvanceWidth = width;
- textChunk.width += width * textChunk.textAdvanceScale;
- } else {
- textChunk.lastAdvanceHeight = height;
- textChunk.height += Math.abs(height * textChunk.textAdvanceScale);
- }
- return textChunk;
- }
- function addFakeSpaces(width, strBuf) {
- if (width < textContentItem.fakeSpaceMin) {
- return;
- }
- if (width < textContentItem.fakeMultiSpaceMin) {
- strBuf.push(' ');
- return;
- }
- var fakeSpaces = Math.round(width / textContentItem.spaceWidth);
- while (fakeSpaces-- > 0) {
- strBuf.push(' ');
- }
- }
- function flushTextContentItem() {
- if (!textContentItem.initialized) {
- return;
- }
- textContent.items.push(runBidiTransform(textContentItem));
- textContentItem.initialized = false;
- textContentItem.str.length = 0;
- }
- var timeSlotManager = new TimeSlotManager();
- return new Promise(function promiseBody(resolve, reject) {
- var next = function (promise) {
- promise.then(function () {
- try {
- promiseBody(resolve, reject);
- } catch (ex) {
- reject(ex);
- }
- }, reject);
- };
- task.ensureNotTerminated();
- timeSlotManager.reset();
- var stop, operation = {}, args = [];
- while (!(stop = timeSlotManager.check())) {
- // The arguments parsed by read() are not used beyond this loop, so
- // we can reuse the same array on every iteration, thus avoiding
- // unnecessary allocations.
- args.length = 0;
- operation.args = args;
- if (!preprocessor.read(operation)) {
- break;
- }
- textState = stateManager.state;
- var fn = operation.fn;
- args = operation.args;
- var advance, diff;
- switch (fn | 0) {
- case OPS.setFont:
- // Optimization to ignore multiple identical Tf commands.
- var fontNameArg = args[0].name, fontSizeArg = args[1];
- if (textState.font && fontNameArg === textState.fontName && fontSizeArg === textState.fontSize) {
- break;
- }
- flushTextContentItem();
- textState.fontName = fontNameArg;
- textState.fontSize = fontSizeArg;
- next(handleSetFont(fontNameArg, null));
- return;
- case OPS.setTextRise:
- flushTextContentItem();
- textState.textRise = args[0];
- break;
- case OPS.setHScale:
- flushTextContentItem();
- textState.textHScale = args[0] / 100;
- break;
- case OPS.setLeading:
- flushTextContentItem();
- textState.leading = args[0];
- break;
- case OPS.moveText:
- // Optimization to treat same line movement as advance
- var isSameTextLine = !textState.font ? false : (textState.font.vertical ? args[0] : args[1]) === 0;
- advance = args[0] - args[1];
- if (combineTextItems && isSameTextLine && textContentItem.initialized && advance > 0 && advance <= textContentItem.fakeMultiSpaceMax) {
- textState.translateTextLineMatrix(args[0], args[1]);
- textContentItem.width += args[0] - textContentItem.lastAdvanceWidth;
- textContentItem.height += args[1] - textContentItem.lastAdvanceHeight;
- diff = args[0] - textContentItem.lastAdvanceWidth - (args[1] - textContentItem.lastAdvanceHeight);
- addFakeSpaces(diff, textContentItem.str);
- break;
- }
- flushTextContentItem();
- textState.translateTextLineMatrix(args[0], args[1]);
- textState.textMatrix = textState.textLineMatrix.slice();
- break;
- case OPS.setLeadingMoveText:
- flushTextContentItem();
- textState.leading = -args[1];
- textState.translateTextLineMatrix(args[0], args[1]);
- textState.textMatrix = textState.textLineMatrix.slice();
- break;
- case OPS.nextLine:
- flushTextContentItem();
- textState.carriageReturn();
- break;
- case OPS.setTextMatrix:
- // Optimization to treat same line movement as advance.
- advance = textState.calcTextLineMatrixAdvance(args[0], args[1], args[2], args[3], args[4], args[5]);
- if (combineTextItems && advance !== null && textContentItem.initialized && advance.value > 0 && advance.value <= textContentItem.fakeMultiSpaceMax) {
- textState.translateTextLineMatrix(advance.width, advance.height);
- textContentItem.width += advance.width - textContentItem.lastAdvanceWidth;
- textContentItem.height += advance.height - textContentItem.lastAdvanceHeight;
- diff = advance.width - textContentItem.lastAdvanceWidth - (advance.height - textContentItem.lastAdvanceHeight);
- addFakeSpaces(diff, textContentItem.str);
- break;
- }
- flushTextContentItem();
- textState.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
- textState.setTextLineMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
- break;
- case OPS.setCharSpacing:
- textState.charSpacing = args[0];
- break;
- case OPS.setWordSpacing:
- textState.wordSpacing = args[0];
- break;
- case OPS.beginText:
- flushTextContentItem();
- textState.textMatrix = IDENTITY_MATRIX.slice();
- textState.textLineMatrix = IDENTITY_MATRIX.slice();
- break;
- case OPS.showSpacedText:
- var items = args[0];
- var offset;
- for (var j = 0, jj = items.length; j < jj; j++) {
- if (typeof items[j] === 'string') {
- buildTextContentItem(items[j]);
- } else if (isNum(items[j])) {
- ensureTextContentItem();
- // PDF Specification 5.3.2 states:
- // The number is expressed in thousandths of a unit of text
- // space.
- // This amount is subtracted from the current horizontal or
- // vertical coordinate, depending on the writing mode.
- // In the default coordinate system, a positive adjustment
- // has the effect of moving the next glyph painted either to
- // the left or down by the given amount.
- advance = items[j] * textState.fontSize / 1000;
- var breakTextRun = false;
- if (textState.font.vertical) {
- offset = advance * (textState.textHScale * textState.textMatrix[2] + textState.textMatrix[3]);
- textState.translateTextMatrix(0, advance);
- breakTextRun = textContentItem.textRunBreakAllowed && advance > textContentItem.fakeMultiSpaceMax;
- if (!breakTextRun) {
- // Value needs to be added to height to paint down.
- textContentItem.height += offset;
- }
- } else {
- advance = -advance;
- offset = advance * (textState.textHScale * textState.textMatrix[0] + textState.textMatrix[1]);
- textState.translateTextMatrix(advance, 0);
- breakTextRun = textContentItem.textRunBreakAllowed && advance > textContentItem.fakeMultiSpaceMax;
- if (!breakTextRun) {
- // Value needs to be subtracted from width to paint left.
- textContentItem.width += offset;
- }
- }
- if (breakTextRun) {
- flushTextContentItem();
- } else if (advance > 0) {
- addFakeSpaces(advance, textContentItem.str);
- }
- }
- }
- break;
- case OPS.showText:
- buildTextContentItem(args[0]);
- break;
- case OPS.nextLineShowText:
- flushTextContentItem();
- textState.carriageReturn();
- buildTextContentItem(args[0]);
- break;
- case OPS.nextLineSetSpacingShowText:
- flushTextContentItem();
- textState.wordSpacing = args[0];
- textState.charSpacing = args[1];
- textState.carriageReturn();
- buildTextContentItem(args[2]);
- break;
- case OPS.paintXObject:
- flushTextContentItem();
- if (args[0].code) {
- break;
- }
- if (!xobjs) {
- xobjs = resources.get('XObject') || Dict.empty;
- }
- var name = args[0].name;
- if (xobjsCache.key === name) {
- if (xobjsCache.texts) {
- Util.appendToArray(textContent.items, xobjsCache.texts.items);
- Util.extendObj(textContent.styles, xobjsCache.texts.styles);
- }
- break;
- }
- var xobj = xobjs.get(name);
- if (!xobj) {
- break;
- }
- assert(isStream(xobj), 'XObject should be a stream');
- var type = xobj.dict.get('Subtype');
- assert(isName(type), 'XObject should have a Name subtype');
- if ('Form' !== type.name) {
- xobjsCache.key = name;
- xobjsCache.texts = null;
- break;
- }
- stateManager.save();
- var matrix = xobj.dict.getArray('Matrix');
- if (isArray(matrix) && matrix.length === 6) {
- stateManager.transform(matrix);
- }
- next(self.getTextContent(xobj, task, xobj.dict.get('Resources') || resources, stateManager, normalizeWhitespace, combineTextItems).then(function (formTextContent) {
- Util.appendToArray(textContent.items, formTextContent.items);
- Util.extendObj(textContent.styles, formTextContent.styles);
- stateManager.restore();
- xobjsCache.key = name;
- xobjsCache.texts = formTextContent;
- }));
- return;
- case OPS.setGState:
- flushTextContentItem();
- var dictName = args[0];
- var extGState = resources.get('ExtGState');
- if (!isDict(extGState) || !isName(dictName)) {
- break;
- }
- var gState = extGState.get(dictName.name);
- if (!isDict(gState)) {
- break;
- }
- var gStateFont = gState.get('Font');
- if (gStateFont) {
- textState.fontName = null;
- textState.fontSize = gStateFont[1];
- next(handleSetFont(null, gStateFont[0]));
- return;
- }
- break;
- }
- }
- // switch
- // while
- if (stop) {
- next(deferred);
- return;
- }
- flushTextContentItem();
- resolve(textContent);
- });
- },
- extractDataStructures: function PartialEvaluator_extractDataStructures(dict, baseDict, xref, properties) {
- // 9.10.2
- var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode');
- var toUnicodePromise = toUnicode ? this.readToUnicode(toUnicode) : Promise.resolve(undefined);
- if (properties.composite) {
- // CIDSystemInfo helps to match CID to glyphs
- var cidSystemInfo = dict.get('CIDSystemInfo');
- if (isDict(cidSystemInfo)) {
- properties.cidSystemInfo = {
- registry: cidSystemInfo.get('Registry'),
- ordering: cidSystemInfo.get('Ordering'),
- supplement: cidSystemInfo.get('Supplement')
- };
- }
- var cidToGidMap = dict.get('CIDToGIDMap');
- if (isStream(cidToGidMap)) {
- properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
- }
- }
- // Based on 9.6.6 of the spec the encoding can come from multiple places
- // and depends on the font type. The base encoding and differences are
- // read here, but the encoding that is actually used is chosen during
- // glyph mapping in the font.
- // TODO: Loading the built in encoding in the font would allow the
- // differences to be merged in here not require us to hold on to it.
- var differences = [];
- var baseEncodingName = null;
- var encoding;
- if (dict.has('Encoding')) {
- encoding = dict.get('Encoding');
- if (isDict(encoding)) {
- baseEncodingName = encoding.get('BaseEncoding');
- baseEncodingName = isName(baseEncodingName) ? baseEncodingName.name : null;
- // Load the differences between the base and original
- if (encoding.has('Differences')) {
- var diffEncoding = encoding.get('Differences');
- var index = 0;
- for (var j = 0, jj = diffEncoding.length; j < jj; j++) {
- var data = xref.fetchIfRef(diffEncoding[j]);
- if (isNum(data)) {
- index = data;
- } else if (isName(data)) {
- differences[index++] = data.name;
- } else {
- error('Invalid entry in \'Differences\' array: ' + data);
- }
- }
- }
- } else if (isName(encoding)) {
- baseEncodingName = encoding.name;
- } else {
- error('Encoding is not a Name nor a Dict');
- }
- // According to table 114 if the encoding is a named encoding it must be
- // one of these predefined encodings.
- if (baseEncodingName !== 'MacRomanEncoding' && baseEncodingName !== 'MacExpertEncoding' && baseEncodingName !== 'WinAnsiEncoding') {
- baseEncodingName = null;
- }
- }
- if (baseEncodingName) {
- properties.defaultEncoding = getEncoding(baseEncodingName).slice();
- } else {
- encoding = properties.type === 'TrueType' ? WinAnsiEncoding : StandardEncoding;
- // The Symbolic attribute can be misused for regular fonts
- // Heuristic: we have to check if the font is a standard one also
- if (!!(properties.flags & FontFlags.Symbolic)) {
- encoding = MacRomanEncoding;
- if (!properties.file) {
- if (/Symbol/i.test(properties.name)) {
- encoding = SymbolSetEncoding;
- } else if (/Dingbats/i.test(properties.name)) {
- encoding = ZapfDingbatsEncoding;
- }
- }
- }
- properties.defaultEncoding = encoding;
- }
- properties.differences = differences;
- properties.baseEncodingName = baseEncodingName;
- properties.hasEncoding = !!baseEncodingName || differences.length > 0;
- properties.dict = dict;
- return toUnicodePromise.then(function (toUnicode) {
- properties.toUnicode = toUnicode;
- return this.buildToUnicode(properties);
- }.bind(this)).then(function (toUnicode) {
- properties.toUnicode = toUnicode;
- return properties;
- });
- },
- /**
- * Builds a char code to unicode map based on section 9.10 of the spec.
- * @param {Object} properties Font properties object.
- * @return {Promise} A Promise that is resolved with a
- * {ToUnicodeMap|IdentityToUnicodeMap} object.
- */
- buildToUnicode: function PartialEvaluator_buildToUnicode(properties) {
- properties.hasIncludedToUnicodeMap = !!properties.toUnicode && properties.toUnicode.length > 0;
- // Section 9.10.2 Mapping Character Codes to Unicode Values
- if (properties.hasIncludedToUnicodeMap) {
- return Promise.resolve(properties.toUnicode);
- }
- // According to the spec if the font is a simple font we should only map
- // to unicode if the base encoding is MacRoman, MacExpert, or WinAnsi or
- // the differences array only contains adobe standard or symbol set names,
- // in pratice it seems better to always try to create a toUnicode
- // map based of the default encoding.
- var toUnicode, charcode, glyphName;
- if (!properties.composite)
- /* is simple font */
- {
- toUnicode = [];
- var encoding = properties.defaultEncoding.slice();
- var baseEncodingName = properties.baseEncodingName;
- // Merge in the differences array.
- var differences = properties.differences;
- for (charcode in differences) {
- glyphName = differences[charcode];
- if (glyphName === '.notdef') {
- // Skip .notdef to prevent rendering errors, e.g. boxes appearing
- // where there should be spaces (fixes issue5256.pdf).
- continue;
- }
- encoding[charcode] = glyphName;
- }
- var glyphsUnicodeMap = getGlyphsUnicode();
- for (charcode in encoding) {
- // a) Map the character code to a character name.
- glyphName = encoding[charcode];
- // b) Look up the character name in the Adobe Glyph List (see the
- // Bibliography) to obtain the corresponding Unicode value.
- if (glyphName === '') {
- continue;
- } else if (glyphsUnicodeMap[glyphName] === undefined) {
- // (undocumented) c) Few heuristics to recognize unknown glyphs
- // NOTE: Adobe Reader does not do this step, but OSX Preview does
- var code = 0;
- switch (glyphName[0]) {
- case 'G':
- // Gxx glyph
- if (glyphName.length === 3) {
- code = parseInt(glyphName.substr(1), 16);
- }
- break;
- case 'g':
- // g00xx glyph
- if (glyphName.length === 5) {
- code = parseInt(glyphName.substr(1), 16);
- }
- break;
- case 'C':
- // Cddd glyph
- case 'c':
- // cddd glyph
- if (glyphName.length >= 3) {
- code = +glyphName.substr(1);
- }
- break;
- default:
- // 'uniXXXX'/'uXXXX{XX}' glyphs
- var unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);
- if (unicode !== -1) {
- code = unicode;
- }
- }
- if (code) {
- // If |baseEncodingName| is one the predefined encodings,
- // and |code| equals |charcode|, using the glyph defined in the
- // baseEncoding seems to yield a better |toUnicode| mapping
- // (fixes issue 5070).
- if (baseEncodingName && code === +charcode) {
- var baseEncoding = getEncoding(baseEncodingName);
- if (baseEncoding && (glyphName = baseEncoding[charcode])) {
- toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]);
- continue;
- }
- }
- toUnicode[charcode] = String.fromCharCode(code);
- }
- continue;
- }
- toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]);
- }
- return Promise.resolve(new ToUnicodeMap(toUnicode));
- }
- // If the font is a composite font that uses one of the predefined CMaps
- // listed in Table 118 (except Identity–H and Identity–V) or whose
- // descendant CIDFont uses the Adobe-GB1, Adobe-CNS1, Adobe-Japan1, or
- // Adobe-Korea1 character collection:
- if (properties.composite && (properties.cMap.builtInCMap && !(properties.cMap instanceof IdentityCMap) || properties.cidSystemInfo.registry === 'Adobe' && (properties.cidSystemInfo.ordering === 'GB1' || properties.cidSystemInfo.ordering === 'CNS1' || properties.cidSystemInfo.ordering === 'Japan1' || properties.cidSystemInfo.ordering === 'Korea1'))) {
- // Then:
- // a) Map the character code to a character identifier (CID) according
- // to the font’s CMap.
- // b) Obtain the registry and ordering of the character collection used
- // by the font’s CMap (for example, Adobe and Japan1) from its
- // CIDSystemInfo dictionary.
- var registry = properties.cidSystemInfo.registry;
- var ordering = properties.cidSystemInfo.ordering;
- // c) Construct a second CMap name by concatenating the registry and
- // ordering obtained in step (b) in the format registry–ordering–UCS2
- // (for example, Adobe–Japan1–UCS2).
- var ucs2CMapName = Name.get(registry + '-' + ordering + '-UCS2');
- // d) Obtain the CMap with the name constructed in step (c) (available
- // from the ASN Web site; see the Bibliography).
- return CMapFactory.create(ucs2CMapName, this.options.cMapOptions, null).then(function (ucs2CMap) {
- var cMap = properties.cMap;
- toUnicode = [];
- cMap.forEach(function (charcode, cid) {
- assert(cid <= 0xffff, 'Max size of CID is 65,535');
- // e) Map the CID obtained in step (a) according to the CMap
- // obtained in step (d), producing a Unicode value.
- var ucs2 = ucs2CMap.lookup(cid);
- if (ucs2) {
- toUnicode[charcode] = String.fromCharCode((ucs2.charCodeAt(0) << 8) + ucs2.charCodeAt(1));
- }
- });
- return new ToUnicodeMap(toUnicode);
- });
- }
- // The viewer's choice, just use an identity map.
- return Promise.resolve(new IdentityToUnicodeMap(properties.firstChar, properties.lastChar));
- },
- readToUnicode: function PartialEvaluator_readToUnicode(toUnicode) {
- var cmapObj = toUnicode;
- if (isName(cmapObj)) {
- return CMapFactory.create(cmapObj, this.options.cMapOptions, null).then(function (cmap) {
- if (cmap instanceof IdentityCMap) {
- return new IdentityToUnicodeMap(0, 0xFFFF);
- }
- return new ToUnicodeMap(cmap.getMap());
- });
- } else if (isStream(cmapObj)) {
- return CMapFactory.create(cmapObj, this.options.cMapOptions, null).then(function (cmap) {
- if (cmap instanceof IdentityCMap) {
- return new IdentityToUnicodeMap(0, 0xFFFF);
- }
- var map = new Array(cmap.length);
- // Convert UTF-16BE
- // NOTE: cmap can be a sparse array, so use forEach instead of for(;;)
- // to iterate over all keys.
- cmap.forEach(function (charCode, token) {
- var str = [];
- for (var k = 0; k < token.length; k += 2) {
- var w1 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);
- if ((w1 & 0xF800) !== 0xD800) {
- // w1 < 0xD800 || w1 > 0xDFFF
- str.push(w1);
- continue;
- }
- k += 2;
- var w2 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);
- str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
- }
- map[charCode] = String.fromCharCode.apply(String, str);
- });
- return new ToUnicodeMap(map);
- });
- }
- return Promise.resolve(null);
- },
- readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) {
- // Extract the encoding from the CIDToGIDMap
- var glyphsData = cidToGidStream.getBytes();
- // Set encoding 0 to later verify the font has an encoding
- var result = [];
- for (var j = 0, jj = glyphsData.length; j < jj; j++) {
- var glyphID = glyphsData[j++] << 8 | glyphsData[j];
- if (glyphID === 0) {
- continue;
- }
- var code = j >> 1;
- result[code] = glyphID;
- }
- return result;
- },
- extractWidths: function PartialEvaluator_extractWidths(dict, xref, descriptor, properties) {
- var glyphsWidths = [];
- var defaultWidth = 0;
- var glyphsVMetrics = [];
- var defaultVMetrics;
- var i, ii, j, jj, start, code, widths;
- if (properties.composite) {
- defaultWidth = dict.get('DW') || 1000;
- widths = dict.get('W');
- if (widths) {
- for (i = 0, ii = widths.length; i < ii; i++) {
- start = widths[i++];
- code = xref.fetchIfRef(widths[i]);
- if (isArray(code)) {
- for (j = 0, jj = code.length; j < jj; j++) {
- glyphsWidths[start++] = code[j];
- }
- } else {
- var width = widths[++i];
- for (j = start; j <= code; j++) {
- glyphsWidths[j] = width;
- }
- }
- }
- }
- if (properties.vertical) {
- var vmetrics = dict.get('DW2') || [
- 880,
- -1000
- ];
- defaultVMetrics = [
- vmetrics[1],
- defaultWidth * 0.5,
- vmetrics[0]
- ];
- vmetrics = dict.get('W2');
- if (vmetrics) {
- for (i = 0, ii = vmetrics.length; i < ii; i++) {
- start = vmetrics[i++];
- code = xref.fetchIfRef(vmetrics[i]);
- if (isArray(code)) {
- for (j = 0, jj = code.length; j < jj; j++) {
- glyphsVMetrics[start++] = [
- code[j++],
- code[j++],
- code[j]
- ];
- }
- } else {
- var vmetric = [
- vmetrics[++i],
- vmetrics[++i],
- vmetrics[++i]
- ];
- for (j = start; j <= code; j++) {
- glyphsVMetrics[j] = vmetric;
- }
- }
- }
- }
- }
- } else {
- var firstChar = properties.firstChar;
- widths = dict.get('Widths');
- if (widths) {
- j = firstChar;
- for (i = 0, ii = widths.length; i < ii; i++) {
- glyphsWidths[j++] = widths[i];
- }
- defaultWidth = parseFloat(descriptor.get('MissingWidth')) || 0;
- } else {
- // Trying get the BaseFont metrics (see comment above).
- var baseFontName = dict.get('BaseFont');
- if (isName(baseFontName)) {
- var metrics = this.getBaseFontMetrics(baseFontName.name);
- glyphsWidths = this.buildCharCodeToWidth(metrics.widths, properties);
- defaultWidth = metrics.defaultWidth;
- }
- }
- }
- // Heuristic: detection of monospace font by checking all non-zero widths
- var isMonospace = true;
- var firstWidth = defaultWidth;
- for (var glyph in glyphsWidths) {
- var glyphWidth = glyphsWidths[glyph];
- if (!glyphWidth) {
- continue;
- }
- if (!firstWidth) {
- firstWidth = glyphWidth;
- continue;
- }
- if (firstWidth !== glyphWidth) {
- isMonospace = false;
- break;
- }
- }
- if (isMonospace) {
- properties.flags |= FontFlags.FixedPitch;
- }
- properties.defaultWidth = defaultWidth;
- properties.widths = glyphsWidths;
- properties.defaultVMetrics = defaultVMetrics;
- properties.vmetrics = glyphsVMetrics;
- },
- isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) {
- // Simulating descriptor flags attribute
- var fontNameWoStyle = baseFontName.split('-')[0];
- return fontNameWoStyle in getSerifFonts() || fontNameWoStyle.search(/serif/gi) !== -1;
- },
- getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) {
- var defaultWidth = 0;
- var widths = [];
- var monospace = false;
- var stdFontMap = getStdFontMap();
- var lookupName = stdFontMap[name] || name;
- var Metrics = getMetrics();
- if (!(lookupName in Metrics)) {
- // Use default fonts for looking up font metrics if the passed
- // font is not a base font
- if (this.isSerifFont(name)) {
- lookupName = 'Times-Roman';
- } else {
- lookupName = 'Helvetica';
- }
- }
- var glyphWidths = Metrics[lookupName];
- if (isNum(glyphWidths)) {
- defaultWidth = glyphWidths;
- monospace = true;
- } else {
- widths = glyphWidths();
- }
- // expand lazy widths array
- return {
- defaultWidth: defaultWidth,
- monospace: monospace,
- widths: widths
- };
- },
- buildCharCodeToWidth: function PartialEvaluator_bulildCharCodeToWidth(widthsByGlyphName, properties) {
- var widths = Object.create(null);
- var differences = properties.differences;
- var encoding = properties.defaultEncoding;
- for (var charCode = 0; charCode < 256; charCode++) {
- if (charCode in differences && widthsByGlyphName[differences[charCode]]) {
- widths[charCode] = widthsByGlyphName[differences[charCode]];
- continue;
- }
- if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) {
- widths[charCode] = widthsByGlyphName[encoding[charCode]];
- continue;
- }
- }
- return widths;
- },
- preEvaluateFont: function PartialEvaluator_preEvaluateFont(dict, xref) {
- var baseDict = dict;
- var type = dict.get('Subtype');
- assert(isName(type), 'invalid font Subtype');
- var composite = false;
- var uint8array;
- if (type.name === 'Type0') {
- // If font is a composite
- // - get the descendant font
- // - set the type according to the descendant font
- // - get the FontDescriptor from the descendant font
- var df = dict.get('DescendantFonts');
- if (!df) {
- error('Descendant fonts are not specified');
- }
- dict = isArray(df) ? xref.fetchIfRef(df[0]) : df;
- type = dict.get('Subtype');
- assert(isName(type), 'invalid font Subtype');
- composite = true;
- }
- var descriptor = dict.get('FontDescriptor');
- if (descriptor) {
- var hash = new MurmurHash3_64();
- var encoding = baseDict.getRaw('Encoding');
- if (isName(encoding)) {
- hash.update(encoding.name);
- } else if (isRef(encoding)) {
- hash.update(encoding.toString());
- } else if (isDict(encoding)) {
- var keys = encoding.getKeys();
- for (var i = 0, ii = keys.length; i < ii; i++) {
- var entry = encoding.getRaw(keys[i]);
- if (isName(entry)) {
- hash.update(entry.name);
- } else if (isRef(entry)) {
- hash.update(entry.toString());
- } else if (isArray(entry)) {
- // 'Differences' entry.
- // Ideally we should check the contents of the array, but to avoid
- // parsing it here and then again in |extractDataStructures|,
- // we only use the array length for now (fixes bug1157493.pdf).
- hash.update(entry.length.toString());
- }
- }
- }
- var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode');
- if (isStream(toUnicode)) {
- var stream = toUnicode.str || toUnicode;
- uint8array = stream.buffer ? new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : new Uint8Array(stream.bytes.buffer, stream.start, stream.end - stream.start);
- hash.update(uint8array);
- } else if (isName(toUnicode)) {
- hash.update(toUnicode.name);
- }
- var widths = dict.get('Widths') || baseDict.get('Widths');
- if (widths) {
- uint8array = new Uint8Array(new Uint32Array(widths).buffer);
- hash.update(uint8array);
- }
- }
- return {
- descriptor: descriptor,
- dict: dict,
- baseDict: baseDict,
- composite: composite,
- type: type.name,
- hash: hash ? hash.hexdigest() : ''
- };
- },
- translateFont: function PartialEvaluator_translateFont(preEvaluatedFont, xref) {
- var baseDict = preEvaluatedFont.baseDict;
- var dict = preEvaluatedFont.dict;
- var composite = preEvaluatedFont.composite;
- var descriptor = preEvaluatedFont.descriptor;
- var type = preEvaluatedFont.type;
- var maxCharIndex = composite ? 0xFFFF : 0xFF;
- var cMapOptions = this.options.cMapOptions;
- var properties;
- if (!descriptor) {
- if (type === 'Type3') {
- // FontDescriptor is only required for Type3 fonts when the document
- // is a tagged pdf. Create a barbebones one to get by.
- descriptor = new Dict(null);
- descriptor.set('FontName', Name.get(type));
- descriptor.set('FontBBox', dict.getArray('FontBBox'));
- } else {
- // Before PDF 1.5 if the font was one of the base 14 fonts, having a
- // FontDescriptor was not required.
- // This case is here for compatibility.
- var baseFontName = dict.get('BaseFont');
- if (!isName(baseFontName)) {
- error('Base font is not specified');
- }
- // Using base font name as a font name.
- baseFontName = baseFontName.name.replace(/[,_]/g, '-');
- var metrics = this.getBaseFontMetrics(baseFontName);
- // Simulating descriptor flags attribute
- var fontNameWoStyle = baseFontName.split('-')[0];
- var flags = (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | (metrics.monospace ? FontFlags.FixedPitch : 0) | (getSymbolsFonts()[fontNameWoStyle] ? FontFlags.Symbolic : FontFlags.Nonsymbolic);
- properties = {
- type: type,
- name: baseFontName,
- widths: metrics.widths,
- defaultWidth: metrics.defaultWidth,
- flags: flags,
- firstChar: 0,
- lastChar: maxCharIndex
- };
- return this.extractDataStructures(dict, dict, xref, properties).then(function (properties) {
- properties.widths = this.buildCharCodeToWidth(metrics.widths, properties);
- return new Font(baseFontName, null, properties);
- }.bind(this));
- }
- }
- // According to the spec if 'FontDescriptor' is declared, 'FirstChar',
- // 'LastChar' and 'Widths' should exist too, but some PDF encoders seem
- // to ignore this rule when a variant of a standard font is used.
- // TODO Fill the width array depending on which of the base font this is
- // a variant.
- var firstChar = dict.get('FirstChar') || 0;
- var lastChar = dict.get('LastChar') || maxCharIndex;
- var fontName = descriptor.get('FontName');
- var baseFont = dict.get('BaseFont');
- // Some bad PDFs have a string as the font name.
- if (isString(fontName)) {
- fontName = Name.get(fontName);
- }
- if (isString(baseFont)) {
- baseFont = Name.get(baseFont);
- }
- if (type !== 'Type3') {
- var fontNameStr = fontName && fontName.name;
- var baseFontStr = baseFont && baseFont.name;
- if (fontNameStr !== baseFontStr) {
- info('The FontDescriptor\'s FontName is "' + fontNameStr + '" but should be the same as the Font\'s BaseFont "' + baseFontStr + '"');
- // Workaround for cases where e.g. fontNameStr = 'Arial' and
- // baseFontStr = 'Arial,Bold' (needed when no font file is embedded).
- if (fontNameStr && baseFontStr && baseFontStr.indexOf(fontNameStr) === 0) {
- fontName = baseFont;
- }
- }
- }
- fontName = fontName || baseFont;
- assert(isName(fontName), 'invalid font name');
- var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
- if (fontFile) {
- if (fontFile.dict) {
- var subtype = fontFile.dict.get('Subtype');
- if (subtype) {
- subtype = subtype.name;
- }
- var length1 = fontFile.dict.get('Length1');
- var length2 = fontFile.dict.get('Length2');
- var length3 = fontFile.dict.get('Length3');
- }
- }
- properties = {
- type: type,
- name: fontName.name,
- subtype: subtype,
- file: fontFile,
- length1: length1,
- length2: length2,
- length3: length3,
- loadedName: baseDict.loadedName,
- composite: composite,
- wideChars: composite,
- fixedPitch: false,
- fontMatrix: dict.getArray('FontMatrix') || FONT_IDENTITY_MATRIX,
- firstChar: firstChar || 0,
- lastChar: lastChar || maxCharIndex,
- bbox: descriptor.getArray('FontBBox'),
- ascent: descriptor.get('Ascent'),
- descent: descriptor.get('Descent'),
- xHeight: descriptor.get('XHeight'),
- capHeight: descriptor.get('CapHeight'),
- flags: descriptor.get('Flags'),
- italicAngle: descriptor.get('ItalicAngle'),
- coded: false
- };
- var cMapPromise;
- if (composite) {
- var cidEncoding = baseDict.get('Encoding');
- if (isName(cidEncoding)) {
- properties.cidEncoding = cidEncoding.name;
- }
- cMapPromise = CMapFactory.create(cidEncoding, cMapOptions, null).then(function (cMap) {
- properties.cMap = cMap;
- properties.vertical = properties.cMap.vertical;
- });
- } else {
- cMapPromise = Promise.resolve(undefined);
- }
- return cMapPromise.then(function () {
- return this.extractDataStructures(dict, baseDict, xref, properties);
- }.bind(this)).then(function (properties) {
- this.extractWidths(dict, xref, descriptor, properties);
- if (type === 'Type3') {
- properties.isType3Font = true;
- }
- return new Font(fontName.name, fontFile, properties);
- }.bind(this));
- }
- };
- return PartialEvaluator;
- }();
- var TranslatedFont = function TranslatedFontClosure() {
- function TranslatedFont(loadedName, font, dict) {
- this.loadedName = loadedName;
- this.font = font;
- this.dict = dict;
- this.type3Loaded = null;
- this.sent = false;
- }
- TranslatedFont.prototype = {
- send: function (handler) {
- if (this.sent) {
- return;
- }
- var fontData = this.font.exportData();
- handler.send('commonobj', [
- this.loadedName,
- 'Font',
- fontData
- ]);
- this.sent = true;
- },
- loadType3Data: function (evaluator, resources, parentOperatorList, task) {
- assert(this.font.isType3Font);
- if (this.type3Loaded) {
- return this.type3Loaded;
- }
- var translatedFont = this.font;
- var loadCharProcsPromise = Promise.resolve();
- var charProcs = this.dict.get('CharProcs');
- var fontResources = this.dict.get('Resources') || resources;
- var charProcKeys = charProcs.getKeys();
- var charProcOperatorList = Object.create(null);
- for (var i = 0, n = charProcKeys.length; i < n; ++i) {
- loadCharProcsPromise = loadCharProcsPromise.then(function (key) {
- var glyphStream = charProcs.get(key);
- var operatorList = new OperatorList();
- return evaluator.getOperatorList(glyphStream, task, fontResources, operatorList).then(function () {
- charProcOperatorList[key] = operatorList.getIR();
- // Add the dependencies to the parent operator list so they are
- // resolved before sub operator list is executed synchronously.
- parentOperatorList.addDependencies(operatorList.dependencies);
- }, function (reason) {
- warn('Type3 font resource \"' + key + '\" is not available');
- var operatorList = new OperatorList();
- charProcOperatorList[key] = operatorList.getIR();
- });
- }.bind(this, charProcKeys[i]));
- }
- this.type3Loaded = loadCharProcsPromise.then(function () {
- translatedFont.charProcOperatorList = charProcOperatorList;
- });
- return this.type3Loaded;
- }
- };
- return TranslatedFont;
- }();
- var OperatorList = function OperatorListClosure() {
- var CHUNK_SIZE = 1000;
- var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5;
- // close to chunk size
- function getTransfers(queue) {
- var transfers = [];
- var fnArray = queue.fnArray, argsArray = queue.argsArray;
- for (var i = 0, ii = queue.length; i < ii; i++) {
- switch (fnArray[i]) {
- case OPS.paintInlineImageXObject:
- case OPS.paintInlineImageXObjectGroup:
- case OPS.paintImageMaskXObject:
- var arg = argsArray[i][0];
- // first param in imgData
- if (!arg.cached) {
- transfers.push(arg.data.buffer);
- }
- break;
- }
- }
- return transfers;
- }
- function OperatorList(intent, messageHandler, pageIndex) {
- this.messageHandler = messageHandler;
- this.fnArray = [];
- this.argsArray = [];
- this.dependencies = Object.create(null);
- this._totalLength = 0;
- this.pageIndex = pageIndex;
- this.intent = intent;
- }
- OperatorList.prototype = {
- get length() {
- return this.argsArray.length;
- },
- /**
- * @returns {number} The total length of the entire operator list,
- * since `this.length === 0` after flushing.
- */
- get totalLength() {
- return this._totalLength + this.length;
- },
- addOp: function (fn, args) {
- this.fnArray.push(fn);
- this.argsArray.push(args);
- if (this.messageHandler) {
- if (this.fnArray.length >= CHUNK_SIZE) {
- this.flush();
- } else if (this.fnArray.length >= CHUNK_SIZE_ABOUT && (fn === OPS.restore || fn === OPS.endText)) {
- // heuristic to flush on boundary of restore or endText
- this.flush();
- }
- }
- },
- addDependency: function (dependency) {
- if (dependency in this.dependencies) {
- return;
- }
- this.dependencies[dependency] = true;
- this.addOp(OPS.dependency, [dependency]);
- },
- addDependencies: function (dependencies) {
- for (var key in dependencies) {
- this.addDependency(key);
- }
- },
- addOpList: function (opList) {
- Util.extendObj(this.dependencies, opList.dependencies);
- for (var i = 0, ii = opList.length; i < ii; i++) {
- this.addOp(opList.fnArray[i], opList.argsArray[i]);
- }
- },
- getIR: function () {
- return {
- fnArray: this.fnArray,
- argsArray: this.argsArray,
- length: this.length
- };
- },
- flush: function (lastChunk) {
- if (this.intent !== 'oplist') {
- new QueueOptimizer().optimize(this);
- }
- var transfers = getTransfers(this);
- var length = this.length;
- this._totalLength += length;
- this.messageHandler.send('RenderPageChunk', {
- operatorList: {
- fnArray: this.fnArray,
- argsArray: this.argsArray,
- lastChunk: lastChunk,
- length: length
- },
- pageIndex: this.pageIndex,
- intent: this.intent
- }, transfers);
- this.dependencies = Object.create(null);
- this.fnArray.length = 0;
- this.argsArray.length = 0;
- }
- };
- return OperatorList;
- }();
- var StateManager = function StateManagerClosure() {
- function StateManager(initialState) {
- this.state = initialState;
- this.stateStack = [];
- }
- StateManager.prototype = {
- save: function () {
- var old = this.state;
- this.stateStack.push(this.state);
- this.state = old.clone();
- },
- restore: function () {
- var prev = this.stateStack.pop();
- if (prev) {
- this.state = prev;
- }
- },
- transform: function (args) {
- this.state.ctm = Util.transform(this.state.ctm, args);
- }
- };
- return StateManager;
- }();
- var TextState = function TextStateClosure() {
- function TextState() {
- this.ctm = new Float32Array(IDENTITY_MATRIX);
- this.fontName = null;
- this.fontSize = 0;
- this.font = null;
- this.fontMatrix = FONT_IDENTITY_MATRIX;
- this.textMatrix = IDENTITY_MATRIX.slice();
- this.textLineMatrix = IDENTITY_MATRIX.slice();
- this.charSpacing = 0;
- this.wordSpacing = 0;
- this.leading = 0;
- this.textHScale = 1;
- this.textRise = 0;
- }
- TextState.prototype = {
- setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) {
- var m = this.textMatrix;
- m[0] = a;
- m[1] = b;
- m[2] = c;
- m[3] = d;
- m[4] = e;
- m[5] = f;
- },
- setTextLineMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) {
- var m = this.textLineMatrix;
- m[0] = a;
- m[1] = b;
- m[2] = c;
- m[3] = d;
- m[4] = e;
- m[5] = f;
- },
- translateTextMatrix: function TextState_translateTextMatrix(x, y) {
- var m = this.textMatrix;
- m[4] = m[0] * x + m[2] * y + m[4];
- m[5] = m[1] * x + m[3] * y + m[5];
- },
- translateTextLineMatrix: function TextState_translateTextMatrix(x, y) {
- var m = this.textLineMatrix;
- m[4] = m[0] * x + m[2] * y + m[4];
- m[5] = m[1] * x + m[3] * y + m[5];
- },
- calcTextLineMatrixAdvance: function TextState_calcTextLineMatrixAdvance(a, b, c, d, e, f) {
- var font = this.font;
- if (!font) {
- return null;
- }
- var m = this.textLineMatrix;
- if (!(a === m[0] && b === m[1] && c === m[2] && d === m[3])) {
- return null;
- }
- var txDiff = e - m[4], tyDiff = f - m[5];
- if (font.vertical && txDiff !== 0 || !font.vertical && tyDiff !== 0) {
- return null;
- }
- var tx, ty, denominator = a * d - b * c;
- if (font.vertical) {
- tx = -tyDiff * c / denominator;
- ty = tyDiff * a / denominator;
- } else {
- tx = txDiff * d / denominator;
- ty = -txDiff * b / denominator;
- }
- return {
- width: tx,
- height: ty,
- value: font.vertical ? ty : tx
- };
- },
- calcRenderMatrix: function TextState_calcRendeMatrix(ctm) {
- // 9.4.4 Text Space Details
- var tsm = [
- this.fontSize * this.textHScale,
- 0,
- 0,
- this.fontSize,
- 0,
- this.textRise
- ];
- return Util.transform(ctm, Util.transform(this.textMatrix, tsm));
- },
- carriageReturn: function TextState_carriageReturn() {
- this.translateTextLineMatrix(0, -this.leading);
- this.textMatrix = this.textLineMatrix.slice();
- },
- clone: function TextState_clone() {
- var clone = Object.create(this);
- clone.textMatrix = this.textMatrix.slice();
- clone.textLineMatrix = this.textLineMatrix.slice();
- clone.fontMatrix = this.fontMatrix.slice();
- return clone;
- }
- };
- return TextState;
- }();
- var EvalState = function EvalStateClosure() {
- function EvalState() {
- this.ctm = new Float32Array(IDENTITY_MATRIX);
- this.font = null;
- this.textRenderingMode = TextRenderingMode.FILL;
- this.fillColorSpace = ColorSpace.singletons.gray;
- this.strokeColorSpace = ColorSpace.singletons.gray;
- }
- EvalState.prototype = {
- clone: function CanvasExtraState_clone() {
- return Object.create(this);
- }
- };
- return EvalState;
- }();
- var EvaluatorPreprocessor = function EvaluatorPreprocessorClosure() {
- // Specifies properties for each command
- //
- // If variableArgs === true: [0, `numArgs`] expected
- // If variableArgs === false: exactly `numArgs` expected
- var getOPMap = getLookupTableFactory(function (t) {
- // Graphic state
- t['w'] = {
- id: OPS.setLineWidth,
- numArgs: 1,
- variableArgs: false
- };
- t['J'] = {
- id: OPS.setLineCap,
- numArgs: 1,
- variableArgs: false
- };
- t['j'] = {
- id: OPS.setLineJoin,
- numArgs: 1,
- variableArgs: false
- };
- t['M'] = {
- id: OPS.setMiterLimit,
- numArgs: 1,
- variableArgs: false
- };
- t['d'] = {
- id: OPS.setDash,
- numArgs: 2,
- variableArgs: false
- };
- t['ri'] = {
- id: OPS.setRenderingIntent,
- numArgs: 1,
- variableArgs: false
- };
- t['i'] = {
- id: OPS.setFlatness,
- numArgs: 1,
- variableArgs: false
- };
- t['gs'] = {
- id: OPS.setGState,
- numArgs: 1,
- variableArgs: false
- };
- t['q'] = {
- id: OPS.save,
- numArgs: 0,
- variableArgs: false
- };
- t['Q'] = {
- id: OPS.restore,
- numArgs: 0,
- variableArgs: false
- };
- t['cm'] = {
- id: OPS.transform,
- numArgs: 6,
- variableArgs: false
- };
- // Path
- t['m'] = {
- id: OPS.moveTo,
- numArgs: 2,
- variableArgs: false
- };
- t['l'] = {
- id: OPS.lineTo,
- numArgs: 2,
- variableArgs: false
- };
- t['c'] = {
- id: OPS.curveTo,
- numArgs: 6,
- variableArgs: false
- };
- t['v'] = {
- id: OPS.curveTo2,
- numArgs: 4,
- variableArgs: false
- };
- t['y'] = {
- id: OPS.curveTo3,
- numArgs: 4,
- variableArgs: false
- };
- t['h'] = {
- id: OPS.closePath,
- numArgs: 0,
- variableArgs: false
- };
- t['re'] = {
- id: OPS.rectangle,
- numArgs: 4,
- variableArgs: false
- };
- t['S'] = {
- id: OPS.stroke,
- numArgs: 0,
- variableArgs: false
- };
- t['s'] = {
- id: OPS.closeStroke,
- numArgs: 0,
- variableArgs: false
- };
- t['f'] = {
- id: OPS.fill,
- numArgs: 0,
- variableArgs: false
- };
- t['F'] = {
- id: OPS.fill,
- numArgs: 0,
- variableArgs: false
- };
- t['f*'] = {
- id: OPS.eoFill,
- numArgs: 0,
- variableArgs: false
- };
- t['B'] = {
- id: OPS.fillStroke,
- numArgs: 0,
- variableArgs: false
- };
- t['B*'] = {
- id: OPS.eoFillStroke,
- numArgs: 0,
- variableArgs: false
- };
- t['b'] = {
- id: OPS.closeFillStroke,
- numArgs: 0,
- variableArgs: false
- };
- t['b*'] = {
- id: OPS.closeEOFillStroke,
- numArgs: 0,
- variableArgs: false
- };
- t['n'] = {
- id: OPS.endPath,
- numArgs: 0,
- variableArgs: false
- };
- // Clipping
- t['W'] = {
- id: OPS.clip,
- numArgs: 0,
- variableArgs: false
- };
- t['W*'] = {
- id: OPS.eoClip,
- numArgs: 0,
- variableArgs: false
- };
- // Text
- t['BT'] = {
- id: OPS.beginText,
- numArgs: 0,
- variableArgs: false
- };
- t['ET'] = {
- id: OPS.endText,
- numArgs: 0,
- variableArgs: false
- };
- t['Tc'] = {
- id: OPS.setCharSpacing,
- numArgs: 1,
- variableArgs: false
- };
- t['Tw'] = {
- id: OPS.setWordSpacing,
- numArgs: 1,
- variableArgs: false
- };
- t['Tz'] = {
- id: OPS.setHScale,
- numArgs: 1,
- variableArgs: false
- };
- t['TL'] = {
- id: OPS.setLeading,
- numArgs: 1,
- variableArgs: false
- };
- t['Tf'] = {
- id: OPS.setFont,
- numArgs: 2,
- variableArgs: false
- };
- t['Tr'] = {
- id: OPS.setTextRenderingMode,
- numArgs: 1,
- variableArgs: false
- };
- t['Ts'] = {
- id: OPS.setTextRise,
- numArgs: 1,
- variableArgs: false
- };
- t['Td'] = {
- id: OPS.moveText,
- numArgs: 2,
- variableArgs: false
- };
- t['TD'] = {
- id: OPS.setLeadingMoveText,
- numArgs: 2,
- variableArgs: false
- };
- t['Tm'] = {
- id: OPS.setTextMatrix,
- numArgs: 6,
- variableArgs: false
- };
- t['T*'] = {
- id: OPS.nextLine,
- numArgs: 0,
- variableArgs: false
- };
- t['Tj'] = {
- id: OPS.showText,
- numArgs: 1,
- variableArgs: false
- };
- t['TJ'] = {
- id: OPS.showSpacedText,
- numArgs: 1,
- variableArgs: false
- };
- t['\''] = {
- id: OPS.nextLineShowText,
- numArgs: 1,
- variableArgs: false
- };
- t['"'] = {
- id: OPS.nextLineSetSpacingShowText,
- numArgs: 3,
- variableArgs: false
- };
- // Type3 fonts
- t['d0'] = {
- id: OPS.setCharWidth,
- numArgs: 2,
- variableArgs: false
- };
- t['d1'] = {
- id: OPS.setCharWidthAndBounds,
- numArgs: 6,
- variableArgs: false
- };
- // Color
- t['CS'] = {
- id: OPS.setStrokeColorSpace,
- numArgs: 1,
- variableArgs: false
- };
- t['cs'] = {
- id: OPS.setFillColorSpace,
- numArgs: 1,
- variableArgs: false
- };
- t['SC'] = {
- id: OPS.setStrokeColor,
- numArgs: 4,
- variableArgs: true
- };
- t['SCN'] = {
- id: OPS.setStrokeColorN,
- numArgs: 33,
- variableArgs: true
- };
- t['sc'] = {
- id: OPS.setFillColor,
- numArgs: 4,
- variableArgs: true
- };
- t['scn'] = {
- id: OPS.setFillColorN,
- numArgs: 33,
- variableArgs: true
- };
- t['G'] = {
- id: OPS.setStrokeGray,
- numArgs: 1,
- variableArgs: false
- };
- t['g'] = {
- id: OPS.setFillGray,
- numArgs: 1,
- variableArgs: false
- };
- t['RG'] = {
- id: OPS.setStrokeRGBColor,
- numArgs: 3,
- variableArgs: false
- };
- t['rg'] = {
- id: OPS.setFillRGBColor,
- numArgs: 3,
- variableArgs: false
- };
- t['K'] = {
- id: OPS.setStrokeCMYKColor,
- numArgs: 4,
- variableArgs: false
- };
- t['k'] = {
- id: OPS.setFillCMYKColor,
- numArgs: 4,
- variableArgs: false
- };
- // Shading
- t['sh'] = {
- id: OPS.shadingFill,
- numArgs: 1,
- variableArgs: false
- };
- // Images
- t['BI'] = {
- id: OPS.beginInlineImage,
- numArgs: 0,
- variableArgs: false
- };
- t['ID'] = {
- id: OPS.beginImageData,
- numArgs: 0,
- variableArgs: false
- };
- t['EI'] = {
- id: OPS.endInlineImage,
- numArgs: 1,
- variableArgs: false
- };
- // XObjects
- t['Do'] = {
- id: OPS.paintXObject,
- numArgs: 1,
- variableArgs: false
- };
- t['MP'] = {
- id: OPS.markPoint,
- numArgs: 1,
- variableArgs: false
- };
- t['DP'] = {
- id: OPS.markPointProps,
- numArgs: 2,
- variableArgs: false
- };
- t['BMC'] = {
- id: OPS.beginMarkedContent,
- numArgs: 1,
- variableArgs: false
- };
- t['BDC'] = {
- id: OPS.beginMarkedContentProps,
- numArgs: 2,
- variableArgs: false
- };
- t['EMC'] = {
- id: OPS.endMarkedContent,
- numArgs: 0,
- variableArgs: false
- };
- // Compatibility
- t['BX'] = {
- id: OPS.beginCompat,
- numArgs: 0,
- variableArgs: false
- };
- t['EX'] = {
- id: OPS.endCompat,
- numArgs: 0,
- variableArgs: false
- };
- // (reserved partial commands for the lexer)
- t['BM'] = null;
- t['BD'] = null;
- t['true'] = null;
- t['fa'] = null;
- t['fal'] = null;
- t['fals'] = null;
- t['false'] = null;
- t['nu'] = null;
- t['nul'] = null;
- t['null'] = null;
- });
- function EvaluatorPreprocessor(stream, xref, stateManager) {
- this.opMap = getOPMap();
- // TODO(mduan): pass array of knownCommands rather than this.opMap
- // dictionary
- this.parser = new Parser(new Lexer(stream, this.opMap), false, xref);
- this.stateManager = stateManager;
- this.nonProcessedArgs = [];
- }
- EvaluatorPreprocessor.prototype = {
- get savedStatesDepth() {
- return this.stateManager.stateStack.length;
- },
- // |operation| is an object with two fields:
- //
- // - |fn| is an out param.
- //
- // - |args| is an inout param. On entry, it should have one of two values.
- //
- // - An empty array. This indicates that the caller is providing the
- // array in which the args will be stored in. The caller should use
- // this value if it can reuse a single array for each call to read().
- //
- // - |null|. This indicates that the caller needs this function to create
- // the array in which any args are stored in. If there are zero args,
- // this function will leave |operation.args| as |null| (thus avoiding
- // allocations that would occur if we used an empty array to represent
- // zero arguments). Otherwise, it will replace |null| with a new array
- // containing the arguments. The caller should use this value if it
- // cannot reuse an array for each call to read().
- //
- // These two modes are present because this function is very hot and so
- // avoiding allocations where possible is worthwhile.
- //
- read: function EvaluatorPreprocessor_read(operation) {
- var args = operation.args;
- while (true) {
- var obj = this.parser.getObj();
- if (isCmd(obj)) {
- var cmd = obj.cmd;
- // Check that the command is valid
- var opSpec = this.opMap[cmd];
- if (!opSpec) {
- warn('Unknown command "' + cmd + '"');
- continue;
- }
- var fn = opSpec.id;
- var numArgs = opSpec.numArgs;
- var argsLength = args !== null ? args.length : 0;
- if (!opSpec.variableArgs) {
- // Postscript commands can be nested, e.g. /F2 /GS2 gs 5.711 Tf
- if (argsLength !== numArgs) {
- var nonProcessedArgs = this.nonProcessedArgs;
- while (argsLength > numArgs) {
- nonProcessedArgs.push(args.shift());
- argsLength--;
- }
- while (argsLength < numArgs && nonProcessedArgs.length !== 0) {
- if (!args) {
- args = [];
- }
- args.unshift(nonProcessedArgs.pop());
- argsLength++;
- }
- }
- if (argsLength < numArgs) {
- // If we receive too few args, it's not possible to possible
- // to execute the command, so skip the command
- info('Command ' + fn + ': because expected ' + numArgs + ' args, but received ' + argsLength + ' args; skipping');
- args = null;
- continue;
- }
- } else if (argsLength > numArgs) {
- info('Command ' + fn + ': expected [0,' + numArgs + '] args, but received ' + argsLength + ' args');
- }
- // TODO figure out how to type-check vararg functions
- this.preprocessCommand(fn, args);
- operation.fn = fn;
- operation.args = args;
- return true;
- } else {
- if (isEOF(obj)) {
- return false;
- }
- // no more commands
- // argument
- if (obj !== null) {
- if (!args) {
- args = [];
- }
- args.push(obj);
- assert(args.length <= 33, 'Too many arguments');
- }
- }
- }
- },
- preprocessCommand: function EvaluatorPreprocessor_preprocessCommand(fn, args) {
- switch (fn | 0) {
- case OPS.save:
- this.stateManager.save();
- break;
- case OPS.restore:
- this.stateManager.restore();
- break;
- case OPS.transform:
- this.stateManager.transform(args);
- break;
- }
- }
- };
- return EvaluatorPreprocessor;
- }();
- var QueueOptimizer = function QueueOptimizerClosure() {
- function addState(parentState, pattern, fn) {
- var state = parentState;
- for (var i = 0, ii = pattern.length - 1; i < ii; i++) {
- var item = pattern[i];
- state = state[item] || (state[item] = []);
- }
- state[pattern[pattern.length - 1]] = fn;
- }
- function handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray) {
- // Handles special case of mainly LaTeX documents which use image masks to
- // draw lines with the current fill style.
- // 'count' groups of (save, transform, paintImageMaskXObject, restore)+
- // have been found at iFirstSave.
- var iFirstPIMXO = iFirstSave + 2;
- for (var i = 0; i < count; i++) {
- var arg = argsArray[iFirstPIMXO + 4 * i];
- var imageMask = arg.length === 1 && arg[0];
- if (imageMask && imageMask.width === 1 && imageMask.height === 1 && (!imageMask.data.length || imageMask.data.length === 1 && imageMask.data[0] === 0)) {
- fnArray[iFirstPIMXO + 4 * i] = OPS.paintSolidColorImageMask;
- continue;
- }
- break;
- }
- return count - i;
- }
- var InitialState = [];
- // This replaces (save, transform, paintInlineImageXObject, restore)+
- // sequences with one |paintInlineImageXObjectGroup| operation.
- addState(InitialState, [
- OPS.save,
- OPS.transform,
- OPS.paintInlineImageXObject,
- OPS.restore
- ], function foundInlineImageGroup(context) {
- var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;
- var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
- var MAX_WIDTH = 1000;
- var IMAGE_PADDING = 1;
- var fnArray = context.fnArray, argsArray = context.argsArray;
- var curr = context.iCurr;
- var iFirstSave = curr - 3;
- var iFirstTransform = curr - 2;
- var iFirstPIIXO = curr - 1;
- // Look for the quartets.
- var i = iFirstSave + 4;
- var ii = fnArray.length;
- while (i + 3 < ii) {
- if (fnArray[i] !== OPS.save || fnArray[i + 1] !== OPS.transform || fnArray[i + 2] !== OPS.paintInlineImageXObject || fnArray[i + 3] !== OPS.restore) {
- break;
- }
- // ops don't match
- i += 4;
- }
- // At this point, i is the index of the first op past the last valid
- // quartet.
- var count = Math.min((i - iFirstSave) / 4, MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
- if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
- return i;
- }
- // assuming that heights of those image is too small (~1 pixel)
- // packing as much as possible by lines
- var maxX = 0;
- var map = [], maxLineHeight = 0;
- var currentX = IMAGE_PADDING, currentY = IMAGE_PADDING;
- var q;
- for (q = 0; q < count; q++) {
- var transform = argsArray[iFirstTransform + (q << 2)];
- var img = argsArray[iFirstPIIXO + (q << 2)][0];
- if (currentX + img.width > MAX_WIDTH) {
- // starting new line
- maxX = Math.max(maxX, currentX);
- currentY += maxLineHeight + 2 * IMAGE_PADDING;
- currentX = 0;
- maxLineHeight = 0;
- }
- map.push({
- transform: transform,
- x: currentX,
- y: currentY,
- w: img.width,
- h: img.height
- });
- currentX += img.width + 2 * IMAGE_PADDING;
- maxLineHeight = Math.max(maxLineHeight, img.height);
- }
- var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;
- var imgHeight = currentY + maxLineHeight + IMAGE_PADDING;
- var imgData = new Uint8Array(imgWidth * imgHeight * 4);
- var imgRowSize = imgWidth << 2;
- for (q = 0; q < count; q++) {
- var data = argsArray[iFirstPIIXO + (q << 2)][0].data;
- // Copy image by lines and extends pixels into padding.
- var rowSize = map[q].w << 2;
- var dataOffset = 0;
- var offset = map[q].x + map[q].y * imgWidth << 2;
- imgData.set(data.subarray(0, rowSize), offset - imgRowSize);
- for (var k = 0, kk = map[q].h; k < kk; k++) {
- imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset);
- dataOffset += rowSize;
- offset += imgRowSize;
- }
- imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset);
- while (offset >= 0) {
- data[offset - 4] = data[offset];
- data[offset - 3] = data[offset + 1];
- data[offset - 2] = data[offset + 2];
- data[offset - 1] = data[offset + 3];
- data[offset + rowSize] = data[offset + rowSize - 4];
- data[offset + rowSize + 1] = data[offset + rowSize - 3];
- data[offset + rowSize + 2] = data[offset + rowSize - 2];
- data[offset + rowSize + 3] = data[offset + rowSize - 1];
- offset -= imgRowSize;
- }
- }
- // Replace queue items.
- fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup);
- argsArray.splice(iFirstSave, count * 4, [
- {
- width: imgWidth,
- height: imgHeight,
- kind: ImageKind.RGBA_32BPP,
- data: imgData
- },
- map
- ]);
- return iFirstSave + 1;
- });
- // This replaces (save, transform, paintImageMaskXObject, restore)+
- // sequences with one |paintImageMaskXObjectGroup| or one
- // |paintImageMaskXObjectRepeat| operation.
- addState(InitialState, [
- OPS.save,
- OPS.transform,
- OPS.paintImageMaskXObject,
- OPS.restore
- ], function foundImageMaskGroup(context) {
- var MIN_IMAGES_IN_MASKS_BLOCK = 10;
- var MAX_IMAGES_IN_MASKS_BLOCK = 100;
- var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000;
- var fnArray = context.fnArray, argsArray = context.argsArray;
- var curr = context.iCurr;
- var iFirstSave = curr - 3;
- var iFirstTransform = curr - 2;
- var iFirstPIMXO = curr - 1;
- // Look for the quartets.
- var i = iFirstSave + 4;
- var ii = fnArray.length;
- while (i + 3 < ii) {
- if (fnArray[i] !== OPS.save || fnArray[i + 1] !== OPS.transform || fnArray[i + 2] !== OPS.paintImageMaskXObject || fnArray[i + 3] !== OPS.restore) {
- break;
- }
- // ops don't match
- i += 4;
- }
- // At this point, i is the index of the first op past the last valid
- // quartet.
- var count = (i - iFirstSave) / 4;
- count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray);
- if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
- return i;
- }
- var q;
- var isSameImage = false;
- var iTransform, transformArgs;
- var firstPIMXOArg0 = argsArray[iFirstPIMXO][0];
- if (argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0) {
- isSameImage = true;
- var firstTransformArg0 = argsArray[iFirstTransform][0];
- var firstTransformArg3 = argsArray[iFirstTransform][3];
- iTransform = iFirstTransform + 4;
- var iPIMXO = iFirstPIMXO + 4;
- for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) {
- transformArgs = argsArray[iTransform];
- if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || transformArgs[0] !== firstTransformArg0 || transformArgs[1] !== 0 || transformArgs[2] !== 0 || transformArgs[3] !== firstTransformArg3) {
- if (q < MIN_IMAGES_IN_MASKS_BLOCK) {
- isSameImage = false;
- } else {
- count = q;
- }
- break;
- }
- }
- }
- // different image or transform
- if (isSameImage) {
- count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK);
- var positions = new Float32Array(count * 2);
- iTransform = iFirstTransform;
- for (q = 0; q < count; q++, iTransform += 4) {
- transformArgs = argsArray[iTransform];
- positions[q << 1] = transformArgs[4];
- positions[(q << 1) + 1] = transformArgs[5];
- }
- // Replace queue items.
- fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat);
- argsArray.splice(iFirstSave, count * 4, [
- firstPIMXOArg0,
- firstTransformArg0,
- firstTransformArg3,
- positions
- ]);
- } else {
- count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);
- var images = [];
- for (q = 0; q < count; q++) {
- transformArgs = argsArray[iFirstTransform + (q << 2)];
- var maskParams = argsArray[iFirstPIMXO + (q << 2)][0];
- images.push({
- data: maskParams.data,
- width: maskParams.width,
- height: maskParams.height,
- transform: transformArgs
- });
- }
- // Replace queue items.
- fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectGroup);
- argsArray.splice(iFirstSave, count * 4, [images]);
- }
- return iFirstSave + 1;
- });
- // This replaces (save, transform, paintImageXObject, restore)+ sequences
- // with one paintImageXObjectRepeat operation, if the |transform| and
- // |paintImageXObjectRepeat| ops are appropriate.
- addState(InitialState, [
- OPS.save,
- OPS.transform,
- OPS.paintImageXObject,
- OPS.restore
- ], function (context) {
- var MIN_IMAGES_IN_BLOCK = 3;
- var MAX_IMAGES_IN_BLOCK = 1000;
- var fnArray = context.fnArray, argsArray = context.argsArray;
- var curr = context.iCurr;
- var iFirstSave = curr - 3;
- var iFirstTransform = curr - 2;
- var iFirstPIXO = curr - 1;
- var iFirstRestore = curr;
- if (argsArray[iFirstTransform][1] !== 0 || argsArray[iFirstTransform][2] !== 0) {
- return iFirstRestore + 1;
- }
- // transform has the wrong form
- // Look for the quartets.
- var firstPIXOArg0 = argsArray[iFirstPIXO][0];
- var firstTransformArg0 = argsArray[iFirstTransform][0];
- var firstTransformArg3 = argsArray[iFirstTransform][3];
- var i = iFirstSave + 4;
- var ii = fnArray.length;
- while (i + 3 < ii) {
- if (fnArray[i] !== OPS.save || fnArray[i + 1] !== OPS.transform || fnArray[i + 2] !== OPS.paintImageXObject || fnArray[i + 3] !== OPS.restore) {
- break;
- }
- // ops don't match
- if (argsArray[i + 1][0] !== firstTransformArg0 || argsArray[i + 1][1] !== 0 || argsArray[i + 1][2] !== 0 || argsArray[i + 1][3] !== firstTransformArg3) {
- break;
- }
- // transforms don't match
- if (argsArray[i + 2][0] !== firstPIXOArg0) {
- break;
- }
- // images don't match
- i += 4;
- }
- // At this point, i is the index of the first op past the last valid
- // quartet.
- var count = Math.min((i - iFirstSave) / 4, MAX_IMAGES_IN_BLOCK);
- if (count < MIN_IMAGES_IN_BLOCK) {
- return i;
- }
- // Extract the (x,y) positions from all of the matching transforms.
- var positions = new Float32Array(count * 2);
- var iTransform = iFirstTransform;
- for (var q = 0; q < count; q++, iTransform += 4) {
- var transformArgs = argsArray[iTransform];
- positions[q << 1] = transformArgs[4];
- positions[(q << 1) + 1] = transformArgs[5];
- }
- // Replace queue items.
- var args = [
- firstPIXOArg0,
- firstTransformArg0,
- firstTransformArg3,
- positions
- ];
- fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat);
- argsArray.splice(iFirstSave, count * 4, args);
- return iFirstSave + 1;
- });
- // This replaces (beginText, setFont, setTextMatrix, showText, endText)+
- // sequences with (beginText, setFont, (setTextMatrix, showText)+, endText)+
- // sequences, if the font for each one is the same.
- addState(InitialState, [
- OPS.beginText,
- OPS.setFont,
- OPS.setTextMatrix,
- OPS.showText,
- OPS.endText
- ], function (context) {
- var MIN_CHARS_IN_BLOCK = 3;
- var MAX_CHARS_IN_BLOCK = 1000;
- var fnArray = context.fnArray, argsArray = context.argsArray;
- var curr = context.iCurr;
- var iFirstBeginText = curr - 4;
- var iFirstSetFont = curr - 3;
- var iFirstSetTextMatrix = curr - 2;
- var iFirstShowText = curr - 1;
- var iFirstEndText = curr;
- // Look for the quintets.
- var firstSetFontArg0 = argsArray[iFirstSetFont][0];
- var firstSetFontArg1 = argsArray[iFirstSetFont][1];
- var i = iFirstBeginText + 5;
- var ii = fnArray.length;
- while (i + 4 < ii) {
- if (fnArray[i] !== OPS.beginText || fnArray[i + 1] !== OPS.setFont || fnArray[i + 2] !== OPS.setTextMatrix || fnArray[i + 3] !== OPS.showText || fnArray[i + 4] !== OPS.endText) {
- break;
- }
- // ops don't match
- if (argsArray[i + 1][0] !== firstSetFontArg0 || argsArray[i + 1][1] !== firstSetFontArg1) {
- break;
- }
- // fonts don't match
- i += 5;
- }
- // At this point, i is the index of the first op past the last valid
- // quintet.
- var count = Math.min((i - iFirstBeginText) / 5, MAX_CHARS_IN_BLOCK);
- if (count < MIN_CHARS_IN_BLOCK) {
- return i;
- }
- // If the preceding quintet is (<something>, setFont, setTextMatrix,
- // showText, endText), include that as well. (E.g. <something> might be
- // |dependency|.)
- var iFirst = iFirstBeginText;
- if (iFirstBeginText >= 4 && fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) {
- count++;
- iFirst -= 5;
- }
- // Remove (endText, beginText, setFont) trios.
- var iEndText = iFirst + 4;
- for (var q = 1; q < count; q++) {
- fnArray.splice(iEndText, 3);
- argsArray.splice(iEndText, 3);
- iEndText += 2;
- }
- return iEndText + 1;
- });
- function QueueOptimizer() {
- }
- QueueOptimizer.prototype = {
- optimize: function QueueOptimizer_optimize(queue) {
- var fnArray = queue.fnArray, argsArray = queue.argsArray;
- var context = {
- iCurr: 0,
- fnArray: fnArray,
- argsArray: argsArray
- };
- var state;
- var i = 0, ii = fnArray.length;
- while (i < ii) {
- state = (state || InitialState)[fnArray[i]];
- if (typeof state === 'function') {
- // we found some handler
- context.iCurr = i;
- // state() returns the index of the first non-matching op (if we
- // didn't match) or the first op past the modified ops (if we did
- // match and replace).
- i = state(context);
- state = undefined;
- // reset the state machine
- ii = context.fnArray.length;
- } else {
- i++;
- }
- }
- }
- };
- return QueueOptimizer;
- }();
- exports.OperatorList = OperatorList;
- exports.PartialEvaluator = PartialEvaluator;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreAnnotation = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreStream, root.pdfjsCoreColorSpace, root.pdfjsCoreObj, root.pdfjsCoreEvaluator);
- }(this, function (exports, sharedUtil, corePrimitives, coreStream, coreColorSpace, coreObj, coreEvaluator) {
- var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType;
- var AnnotationFieldFlag = sharedUtil.AnnotationFieldFlag;
- var AnnotationFlag = sharedUtil.AnnotationFlag;
- var AnnotationType = sharedUtil.AnnotationType;
- var OPS = sharedUtil.OPS;
- var Util = sharedUtil.Util;
- var isString = sharedUtil.isString;
- var isArray = sharedUtil.isArray;
- var isInt = sharedUtil.isInt;
- var stringToBytes = sharedUtil.stringToBytes;
- var stringToPDFString = sharedUtil.stringToPDFString;
- var warn = sharedUtil.warn;
- var Dict = corePrimitives.Dict;
- var isDict = corePrimitives.isDict;
- var isName = corePrimitives.isName;
- var isRef = corePrimitives.isRef;
- var Stream = coreStream.Stream;
- var ColorSpace = coreColorSpace.ColorSpace;
- var Catalog = coreObj.Catalog;
- var ObjectLoader = coreObj.ObjectLoader;
- var FileSpec = coreObj.FileSpec;
- var OperatorList = coreEvaluator.OperatorList;
- /**
- * @class
- * @alias AnnotationFactory
- */
- function AnnotationFactory() {
- }
- AnnotationFactory.prototype = /** @lends AnnotationFactory.prototype */
- {
- /**
- * @param {XRef} xref
- * @param {Object} ref
- * @param {PDFManager} pdfManager
- * @param {string} uniquePrefix
- * @param {Object} idCounters
- * @returns {Annotation}
- */
- create: function AnnotationFactory_create(xref, ref, pdfManager, uniquePrefix, idCounters) {
- var dict = xref.fetchIfRef(ref);
- if (!isDict(dict)) {
- return;
- }
- var id = isRef(ref) ? ref.toString() : 'annot_' + (uniquePrefix || '') + ++idCounters.obj;
- // Determine the annotation's subtype.
- var subtype = dict.get('Subtype');
- subtype = isName(subtype) ? subtype.name : null;
- // Return the right annotation object based on the subtype and field type.
- var parameters = {
- xref: xref,
- dict: dict,
- ref: isRef(ref) ? ref : null,
- subtype: subtype,
- id: id,
- pdfManager: pdfManager
- };
- switch (subtype) {
- case 'Link':
- return new LinkAnnotation(parameters);
- case 'Text':
- return new TextAnnotation(parameters);
- case 'Widget':
- var fieldType = Util.getInheritableProperty(dict, 'FT');
- fieldType = isName(fieldType) ? fieldType.name : null;
- switch (fieldType) {
- case 'Tx':
- return new TextWidgetAnnotation(parameters);
- case 'Ch':
- return new ChoiceWidgetAnnotation(parameters);
- }
- warn('Unimplemented widget field type "' + fieldType + '", ' + 'falling back to base field type.');
- return new WidgetAnnotation(parameters);
- case 'Popup':
- return new PopupAnnotation(parameters);
- case 'Highlight':
- return new HighlightAnnotation(parameters);
- case 'Underline':
- return new UnderlineAnnotation(parameters);
- case 'Squiggly':
- return new SquigglyAnnotation(parameters);
- case 'StrikeOut':
- return new StrikeOutAnnotation(parameters);
- case 'FileAttachment':
- return new FileAttachmentAnnotation(parameters);
- default:
- if (!subtype) {
- warn('Annotation is missing the required /Subtype.');
- } else {
- warn('Unimplemented annotation type "' + subtype + '", ' + 'falling back to base annotation.');
- }
- return new Annotation(parameters);
- }
- }
- };
- var Annotation = function AnnotationClosure() {
- // 12.5.5: Algorithm: Appearance streams
- function getTransformMatrix(rect, bbox, matrix) {
- var bounds = Util.getAxialAlignedBoundingBox(bbox, matrix);
- var minX = bounds[0];
- var minY = bounds[1];
- var maxX = bounds[2];
- var maxY = bounds[3];
- if (minX === maxX || minY === maxY) {
- // From real-life file, bbox was [0, 0, 0, 0]. In this case,
- // just apply the transform for rect
- return [
- 1,
- 0,
- 0,
- 1,
- rect[0],
- rect[1]
- ];
- }
- var xRatio = (rect[2] - rect[0]) / (maxX - minX);
- var yRatio = (rect[3] - rect[1]) / (maxY - minY);
- return [
- xRatio,
- 0,
- 0,
- yRatio,
- rect[0] - minX * xRatio,
- rect[1] - minY * yRatio
- ];
- }
- function getDefaultAppearance(dict) {
- var appearanceState = dict.get('AP');
- if (!isDict(appearanceState)) {
- return;
- }
- var appearance;
- var appearances = appearanceState.get('N');
- if (isDict(appearances)) {
- var as = dict.get('AS');
- if (as && appearances.has(as.name)) {
- appearance = appearances.get(as.name);
- }
- } else {
- appearance = appearances;
- }
- return appearance;
- }
- function Annotation(params) {
- var dict = params.dict;
- this.setFlags(dict.get('F'));
- this.setRectangle(dict.getArray('Rect'));
- this.setColor(dict.getArray('C'));
- this.setBorderStyle(dict);
- this.appearance = getDefaultAppearance(dict);
- // Expose public properties using a data object.
- this.data = {};
- this.data.id = params.id;
- this.data.subtype = params.subtype;
- this.data.annotationFlags = this.flags;
- this.data.rect = this.rectangle;
- this.data.color = this.color;
- this.data.borderStyle = this.borderStyle;
- this.data.hasAppearance = !!this.appearance;
- }
- Annotation.prototype = {
- /**
- * @private
- */
- _hasFlag: function Annotation_hasFlag(flags, flag) {
- return !!(flags & flag);
- },
- /**
- * @private
- */
- _isViewable: function Annotation_isViewable(flags) {
- return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, AnnotationFlag.HIDDEN) && !this._hasFlag(flags, AnnotationFlag.NOVIEW);
- },
- /**
- * @private
- */
- _isPrintable: function AnnotationFlag_isPrintable(flags) {
- return this._hasFlag(flags, AnnotationFlag.PRINT) && !this._hasFlag(flags, AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, AnnotationFlag.HIDDEN);
- },
- /**
- * @return {boolean}
- */
- get viewable() {
- if (this.flags === 0) {
- return true;
- }
- return this._isViewable(this.flags);
- },
- /**
- * @return {boolean}
- */
- get printable() {
- if (this.flags === 0) {
- return false;
- }
- return this._isPrintable(this.flags);
- },
- /**
- * Set the flags.
- *
- * @public
- * @memberof Annotation
- * @param {number} flags - Unsigned 32-bit integer specifying annotation
- * characteristics
- * @see {@link shared/util.js}
- */
- setFlags: function Annotation_setFlags(flags) {
- this.flags = isInt(flags) && flags > 0 ? flags : 0;
- },
- /**
- * Check if a provided flag is set.
- *
- * @public
- * @memberof Annotation
- * @param {number} flag - Hexadecimal representation for an annotation
- * characteristic
- * @return {boolean}
- * @see {@link shared/util.js}
- */
- hasFlag: function Annotation_hasFlag(flag) {
- return this._hasFlag(this.flags, flag);
- },
- /**
- * Set the rectangle.
- *
- * @public
- * @memberof Annotation
- * @param {Array} rectangle - The rectangle array with exactly four entries
- */
- setRectangle: function Annotation_setRectangle(rectangle) {
- if (isArray(rectangle) && rectangle.length === 4) {
- this.rectangle = Util.normalizeRect(rectangle);
- } else {
- this.rectangle = [
- 0,
- 0,
- 0,
- 0
- ];
- }
- },
- /**
- * Set the color and take care of color space conversion.
- *
- * @public
- * @memberof Annotation
- * @param {Array} color - The color array containing either 0
- * (transparent), 1 (grayscale), 3 (RGB) or
- * 4 (CMYK) elements
- */
- setColor: function Annotation_setColor(color) {
- var rgbColor = new Uint8Array(3);
- // Black in RGB color space (default)
- if (!isArray(color)) {
- this.color = rgbColor;
- return;
- }
- switch (color.length) {
- case 0:
- // Transparent, which we indicate with a null value
- this.color = null;
- break;
- case 1:
- // Convert grayscale to RGB
- ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0);
- this.color = rgbColor;
- break;
- case 3:
- // Convert RGB percentages to RGB
- ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0);
- this.color = rgbColor;
- break;
- case 4:
- // Convert CMYK to RGB
- ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0);
- this.color = rgbColor;
- break;
- default:
- this.color = rgbColor;
- break;
- }
- },
- /**
- * Set the border style (as AnnotationBorderStyle object).
- *
- * @public
- * @memberof Annotation
- * @param {Dict} borderStyle - The border style dictionary
- */
- setBorderStyle: function Annotation_setBorderStyle(borderStyle) {
- this.borderStyle = new AnnotationBorderStyle();
- if (!isDict(borderStyle)) {
- return;
- }
- if (borderStyle.has('BS')) {
- var dict = borderStyle.get('BS');
- var dictType = dict.get('Type');
- if (!dictType || isName(dictType, 'Border')) {
- this.borderStyle.setWidth(dict.get('W'));
- this.borderStyle.setStyle(dict.get('S'));
- this.borderStyle.setDashArray(dict.getArray('D'));
- }
- } else if (borderStyle.has('Border')) {
- var array = borderStyle.getArray('Border');
- if (isArray(array) && array.length >= 3) {
- this.borderStyle.setHorizontalCornerRadius(array[0]);
- this.borderStyle.setVerticalCornerRadius(array[1]);
- this.borderStyle.setWidth(array[2]);
- if (array.length === 4) {
- // Dash array available
- this.borderStyle.setDashArray(array[3]);
- }
- }
- } else {
- // There are no border entries in the dictionary. According to the
- // specification, we should draw a solid border of width 1 in that
- // case, but Adobe Reader did not implement that part of the
- // specification and instead draws no border at all, so we do the same.
- // See also https://github.com/mozilla/pdf.js/issues/6179.
- this.borderStyle.setWidth(0);
- }
- },
- /**
- * Prepare the annotation for working with a popup in the display layer.
- *
- * @private
- * @memberof Annotation
- * @param {Dict} dict - The annotation's data dictionary
- */
- _preparePopup: function Annotation_preparePopup(dict) {
- if (!dict.has('C')) {
- // Fall back to the default background color.
- this.data.color = null;
- }
- this.data.hasPopup = dict.has('Popup');
- this.data.title = stringToPDFString(dict.get('T') || '');
- this.data.contents = stringToPDFString(dict.get('Contents') || '');
- },
- loadResources: function Annotation_loadResources(keys) {
- return new Promise(function (resolve, reject) {
- this.appearance.dict.getAsync('Resources').then(function (resources) {
- if (!resources) {
- resolve();
- return;
- }
- var objectLoader = new ObjectLoader(resources.map, keys, resources.xref);
- objectLoader.load().then(function () {
- resolve(resources);
- }, reject);
- }, reject);
- }.bind(this));
- },
- getOperatorList: function Annotation_getOperatorList(evaluator, task, renderForms) {
- if (!this.appearance) {
- return Promise.resolve(new OperatorList());
- }
- var data = this.data;
- var appearanceDict = this.appearance.dict;
- var resourcesPromise = this.loadResources([
- 'ExtGState',
- 'ColorSpace',
- 'Pattern',
- 'Shading',
- 'XObject',
- 'Font'
- ]);
- // ProcSet
- // Properties
- var bbox = appearanceDict.getArray('BBox') || [
- 0,
- 0,
- 1,
- 1
- ];
- var matrix = appearanceDict.getArray('Matrix') || [
- 1,
- 0,
- 0,
- 1,
- 0,
- 0
- ];
- var transform = getTransformMatrix(data.rect, bbox, matrix);
- var self = this;
- return resourcesPromise.then(function (resources) {
- var opList = new OperatorList();
- opList.addOp(OPS.beginAnnotation, [
- data.rect,
- transform,
- matrix
- ]);
- return evaluator.getOperatorList(self.appearance, task, resources, opList).then(function () {
- opList.addOp(OPS.endAnnotation, []);
- self.appearance.reset();
- return opList;
- });
- });
- }
- };
- Annotation.appendToOperatorList = function Annotation_appendToOperatorList(annotations, opList, partialEvaluator, task, intent, renderForms) {
- var annotationPromises = [];
- for (var i = 0, n = annotations.length; i < n; ++i) {
- if (intent === 'display' && annotations[i].viewable || intent === 'print' && annotations[i].printable) {
- annotationPromises.push(annotations[i].getOperatorList(partialEvaluator, task, renderForms));
- }
- }
- return Promise.all(annotationPromises).then(function (operatorLists) {
- opList.addOp(OPS.beginAnnotations, []);
- for (var i = 0, n = operatorLists.length; i < n; ++i) {
- opList.addOpList(operatorLists[i]);
- }
- opList.addOp(OPS.endAnnotations, []);
- });
- };
- return Annotation;
- }();
- /**
- * Contains all data regarding an annotation's border style.
- *
- * @class
- */
- var AnnotationBorderStyle = function AnnotationBorderStyleClosure() {
- /**
- * @constructor
- * @private
- */
- function AnnotationBorderStyle() {
- this.width = 1;
- this.style = AnnotationBorderStyleType.SOLID;
- this.dashArray = [3];
- this.horizontalCornerRadius = 0;
- this.verticalCornerRadius = 0;
- }
- AnnotationBorderStyle.prototype = {
- /**
- * Set the width.
- *
- * @public
- * @memberof AnnotationBorderStyle
- * @param {integer} width - The width
- */
- setWidth: function AnnotationBorderStyle_setWidth(width) {
- if (width === (width | 0)) {
- this.width = width;
- }
- },
- /**
- * Set the style.
- *
- * @public
- * @memberof AnnotationBorderStyle
- * @param {Object} style - The style object
- * @see {@link shared/util.js}
- */
- setStyle: function AnnotationBorderStyle_setStyle(style) {
- if (!style) {
- return;
- }
- switch (style.name) {
- case 'S':
- this.style = AnnotationBorderStyleType.SOLID;
- break;
- case 'D':
- this.style = AnnotationBorderStyleType.DASHED;
- break;
- case 'B':
- this.style = AnnotationBorderStyleType.BEVELED;
- break;
- case 'I':
- this.style = AnnotationBorderStyleType.INSET;
- break;
- case 'U':
- this.style = AnnotationBorderStyleType.UNDERLINE;
- break;
- default:
- break;
- }
- },
- /**
- * Set the dash array.
- *
- * @public
- * @memberof AnnotationBorderStyle
- * @param {Array} dashArray - The dash array with at least one element
- */
- setDashArray: function AnnotationBorderStyle_setDashArray(dashArray) {
- // We validate the dash array, but we do not use it because CSS does not
- // allow us to change spacing of dashes. For more information, visit
- // http://www.w3.org/TR/css3-background/#the-border-style.
- if (isArray(dashArray) && dashArray.length > 0) {
- // According to the PDF specification: the elements in a dashArray
- // shall be numbers that are nonnegative and not all equal to zero.
- var isValid = true;
- var allZeros = true;
- for (var i = 0, len = dashArray.length; i < len; i++) {
- var element = dashArray[i];
- var validNumber = +element >= 0;
- if (!validNumber) {
- isValid = false;
- break;
- } else if (element > 0) {
- allZeros = false;
- }
- }
- if (isValid && !allZeros) {
- this.dashArray = dashArray;
- } else {
- this.width = 0;
- }
- } else // Adobe behavior when the array is invalid.
- if (dashArray) {
- this.width = 0;
- }
- },
- // Adobe behavior when the array is invalid.
- /**
- * Set the horizontal corner radius (from a Border dictionary).
- *
- * @public
- * @memberof AnnotationBorderStyle
- * @param {integer} radius - The horizontal corner radius
- */
- setHorizontalCornerRadius: function AnnotationBorderStyle_setHorizontalCornerRadius(radius) {
- if (radius === (radius | 0)) {
- this.horizontalCornerRadius = radius;
- }
- },
- /**
- * Set the vertical corner radius (from a Border dictionary).
- *
- * @public
- * @memberof AnnotationBorderStyle
- * @param {integer} radius - The vertical corner radius
- */
- setVerticalCornerRadius: function AnnotationBorderStyle_setVerticalCornerRadius(radius) {
- if (radius === (radius | 0)) {
- this.verticalCornerRadius = radius;
- }
- }
- };
- return AnnotationBorderStyle;
- }();
- var WidgetAnnotation = function WidgetAnnotationClosure() {
- function WidgetAnnotation(params) {
- Annotation.call(this, params);
- var dict = params.dict;
- var data = this.data;
- data.annotationType = AnnotationType.WIDGET;
- data.fieldName = this._constructFieldName(dict);
- data.fieldValue = Util.getInheritableProperty(dict, 'V', /* getArray = */
- true);
- data.alternativeText = stringToPDFString(dict.get('TU') || '');
- data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || '';
- var fieldType = Util.getInheritableProperty(dict, 'FT');
- data.fieldType = isName(fieldType) ? fieldType.name : null;
- this.fieldResources = Util.getInheritableProperty(dict, 'DR') || Dict.empty;
- data.fieldFlags = Util.getInheritableProperty(dict, 'Ff');
- if (!isInt(data.fieldFlags) || data.fieldFlags < 0) {
- data.fieldFlags = 0;
- }
- data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY);
- // Hide signatures because we cannot validate them.
- if (data.fieldType === 'Sig') {
- this.setFlags(AnnotationFlag.HIDDEN);
- }
- }
- Util.inherit(WidgetAnnotation, Annotation, {
- /**
- * Construct the (fully qualified) field name from the (partial) field
- * names of the field and its ancestors.
- *
- * @private
- * @memberof WidgetAnnotation
- * @param {Dict} dict - Complete widget annotation dictionary
- * @return {string}
- */
- _constructFieldName: function WidgetAnnotation_constructFieldName(dict) {
- // Both the `Parent` and `T` fields are optional. While at least one of
- // them should be provided, bad PDF generators may fail to do so.
- if (!dict.has('T') && !dict.has('Parent')) {
- warn('Unknown field name, falling back to empty field name.');
- return '';
- }
- // If no parent exists, the partial and fully qualified names are equal.
- if (!dict.has('Parent')) {
- return stringToPDFString(dict.get('T'));
- }
- // Form the fully qualified field name by appending the partial name to
- // the parent's fully qualified name, separated by a period.
- var fieldName = [];
- if (dict.has('T')) {
- fieldName.unshift(stringToPDFString(dict.get('T')));
- }
- var loopDict = dict;
- while (loopDict.has('Parent')) {
- loopDict = loopDict.get('Parent');
- if (loopDict.has('T')) {
- fieldName.unshift(stringToPDFString(loopDict.get('T')));
- }
- }
- return fieldName.join('.');
- },
- /**
- * Check if a provided field flag is set.
- *
- * @public
- * @memberof WidgetAnnotation
- * @param {number} flag - Hexadecimal representation for an annotation
- * field characteristic
- * @return {boolean}
- * @see {@link shared/util.js}
- */
- hasFieldFlag: function WidgetAnnotation_hasFieldFlag(flag) {
- return !!(this.data.fieldFlags & flag);
- }
- });
- return WidgetAnnotation;
- }();
- var TextWidgetAnnotation = function TextWidgetAnnotationClosure() {
- function TextWidgetAnnotation(params) {
- WidgetAnnotation.call(this, params);
- // The field value is always a string.
- this.data.fieldValue = stringToPDFString(this.data.fieldValue || '');
- // Determine the alignment of text in the field.
- var alignment = Util.getInheritableProperty(params.dict, 'Q');
- if (!isInt(alignment) || alignment < 0 || alignment > 2) {
- alignment = null;
- }
- this.data.textAlignment = alignment;
- // Determine the maximum length of text in the field.
- var maximumLength = Util.getInheritableProperty(params.dict, 'MaxLen');
- if (!isInt(maximumLength) || maximumLength < 0) {
- maximumLength = null;
- }
- this.data.maxLen = maximumLength;
- // Process field flags for the display layer.
- this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE);
- this.data.comb = this.hasFieldFlag(AnnotationFieldFlag.COMB) && !this.hasFieldFlag(AnnotationFieldFlag.MULTILINE) && !this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) && !this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) && this.data.maxLen !== null;
- }
- Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
- getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator, task, renderForms) {
- var operatorList = new OperatorList();
- // Do not render form elements on the canvas when interactive forms are
- // enabled. The display layer is responsible for rendering them instead.
- if (renderForms) {
- return Promise.resolve(operatorList);
- }
- if (this.appearance) {
- return Annotation.prototype.getOperatorList.call(this, evaluator, task, renderForms);
- }
- // Even if there is an appearance stream, ignore it. This is the
- // behaviour used by Adobe Reader.
- if (!this.data.defaultAppearance) {
- return Promise.resolve(operatorList);
- }
- var stream = new Stream(stringToBytes(this.data.defaultAppearance));
- return evaluator.getOperatorList(stream, task, this.fieldResources, operatorList).then(function () {
- return operatorList;
- });
- }
- });
- return TextWidgetAnnotation;
- }();
- var ChoiceWidgetAnnotation = function ChoiceWidgetAnnotationClosure() {
- function ChoiceWidgetAnnotation(params) {
- WidgetAnnotation.call(this, params);
- // Determine the options. The options array may consist of strings or
- // arrays. If the array consists of arrays, then the first element of
- // each array is the export value and the second element of each array is
- // the display value. If the array consists of strings, then these
- // represent both the export and display value. In this case, we convert
- // it to an array of arrays as well for convenience in the display layer.
- this.data.options = [];
- var options = params.dict.getArray('Opt');
- if (isArray(options)) {
- for (var i = 0, ii = options.length; i < ii; i++) {
- var option = options[i];
- this.data.options[i] = {
- exportValue: isArray(option) ? option[0] : option,
- displayValue: isArray(option) ? option[1] : option
- };
- }
- }
- // Determine the field value. In this case, it may be a string or an
- // array of strings. For convenience in the display layer, convert the
- // string to an array of one string as well.
- if (!isArray(this.data.fieldValue)) {
- this.data.fieldValue = [this.data.fieldValue];
- }
- // Process field flags for the display layer.
- this.data.combo = this.hasFieldFlag(AnnotationFieldFlag.COMBO);
- this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT);
- }
- Util.inherit(ChoiceWidgetAnnotation, WidgetAnnotation, {
- getOperatorList: function ChoiceWidgetAnnotation_getOperatorList(evaluator, task, renderForms) {
- var operatorList = new OperatorList();
- // Do not render form elements on the canvas when interactive forms are
- // enabled. The display layer is responsible for rendering them instead.
- if (renderForms) {
- return Promise.resolve(operatorList);
- }
- return Annotation.prototype.getOperatorList.call(this, evaluator, task, renderForms);
- }
- });
- return ChoiceWidgetAnnotation;
- }();
- var TextAnnotation = function TextAnnotationClosure() {
- var DEFAULT_ICON_SIZE = 22;
- // px
- function TextAnnotation(parameters) {
- Annotation.call(this, parameters);
- this.data.annotationType = AnnotationType.TEXT;
- if (this.data.hasAppearance) {
- this.data.name = 'NoIcon';
- } else {
- this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE;
- this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE;
- this.data.name = parameters.dict.has('Name') ? parameters.dict.get('Name').name : 'Note';
- }
- this._preparePopup(parameters.dict);
- }
- Util.inherit(TextAnnotation, Annotation, {});
- return TextAnnotation;
- }();
- var LinkAnnotation = function LinkAnnotationClosure() {
- function LinkAnnotation(params) {
- Annotation.call(this, params);
- var data = this.data;
- data.annotationType = AnnotationType.LINK;
- Catalog.parseDestDictionary({
- destDict: params.dict,
- resultObj: data,
- docBaseUrl: params.pdfManager.docBaseUrl
- });
- }
- Util.inherit(LinkAnnotation, Annotation, {});
- return LinkAnnotation;
- }();
- var PopupAnnotation = function PopupAnnotationClosure() {
- function PopupAnnotation(parameters) {
- Annotation.call(this, parameters);
- this.data.annotationType = AnnotationType.POPUP;
- var dict = parameters.dict;
- var parentItem = dict.get('Parent');
- if (!parentItem) {
- warn('Popup annotation has a missing or invalid parent annotation.');
- return;
- }
- this.data.parentId = dict.getRaw('Parent').toString();
- this.data.title = stringToPDFString(parentItem.get('T') || '');
- this.data.contents = stringToPDFString(parentItem.get('Contents') || '');
- if (!parentItem.has('C')) {
- // Fall back to the default background color.
- this.data.color = null;
- } else {
- this.setColor(parentItem.getArray('C'));
- this.data.color = this.color;
- }
- // If the Popup annotation is not viewable, but the parent annotation is,
- // that is most likely a bug. Fallback to inherit the flags from the parent
- // annotation (this is consistent with the behaviour in Adobe Reader).
- if (!this.viewable) {
- var parentFlags = parentItem.get('F');
- if (this._isViewable(parentFlags)) {
- this.setFlags(parentFlags);
- }
- }
- }
- Util.inherit(PopupAnnotation, Annotation, {});
- return PopupAnnotation;
- }();
- var HighlightAnnotation = function HighlightAnnotationClosure() {
- function HighlightAnnotation(parameters) {
- Annotation.call(this, parameters);
- this.data.annotationType = AnnotationType.HIGHLIGHT;
- this._preparePopup(parameters.dict);
- // PDF viewers completely ignore any border styles.
- this.data.borderStyle.setWidth(0);
- }
- Util.inherit(HighlightAnnotation, Annotation, {});
- return HighlightAnnotation;
- }();
- var UnderlineAnnotation = function UnderlineAnnotationClosure() {
- function UnderlineAnnotation(parameters) {
- Annotation.call(this, parameters);
- this.data.annotationType = AnnotationType.UNDERLINE;
- this._preparePopup(parameters.dict);
- // PDF viewers completely ignore any border styles.
- this.data.borderStyle.setWidth(0);
- }
- Util.inherit(UnderlineAnnotation, Annotation, {});
- return UnderlineAnnotation;
- }();
- var SquigglyAnnotation = function SquigglyAnnotationClosure() {
- function SquigglyAnnotation(parameters) {
- Annotation.call(this, parameters);
- this.data.annotationType = AnnotationType.SQUIGGLY;
- this._preparePopup(parameters.dict);
- // PDF viewers completely ignore any border styles.
- this.data.borderStyle.setWidth(0);
- }
- Util.inherit(SquigglyAnnotation, Annotation, {});
- return SquigglyAnnotation;
- }();
- var StrikeOutAnnotation = function StrikeOutAnnotationClosure() {
- function StrikeOutAnnotation(parameters) {
- Annotation.call(this, parameters);
- this.data.annotationType = AnnotationType.STRIKEOUT;
- this._preparePopup(parameters.dict);
- // PDF viewers completely ignore any border styles.
- this.data.borderStyle.setWidth(0);
- }
- Util.inherit(StrikeOutAnnotation, Annotation, {});
- return StrikeOutAnnotation;
- }();
- var FileAttachmentAnnotation = function FileAttachmentAnnotationClosure() {
- function FileAttachmentAnnotation(parameters) {
- Annotation.call(this, parameters);
- var file = new FileSpec(parameters.dict.get('FS'), parameters.xref);
- this.data.annotationType = AnnotationType.FILEATTACHMENT;
- this.data.file = file.serializable;
- this._preparePopup(parameters.dict);
- }
- Util.inherit(FileAttachmentAnnotation, Annotation, {});
- return FileAttachmentAnnotation;
- }();
- exports.Annotation = Annotation;
- exports.AnnotationBorderStyle = AnnotationBorderStyle;
- exports.AnnotationFactory = AnnotationFactory;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreDocument = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCoreStream, root.pdfjsCoreObj, root.pdfjsCoreParser, root.pdfjsCoreCrypto, root.pdfjsCoreEvaluator, root.pdfjsCoreAnnotation);
- }(this, function (exports, sharedUtil, corePrimitives, coreStream, coreObj, coreParser, coreCrypto, coreEvaluator, coreAnnotation) {
- var MissingDataException = sharedUtil.MissingDataException;
- var Util = sharedUtil.Util;
- var assert = sharedUtil.assert;
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var isArray = sharedUtil.isArray;
- var isArrayBuffer = sharedUtil.isArrayBuffer;
- var isString = sharedUtil.isString;
- var shadow = sharedUtil.shadow;
- var stringToBytes = sharedUtil.stringToBytes;
- var stringToPDFString = sharedUtil.stringToPDFString;
- var warn = sharedUtil.warn;
- var isSpace = sharedUtil.isSpace;
- var Dict = corePrimitives.Dict;
- var isDict = corePrimitives.isDict;
- var isName = corePrimitives.isName;
- var isStream = corePrimitives.isStream;
- var NullStream = coreStream.NullStream;
- var Stream = coreStream.Stream;
- var StreamsSequenceStream = coreStream.StreamsSequenceStream;
- var Catalog = coreObj.Catalog;
- var ObjectLoader = coreObj.ObjectLoader;
- var XRef = coreObj.XRef;
- var Linearization = coreParser.Linearization;
- var calculateMD5 = coreCrypto.calculateMD5;
- var OperatorList = coreEvaluator.OperatorList;
- var PartialEvaluator = coreEvaluator.PartialEvaluator;
- var Annotation = coreAnnotation.Annotation;
- var AnnotationFactory = coreAnnotation.AnnotationFactory;
- var Page = function PageClosure() {
- var LETTER_SIZE_MEDIABOX = [
- 0,
- 0,
- 612,
- 792
- ];
- function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache) {
- this.pdfManager = pdfManager;
- this.pageIndex = pageIndex;
- this.pageDict = pageDict;
- this.xref = xref;
- this.ref = ref;
- this.fontCache = fontCache;
- this.uniquePrefix = 'p' + this.pageIndex + '_';
- this.idCounters = { obj: 0 };
- this.evaluatorOptions = pdfManager.evaluatorOptions;
- this.resourcesPromise = null;
- }
- Page.prototype = {
- getPageProp: function Page_getPageProp(key) {
- return this.pageDict.get(key);
- },
- getInheritedPageProp: function Page_getInheritedPageProp(key) {
- var dict = this.pageDict, valueArray = null, loopCount = 0;
- var MAX_LOOP_COUNT = 100;
- // Always walk up the entire parent chain, to be able to find
- // e.g. \Resources placed on multiple levels of the tree.
- while (dict) {
- var value = dict.get(key);
- if (value) {
- if (!valueArray) {
- valueArray = [];
- }
- valueArray.push(value);
- }
- if (++loopCount > MAX_LOOP_COUNT) {
- warn('Page_getInheritedPageProp: maximum loop count exceeded.');
- break;
- }
- dict = dict.get('Parent');
- }
- if (!valueArray) {
- return Dict.empty;
- }
- if (valueArray.length === 1 || !isDict(valueArray[0]) || loopCount > MAX_LOOP_COUNT) {
- return valueArray[0];
- }
- return Dict.merge(this.xref, valueArray);
- },
- get content() {
- return this.getPageProp('Contents');
- },
- get resources() {
- // For robustness: The spec states that a \Resources entry has to be
- // present, but can be empty. Some document omit it still, in this case
- // we return an empty dictionary.
- return shadow(this, 'resources', this.getInheritedPageProp('Resources'));
- },
- get mediaBox() {
- var obj = this.getInheritedPageProp('MediaBox');
- // Reset invalid media box to letter size.
- if (!isArray(obj) || obj.length !== 4) {
- obj = LETTER_SIZE_MEDIABOX;
- }
- return shadow(this, 'mediaBox', obj);
- },
- get view() {
- var mediaBox = this.mediaBox;
- var cropBox = this.getInheritedPageProp('CropBox');
- if (!isArray(cropBox) || cropBox.length !== 4) {
- return shadow(this, 'view', mediaBox);
- }
- // From the spec, 6th ed., p.963:
- // "The crop, bleed, trim, and art boxes should not ordinarily
- // extend beyond the boundaries of the media box. If they do, they are
- // effectively reduced to their intersection with the media box."
- cropBox = Util.intersect(cropBox, mediaBox);
- if (!cropBox) {
- return shadow(this, 'view', mediaBox);
- }
- return shadow(this, 'view', cropBox);
- },
- get rotate() {
- var rotate = this.getInheritedPageProp('Rotate') || 0;
- // Normalize rotation so it's a multiple of 90 and between 0 and 270
- if (rotate % 90 !== 0) {
- rotate = 0;
- } else if (rotate >= 360) {
- rotate = rotate % 360;
- } else if (rotate < 0) {
- // The spec doesn't cover negatives, assume its counterclockwise
- // rotation. The following is the other implementation of modulo.
- rotate = (rotate % 360 + 360) % 360;
- }
- return shadow(this, 'rotate', rotate);
- },
- getContentStream: function Page_getContentStream() {
- var content = this.content;
- var stream;
- if (isArray(content)) {
- // fetching items
- var xref = this.xref;
- var i, n = content.length;
- var streams = [];
- for (i = 0; i < n; ++i) {
- streams.push(xref.fetchIfRef(content[i]));
- }
- stream = new StreamsSequenceStream(streams);
- } else if (isStream(content)) {
- stream = content;
- } else {
- // replacing non-existent page content with empty one
- stream = new NullStream();
- }
- return stream;
- },
- loadResources: function Page_loadResources(keys) {
- if (!this.resourcesPromise) {
- // TODO: add async getInheritedPageProp and remove this.
- this.resourcesPromise = this.pdfManager.ensure(this, 'resources');
- }
- return this.resourcesPromise.then(function resourceSuccess() {
- var objectLoader = new ObjectLoader(this.resources.map, keys, this.xref);
- return objectLoader.load();
- }.bind(this));
- },
- getOperatorList: function Page_getOperatorList(handler, task, intent, renderInteractiveForms) {
- var self = this;
- var pdfManager = this.pdfManager;
- var contentStreamPromise = pdfManager.ensure(this, 'getContentStream', []);
- var resourcesPromise = this.loadResources([
- 'ExtGState',
- 'ColorSpace',
- 'Pattern',
- 'Shading',
- 'XObject',
- 'Font'
- ]);
- // ProcSet
- // Properties
- var partialEvaluator = new PartialEvaluator(pdfManager, this.xref, handler, this.pageIndex, this.uniquePrefix, this.idCounters, this.fontCache, this.evaluatorOptions);
- var dataPromises = Promise.all([
- contentStreamPromise,
- resourcesPromise
- ]);
- var pageListPromise = dataPromises.then(function (data) {
- var contentStream = data[0];
- var opList = new OperatorList(intent, handler, self.pageIndex);
- handler.send('StartRenderPage', {
- transparency: partialEvaluator.hasBlendModes(self.resources),
- pageIndex: self.pageIndex,
- intent: intent
- });
- return partialEvaluator.getOperatorList(contentStream, task, self.resources, opList).then(function () {
- return opList;
- });
- });
- var annotationsPromise = pdfManager.ensure(this, 'annotations');
- return Promise.all([
- pageListPromise,
- annotationsPromise
- ]).then(function (datas) {
- var pageOpList = datas[0];
- var annotations = datas[1];
- if (annotations.length === 0) {
- pageOpList.flush(true);
- return pageOpList;
- }
- var annotationsReadyPromise = Annotation.appendToOperatorList(annotations, pageOpList, partialEvaluator, task, intent, renderInteractiveForms);
- return annotationsReadyPromise.then(function () {
- pageOpList.flush(true);
- return pageOpList;
- });
- });
- },
- extractTextContent: function Page_extractTextContent(task, normalizeWhitespace, combineTextItems) {
- var handler = {
- on: function nullHandlerOn() {
- },
- send: function nullHandlerSend() {
- }
- };
- var self = this;
- var pdfManager = this.pdfManager;
- var contentStreamPromise = pdfManager.ensure(this, 'getContentStream', []);
- var resourcesPromise = this.loadResources([
- 'ExtGState',
- 'XObject',
- 'Font'
- ]);
- var dataPromises = Promise.all([
- contentStreamPromise,
- resourcesPromise
- ]);
- return dataPromises.then(function (data) {
- var contentStream = data[0];
- var partialEvaluator = new PartialEvaluator(pdfManager, self.xref, handler, self.pageIndex, self.uniquePrefix, self.idCounters, self.fontCache, self.evaluatorOptions);
- return partialEvaluator.getTextContent(contentStream, task, self.resources, /* stateManager = */
- null, normalizeWhitespace, combineTextItems);
- });
- },
- getAnnotationsData: function Page_getAnnotationsData(intent) {
- var annotations = this.annotations;
- var annotationsData = [];
- for (var i = 0, n = annotations.length; i < n; ++i) {
- if (intent) {
- if (!(intent === 'display' && annotations[i].viewable) && !(intent === 'print' && annotations[i].printable)) {
- continue;
- }
- }
- annotationsData.push(annotations[i].data);
- }
- return annotationsData;
- },
- get annotations() {
- var annotations = [];
- var annotationRefs = this.getInheritedPageProp('Annots') || [];
- var annotationFactory = new AnnotationFactory();
- for (var i = 0, n = annotationRefs.length; i < n; ++i) {
- var annotationRef = annotationRefs[i];
- var annotation = annotationFactory.create(this.xref, annotationRef, this.pdfManager, this.uniquePrefix, this.idCounters);
- if (annotation) {
- annotations.push(annotation);
- }
- }
- return shadow(this, 'annotations', annotations);
- }
- };
- return Page;
- }();
- /**
- * The `PDFDocument` holds all the data of the PDF file. Compared to the
- * `PDFDoc`, this one doesn't have any job management code.
- * Right now there exists one PDFDocument on the main thread + one object
- * for each worker. If there is no worker support enabled, there are two
- * `PDFDocument` objects on the main thread created.
- */
- var PDFDocument = function PDFDocumentClosure() {
- var FINGERPRINT_FIRST_BYTES = 1024;
- var EMPTY_FINGERPRINT = '\x00\x00\x00\x00\x00\x00\x00' + '\x00\x00\x00\x00\x00\x00\x00\x00\x00';
- function PDFDocument(pdfManager, arg, password) {
- if (isStream(arg)) {
- init.call(this, pdfManager, arg, password);
- } else if (isArrayBuffer(arg)) {
- init.call(this, pdfManager, new Stream(arg), password);
- } else {
- error('PDFDocument: Unknown argument type');
- }
- }
- function init(pdfManager, stream, password) {
- assert(stream.length > 0, 'stream must have data');
- this.pdfManager = pdfManager;
- this.stream = stream;
- var xref = new XRef(this.stream, password, pdfManager);
- this.xref = xref;
- }
- function find(stream, needle, limit, backwards) {
- var pos = stream.pos;
- var end = stream.end;
- var strBuf = [];
- if (pos + limit > end) {
- limit = end - pos;
- }
- for (var n = 0; n < limit; ++n) {
- strBuf.push(String.fromCharCode(stream.getByte()));
- }
- var str = strBuf.join('');
- stream.pos = pos;
- var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle);
- if (index === -1) {
- return false;
- }
- /* not found */
- stream.pos += index;
- return true;
- }
- /* found */
- var DocumentInfoValidators = {
- get entries() {
- // Lazily build this since all the validation functions below are not
- // defined until after this file loads.
- return shadow(this, 'entries', {
- Title: isString,
- Author: isString,
- Subject: isString,
- Keywords: isString,
- Creator: isString,
- Producer: isString,
- CreationDate: isString,
- ModDate: isString,
- Trapped: isName
- });
- }
- };
- PDFDocument.prototype = {
- parse: function PDFDocument_parse(recoveryMode) {
- this.setup(recoveryMode);
- var version = this.catalog.catDict.get('Version');
- if (isName(version)) {
- this.pdfFormatVersion = version.name;
- }
- try {
- // checking if AcroForm is present
- this.acroForm = this.catalog.catDict.get('AcroForm');
- if (this.acroForm) {
- this.xfa = this.acroForm.get('XFA');
- var fields = this.acroForm.get('Fields');
- if ((!fields || !isArray(fields) || fields.length === 0) && !this.xfa) {
- // no fields and no XFA -- not a form (?)
- this.acroForm = null;
- }
- }
- } catch (ex) {
- info('Something wrong with AcroForm entry');
- this.acroForm = null;
- }
- },
- get linearization() {
- var linearization = null;
- if (this.stream.length) {
- try {
- linearization = Linearization.create(this.stream);
- } catch (err) {
- if (err instanceof MissingDataException) {
- throw err;
- }
- info(err);
- }
- }
- // shadow the prototype getter with a data property
- return shadow(this, 'linearization', linearization);
- },
- get startXRef() {
- var stream = this.stream;
- var startXRef = 0;
- var linearization = this.linearization;
- if (linearization) {
- // Find end of first obj.
- stream.reset();
- if (find(stream, 'endobj', 1024)) {
- startXRef = stream.pos + 6;
- }
- } else {
- // Find startxref by jumping backward from the end of the file.
- var step = 1024;
- var found = false, pos = stream.end;
- while (!found && pos > 0) {
- pos -= step - 'startxref'.length;
- if (pos < 0) {
- pos = 0;
- }
- stream.pos = pos;
- found = find(stream, 'startxref', step, true);
- }
- if (found) {
- stream.skip(9);
- var ch;
- do {
- ch = stream.getByte();
- } while (isSpace(ch));
- var str = '';
- while (ch >= 0x20 && ch <= 0x39) {
- // < '9'
- str += String.fromCharCode(ch);
- ch = stream.getByte();
- }
- startXRef = parseInt(str, 10);
- if (isNaN(startXRef)) {
- startXRef = 0;
- }
- }
- }
- // shadow the prototype getter with a data property
- return shadow(this, 'startXRef', startXRef);
- },
- get mainXRefEntriesOffset() {
- var mainXRefEntriesOffset = 0;
- var linearization = this.linearization;
- if (linearization) {
- mainXRefEntriesOffset = linearization.mainXRefEntriesOffset;
- }
- // shadow the prototype getter with a data property
- return shadow(this, 'mainXRefEntriesOffset', mainXRefEntriesOffset);
- },
- // Find the header, remove leading garbage and setup the stream
- // starting from the header.
- checkHeader: function PDFDocument_checkHeader() {
- var stream = this.stream;
- stream.reset();
- if (find(stream, '%PDF-', 1024)) {
- // Found the header, trim off any garbage before it.
- stream.moveStart();
- // Reading file format version
- var MAX_VERSION_LENGTH = 12;
- var version = '', ch;
- while ((ch = stream.getByte()) > 0x20) {
- // SPACE
- if (version.length >= MAX_VERSION_LENGTH) {
- break;
- }
- version += String.fromCharCode(ch);
- }
- if (!this.pdfFormatVersion) {
- // removing "%PDF-"-prefix
- this.pdfFormatVersion = version.substring(5);
- }
- return;
- }
- },
- // May not be a PDF file, continue anyway.
- parseStartXRef: function PDFDocument_parseStartXRef() {
- var startXRef = this.startXRef;
- this.xref.setStartXRef(startXRef);
- },
- setup: function PDFDocument_setup(recoveryMode) {
- this.xref.parse(recoveryMode);
- var self = this;
- var pageFactory = {
- createPage: function (pageIndex, dict, ref, fontCache) {
- return new Page(self.pdfManager, self.xref, pageIndex, dict, ref, fontCache);
- }
- };
- this.catalog = new Catalog(this.pdfManager, this.xref, pageFactory);
- },
- get numPages() {
- var linearization = this.linearization;
- var num = linearization ? linearization.numPages : this.catalog.numPages;
- // shadow the prototype getter
- return shadow(this, 'numPages', num);
- },
- get documentInfo() {
- var docInfo = {
- PDFFormatVersion: this.pdfFormatVersion,
- IsAcroFormPresent: !!this.acroForm,
- IsXFAPresent: !!this.xfa
- };
- var infoDict;
- try {
- infoDict = this.xref.trailer.get('Info');
- } catch (err) {
- info('The document information dictionary is invalid.');
- }
- if (infoDict) {
- var validEntries = DocumentInfoValidators.entries;
- // Only fill the document info with valid entries from the spec.
- for (var key in validEntries) {
- if (infoDict.has(key)) {
- var value = infoDict.get(key);
- // Make sure the value conforms to the spec.
- if (validEntries[key](value)) {
- docInfo[key] = typeof value !== 'string' ? value : stringToPDFString(value);
- } else {
- info('Bad value in document info for "' + key + '"');
- }
- }
- }
- }
- return shadow(this, 'documentInfo', docInfo);
- },
- get fingerprint() {
- var xref = this.xref, hash, fileID = '';
- var idArray = xref.trailer.get('ID');
- if (idArray && isArray(idArray) && idArray[0] && isString(idArray[0]) && idArray[0] !== EMPTY_FINGERPRINT) {
- hash = stringToBytes(idArray[0]);
- } else {
- if (this.stream.ensureRange) {
- this.stream.ensureRange(0, Math.min(FINGERPRINT_FIRST_BYTES, this.stream.end));
- }
- hash = calculateMD5(this.stream.bytes.subarray(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES);
- }
- for (var i = 0, n = hash.length; i < n; i++) {
- var hex = hash[i].toString(16);
- fileID += hex.length === 1 ? '0' + hex : hex;
- }
- return shadow(this, 'fingerprint', fileID);
- },
- getPage: function PDFDocument_getPage(pageIndex) {
- return this.catalog.getPage(pageIndex);
- },
- cleanup: function PDFDocument_cleanup() {
- return this.catalog.cleanup();
- }
- };
- return PDFDocument;
- }();
- exports.Page = Page;
- exports.PDFDocument = PDFDocument;
- }));
- (function (root, factory) {
- factory(root.pdfjsCorePdfManager = {}, root.pdfjsSharedUtil, root.pdfjsCoreStream, root.pdfjsCoreChunkedStream, root.pdfjsCoreDocument);
- }(this, function (exports, sharedUtil, coreStream, coreChunkedStream, coreDocument) {
- var warn = sharedUtil.warn;
- var createValidAbsoluteUrl = sharedUtil.createValidAbsoluteUrl;
- var shadow = sharedUtil.shadow;
- var NotImplementedException = sharedUtil.NotImplementedException;
- var MissingDataException = sharedUtil.MissingDataException;
- var createPromiseCapability = sharedUtil.createPromiseCapability;
- var Util = sharedUtil.Util;
- var Stream = coreStream.Stream;
- var ChunkedStreamManager = coreChunkedStream.ChunkedStreamManager;
- var PDFDocument = coreDocument.PDFDocument;
- var BasePdfManager = function BasePdfManagerClosure() {
- function BasePdfManager() {
- throw new Error('Cannot initialize BaseManagerManager');
- }
- BasePdfManager.prototype = {
- get docId() {
- return this._docId;
- },
- get docBaseUrl() {
- var docBaseUrl = null;
- if (this._docBaseUrl) {
- var absoluteUrl = createValidAbsoluteUrl(this._docBaseUrl);
- if (absoluteUrl) {
- docBaseUrl = absoluteUrl.href;
- } else {
- warn('Invalid absolute docBaseUrl: "' + this._docBaseUrl + '".');
- }
- }
- return shadow(this, 'docBaseUrl', docBaseUrl);
- },
- onLoadedStream: function BasePdfManager_onLoadedStream() {
- throw new NotImplementedException();
- },
- ensureDoc: function BasePdfManager_ensureDoc(prop, args) {
- return this.ensure(this.pdfDocument, prop, args);
- },
- ensureXRef: function BasePdfManager_ensureXRef(prop, args) {
- return this.ensure(this.pdfDocument.xref, prop, args);
- },
- ensureCatalog: function BasePdfManager_ensureCatalog(prop, args) {
- return this.ensure(this.pdfDocument.catalog, prop, args);
- },
- getPage: function BasePdfManager_getPage(pageIndex) {
- return this.pdfDocument.getPage(pageIndex);
- },
- cleanup: function BasePdfManager_cleanup() {
- return this.pdfDocument.cleanup();
- },
- ensure: function BasePdfManager_ensure(obj, prop, args) {
- return new NotImplementedException();
- },
- requestRange: function BasePdfManager_requestRange(begin, end) {
- return new NotImplementedException();
- },
- requestLoadedStream: function BasePdfManager_requestLoadedStream() {
- return new NotImplementedException();
- },
- sendProgressiveData: function BasePdfManager_sendProgressiveData(chunk) {
- return new NotImplementedException();
- },
- updatePassword: function BasePdfManager_updatePassword(password) {
- this.pdfDocument.xref.password = this.password = password;
- if (this._passwordChangedCapability) {
- this._passwordChangedCapability.resolve();
- }
- },
- passwordChanged: function BasePdfManager_passwordChanged() {
- this._passwordChangedCapability = createPromiseCapability();
- return this._passwordChangedCapability.promise;
- },
- terminate: function BasePdfManager_terminate() {
- return new NotImplementedException();
- }
- };
- return BasePdfManager;
- }();
- var LocalPdfManager = function LocalPdfManagerClosure() {
- function LocalPdfManager(docId, data, password, evaluatorOptions, docBaseUrl) {
- this._docId = docId;
- this._docBaseUrl = docBaseUrl;
- this.evaluatorOptions = evaluatorOptions;
- var stream = new Stream(data);
- this.pdfDocument = new PDFDocument(this, stream, password);
- this._loadedStreamCapability = createPromiseCapability();
- this._loadedStreamCapability.resolve(stream);
- }
- Util.inherit(LocalPdfManager, BasePdfManager, {
- ensure: function LocalPdfManager_ensure(obj, prop, args) {
- return new Promise(function (resolve, reject) {
- try {
- var value = obj[prop];
- var result;
- if (typeof value === 'function') {
- result = value.apply(obj, args);
- } else {
- result = value;
- }
- resolve(result);
- } catch (e) {
- reject(e);
- }
- });
- },
- requestRange: function LocalPdfManager_requestRange(begin, end) {
- return Promise.resolve();
- },
- requestLoadedStream: function LocalPdfManager_requestLoadedStream() {
- return;
- },
- onLoadedStream: function LocalPdfManager_onLoadedStream() {
- return this._loadedStreamCapability.promise;
- },
- terminate: function LocalPdfManager_terminate() {
- return;
- }
- });
- return LocalPdfManager;
- }();
- var NetworkPdfManager = function NetworkPdfManagerClosure() {
- function NetworkPdfManager(docId, pdfNetworkStream, args, evaluatorOptions, docBaseUrl) {
- this._docId = docId;
- this._docBaseUrl = docBaseUrl;
- this.msgHandler = args.msgHandler;
- this.evaluatorOptions = evaluatorOptions;
- var params = {
- msgHandler: args.msgHandler,
- url: args.url,
- length: args.length,
- disableAutoFetch: args.disableAutoFetch,
- rangeChunkSize: args.rangeChunkSize
- };
- this.streamManager = new ChunkedStreamManager(pdfNetworkStream, params);
- this.pdfDocument = new PDFDocument(this, this.streamManager.getStream(), args.password);
- }
- Util.inherit(NetworkPdfManager, BasePdfManager, {
- ensure: function NetworkPdfManager_ensure(obj, prop, args) {
- var pdfManager = this;
- return new Promise(function (resolve, reject) {
- function ensureHelper() {
- try {
- var result;
- var value = obj[prop];
- if (typeof value === 'function') {
- result = value.apply(obj, args);
- } else {
- result = value;
- }
- resolve(result);
- } catch (e) {
- if (!(e instanceof MissingDataException)) {
- reject(e);
- return;
- }
- pdfManager.streamManager.requestRange(e.begin, e.end).then(ensureHelper, reject);
- }
- }
- ensureHelper();
- });
- },
- requestRange: function NetworkPdfManager_requestRange(begin, end) {
- return this.streamManager.requestRange(begin, end);
- },
- requestLoadedStream: function NetworkPdfManager_requestLoadedStream() {
- this.streamManager.requestAllChunks();
- },
- sendProgressiveData: function NetworkPdfManager_sendProgressiveData(chunk) {
- this.streamManager.onReceiveData({ chunk: chunk });
- },
- onLoadedStream: function NetworkPdfManager_onLoadedStream() {
- return this.streamManager.onLoadedStream();
- },
- terminate: function NetworkPdfManager_terminate() {
- this.streamManager.abort();
- }
- });
- return NetworkPdfManager;
- }();
- exports.LocalPdfManager = LocalPdfManager;
- exports.NetworkPdfManager = NetworkPdfManager;
- }));
- (function (root, factory) {
- factory(root.pdfjsCoreWorker = {}, root.pdfjsSharedUtil, root.pdfjsCorePrimitives, root.pdfjsCorePdfManager);
- }(this, function (exports, sharedUtil, corePrimitives, corePdfManager) {
- var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES;
- var InvalidPDFException = sharedUtil.InvalidPDFException;
- var MessageHandler = sharedUtil.MessageHandler;
- var MissingPDFException = sharedUtil.MissingPDFException;
- var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
- var PasswordException = sharedUtil.PasswordException;
- var PasswordResponses = sharedUtil.PasswordResponses;
- var UnknownErrorException = sharedUtil.UnknownErrorException;
- var XRefParseException = sharedUtil.XRefParseException;
- var arrayByteLength = sharedUtil.arrayByteLength;
- var arraysToBytes = sharedUtil.arraysToBytes;
- var assert = sharedUtil.assert;
- var createPromiseCapability = sharedUtil.createPromiseCapability;
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var warn = sharedUtil.warn;
- var setVerbosityLevel = sharedUtil.setVerbosityLevel;
- var Ref = corePrimitives.Ref;
- var LocalPdfManager = corePdfManager.LocalPdfManager;
- var NetworkPdfManager = corePdfManager.NetworkPdfManager;
- var globalScope = sharedUtil.globalScope;
- var WorkerTask = function WorkerTaskClosure() {
- function WorkerTask(name) {
- this.name = name;
- this.terminated = false;
- this._capability = createPromiseCapability();
- }
- WorkerTask.prototype = {
- get finished() {
- return this._capability.promise;
- },
- finish: function () {
- this._capability.resolve();
- },
- terminate: function () {
- this.terminated = true;
- },
- ensureNotTerminated: function () {
- if (this.terminated) {
- throw new Error('Worker task was terminated');
- }
- }
- };
- return WorkerTask;
- }();
- /** @implements {IPDFStream} */
- var PDFWorkerStream = function PDFWorkerStreamClosure() {
- function PDFWorkerStream(params, msgHandler) {
- this._queuedChunks = [];
- var initialData = params.initialData;
- if (initialData && initialData.length > 0) {
- this._queuedChunks.push(initialData);
- }
- this._msgHandler = msgHandler;
- this._isRangeSupported = !params.disableRange;
- this._isStreamingSupported = !params.disableStream;
- this._contentLength = params.length;
- this._fullRequestReader = null;
- this._rangeReaders = [];
- msgHandler.on('OnDataRange', this._onReceiveData.bind(this));
- msgHandler.on('OnDataProgress', this._onProgress.bind(this));
- }
- PDFWorkerStream.prototype = {
- _onReceiveData: function PDFWorkerStream_onReceiveData(args) {
- if (args.begin === undefined) {
- if (this._fullRequestReader) {
- this._fullRequestReader._enqueue(args.chunk);
- } else {
- this._queuedChunks.push(args.chunk);
- }
- } else {
- var found = this._rangeReaders.some(function (rangeReader) {
- if (rangeReader._begin !== args.begin) {
- return false;
- }
- rangeReader._enqueue(args.chunk);
- return true;
- });
- assert(found);
- }
- },
- _onProgress: function PDFWorkerStream_onProgress(evt) {
- if (this._rangeReaders.length > 0) {
- // Reporting to first range reader.
- var firstReader = this._rangeReaders[0];
- if (firstReader.onProgress) {
- firstReader.onProgress({ loaded: evt.loaded });
- }
- }
- },
- _removeRangeReader: function PDFWorkerStream_removeRangeReader(reader) {
- var i = this._rangeReaders.indexOf(reader);
- if (i >= 0) {
- this._rangeReaders.splice(i, 1);
- }
- },
- getFullReader: function PDFWorkerStream_getFullReader() {
- assert(!this._fullRequestReader);
- var queuedChunks = this._queuedChunks;
- this._queuedChunks = null;
- return new PDFWorkerStreamReader(this, queuedChunks);
- },
- getRangeReader: function PDFWorkerStream_getRangeReader(begin, end) {
- var reader = new PDFWorkerStreamRangeReader(this, begin, end);
- this._msgHandler.send('RequestDataRange', {
- begin: begin,
- end: end
- });
- this._rangeReaders.push(reader);
- return reader;
- },
- cancelAllRequests: function PDFWorkerStream_cancelAllRequests(reason) {
- if (this._fullRequestReader) {
- this._fullRequestReader.cancel(reason);
- }
- var readers = this._rangeReaders.slice(0);
- readers.forEach(function (rangeReader) {
- rangeReader.cancel(reason);
- });
- }
- };
- /** @implements {IPDFStreamReader} */
- function PDFWorkerStreamReader(stream, queuedChunks) {
- this._stream = stream;
- this._done = false;
- this._queuedChunks = queuedChunks || [];
- this._requests = [];
- this._headersReady = Promise.resolve();
- stream._fullRequestReader = this;
- this.onProgress = null;
- }
- // not used
- PDFWorkerStreamReader.prototype = {
- _enqueue: function PDFWorkerStreamReader_enqueue(chunk) {
- if (this._done) {
- return;
- }
- // ignore new data
- if (this._requests.length > 0) {
- var requestCapability = this._requests.shift();
- requestCapability.resolve({
- value: chunk,
- done: false
- });
- return;
- }
- this._queuedChunks.push(chunk);
- },
- get headersReady() {
- return this._headersReady;
- },
- get isRangeSupported() {
- return this._stream._isRangeSupported;
- },
- get isStreamingSupported() {
- return this._stream._isStreamingSupported;
- },
- get contentLength() {
- return this._stream._contentLength;
- },
- read: function PDFWorkerStreamReader_read() {
- if (this._queuedChunks.length > 0) {
- var chunk = this._queuedChunks.shift();
- return Promise.resolve({
- value: chunk,
- done: false
- });
- }
- if (this._done) {
- return Promise.resolve({
- value: undefined,
- done: true
- });
- }
- var requestCapability = createPromiseCapability();
- this._requests.push(requestCapability);
- return requestCapability.promise;
- },
- cancel: function PDFWorkerStreamReader_cancel(reason) {
- this._done = true;
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({
- value: undefined,
- done: true
- });
- });
- this._requests = [];
- }
- };
- /** @implements {IPDFStreamRangeReader} */
- function PDFWorkerStreamRangeReader(stream, begin, end) {
- this._stream = stream;
- this._begin = begin;
- this._end = end;
- this._queuedChunk = null;
- this._requests = [];
- this._done = false;
- this.onProgress = null;
- }
- PDFWorkerStreamRangeReader.prototype = {
- _enqueue: function PDFWorkerStreamRangeReader_enqueue(chunk) {
- if (this._done) {
- return;
- }
- // ignore new data
- if (this._requests.length === 0) {
- this._queuedChunk = chunk;
- } else {
- var requestsCapability = this._requests.shift();
- requestsCapability.resolve({
- value: chunk,
- done: false
- });
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({
- value: undefined,
- done: true
- });
- });
- this._requests = [];
- }
- this._done = true;
- this._stream._removeRangeReader(this);
- },
- get isStreamingSupported() {
- return false;
- },
- read: function PDFWorkerStreamRangeReader_read() {
- if (this._queuedChunk) {
- return Promise.resolve({
- value: this._queuedChunk,
- done: false
- });
- }
- if (this._done) {
- return Promise.resolve({
- value: undefined,
- done: true
- });
- }
- var requestCapability = createPromiseCapability();
- this._requests.push(requestCapability);
- return requestCapability.promise;
- },
- cancel: function PDFWorkerStreamRangeReader_cancel(reason) {
- this._done = true;
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({
- value: undefined,
- done: true
- });
- });
- this._requests = [];
- this._stream._removeRangeReader(this);
- }
- };
- return PDFWorkerStream;
- }();
- /** @type IPDFStream */
- var PDFNetworkStream;
- /**
- * Sets PDFNetworkStream class to be used as alternative PDF data transport.
- * @param {IPDFStream} cls - the PDF data transport.
- */
- function setPDFNetworkStreamClass(cls) {
- PDFNetworkStream = cls;
- }
- var WorkerMessageHandler = {
- setup: function wphSetup(handler, port) {
- var testMessageProcessed = false;
- handler.on('test', function wphSetupTest(data) {
- if (testMessageProcessed) {
- return;
- }
- // we already processed 'test' message once
- testMessageProcessed = true;
- // check if Uint8Array can be sent to worker
- if (!(data instanceof Uint8Array)) {
- handler.send('test', 'main', false);
- return;
- }
- // making sure postMessage transfers are working
- var supportTransfers = data[0] === 255;
- handler.postMessageTransfers = supportTransfers;
- // check if the response property is supported by xhr
- var xhr = new XMLHttpRequest();
- var responseExists = 'response' in xhr;
- // check if the property is actually implemented
- try {
- var dummy = xhr.responseType;
- } catch (e) {
- responseExists = false;
- }
- if (!responseExists) {
- handler.send('test', false);
- return;
- }
- handler.send('test', {
- supportTypedArray: true,
- supportTransfers: supportTransfers
- });
- });
- handler.on('configure', function wphConfigure(data) {
- setVerbosityLevel(data.verbosity);
- });
- handler.on('GetDocRequest', function wphSetupDoc(data) {
- return WorkerMessageHandler.createDocumentHandler(data, port);
- });
- },
- createDocumentHandler: function wphCreateDocumentHandler(docParams, port) {
- // This context is actually holds references on pdfManager and handler,
- // until the latter is destroyed.
- var pdfManager;
- var terminated = false;
- var cancelXHRs = null;
- var WorkerTasks = [];
- var docId = docParams.docId;
- var docBaseUrl = docParams.docBaseUrl;
- var workerHandlerName = docParams.docId + '_worker';
- var handler = new MessageHandler(workerHandlerName, docId, port);
- // Ensure that postMessage transfers are correctly enabled/disabled,
- // to prevent "DataCloneError" in older versions of IE (see issue 6957).
- handler.postMessageTransfers = docParams.postMessageTransfers;
- function ensureNotTerminated() {
- if (terminated) {
- throw new Error('Worker was terminated');
- }
- }
- function startWorkerTask(task) {
- WorkerTasks.push(task);
- }
- function finishWorkerTask(task) {
- task.finish();
- var i = WorkerTasks.indexOf(task);
- WorkerTasks.splice(i, 1);
- }
- function loadDocument(recoveryMode) {
- var loadDocumentCapability = createPromiseCapability();
- var parseSuccess = function parseSuccess() {
- var numPagesPromise = pdfManager.ensureDoc('numPages');
- var fingerprintPromise = pdfManager.ensureDoc('fingerprint');
- var encryptedPromise = pdfManager.ensureXRef('encrypt');
- Promise.all([
- numPagesPromise,
- fingerprintPromise,
- encryptedPromise
- ]).then(function onDocReady(results) {
- var doc = {
- numPages: results[0],
- fingerprint: results[1],
- encrypted: !!results[2]
- };
- loadDocumentCapability.resolve(doc);
- }, parseFailure);
- };
- var parseFailure = function parseFailure(e) {
- loadDocumentCapability.reject(e);
- };
- pdfManager.ensureDoc('checkHeader', []).then(function () {
- pdfManager.ensureDoc('parseStartXRef', []).then(function () {
- pdfManager.ensureDoc('parse', [recoveryMode]).then(parseSuccess, parseFailure);
- }, parseFailure);
- }, parseFailure);
- return loadDocumentCapability.promise;
- }
- function getPdfManager(data, evaluatorOptions) {
- var pdfManagerCapability = createPromiseCapability();
- var pdfManager;
- var source = data.source;
- if (source.data) {
- try {
- pdfManager = new LocalPdfManager(docId, source.data, source.password, evaluatorOptions, docBaseUrl);
- pdfManagerCapability.resolve(pdfManager);
- } catch (ex) {
- pdfManagerCapability.reject(ex);
- }
- return pdfManagerCapability.promise;
- }
- var pdfStream;
- try {
- if (source.chunkedViewerLoading) {
- pdfStream = new PDFWorkerStream(source, handler);
- } else {
- assert(PDFNetworkStream, 'pdfjs/core/network module is not loaded');
- pdfStream = new PDFNetworkStream(data);
- }
- } catch (ex) {
- pdfManagerCapability.reject(ex);
- return pdfManagerCapability.promise;
- }
- var fullRequest = pdfStream.getFullReader();
- fullRequest.headersReady.then(function () {
- if (!fullRequest.isStreamingSupported || !fullRequest.isRangeSupported) {
- // If stream or range are disabled, it's our only way to report
- // loading progress.
- fullRequest.onProgress = function (evt) {
- handler.send('DocProgress', {
- loaded: evt.loaded,
- total: evt.total
- });
- };
- }
- if (!fullRequest.isRangeSupported) {
- return;
- }
- // We don't need auto-fetch when streaming is enabled.
- var disableAutoFetch = source.disableAutoFetch || fullRequest.isStreamingSupported;
- pdfManager = new NetworkPdfManager(docId, pdfStream, {
- msgHandler: handler,
- url: source.url,
- password: source.password,
- length: fullRequest.contentLength,
- disableAutoFetch: disableAutoFetch,
- rangeChunkSize: source.rangeChunkSize
- }, evaluatorOptions, docBaseUrl);
- pdfManagerCapability.resolve(pdfManager);
- cancelXHRs = null;
- }).catch(function (reason) {
- pdfManagerCapability.reject(reason);
- cancelXHRs = null;
- });
- var cachedChunks = [], loaded = 0;
- var flushChunks = function () {
- var pdfFile = arraysToBytes(cachedChunks);
- if (source.length && pdfFile.length !== source.length) {
- warn('reported HTTP length is different from actual');
- }
- // the data is array, instantiating directly from it
- try {
- pdfManager = new LocalPdfManager(docId, pdfFile, source.password, evaluatorOptions, docBaseUrl);
- pdfManagerCapability.resolve(pdfManager);
- } catch (ex) {
- pdfManagerCapability.reject(ex);
- }
- cachedChunks = [];
- };
- var readPromise = new Promise(function (resolve, reject) {
- var readChunk = function (chunk) {
- try {
- ensureNotTerminated();
- if (chunk.done) {
- if (!pdfManager) {
- flushChunks();
- }
- cancelXHRs = null;
- return;
- }
- var data = chunk.value;
- loaded += arrayByteLength(data);
- if (!fullRequest.isStreamingSupported) {
- handler.send('DocProgress', {
- loaded: loaded,
- total: Math.max(loaded, fullRequest.contentLength || 0)
- });
- }
- if (pdfManager) {
- pdfManager.sendProgressiveData(data);
- } else {
- cachedChunks.push(data);
- }
- fullRequest.read().then(readChunk, reject);
- } catch (e) {
- reject(e);
- }
- };
- fullRequest.read().then(readChunk, reject);
- });
- readPromise.catch(function (e) {
- pdfManagerCapability.reject(e);
- cancelXHRs = null;
- });
- cancelXHRs = function () {
- pdfStream.cancelAllRequests('abort');
- };
- return pdfManagerCapability.promise;
- }
- var setupDoc = function (data) {
- var onSuccess = function (doc) {
- ensureNotTerminated();
- handler.send('GetDoc', { pdfInfo: doc });
- };
- var onFailure = function (e) {
- if (e instanceof PasswordException) {
- if (e.code === PasswordResponses.NEED_PASSWORD) {
- handler.send('NeedPassword', e);
- } else if (e.code === PasswordResponses.INCORRECT_PASSWORD) {
- handler.send('IncorrectPassword', e);
- }
- } else if (e instanceof InvalidPDFException) {
- handler.send('InvalidPDF', e);
- } else if (e instanceof MissingPDFException) {
- handler.send('MissingPDF', e);
- } else if (e instanceof UnexpectedResponseException) {
- handler.send('UnexpectedResponse', e);
- } else {
- handler.send('UnknownError', new UnknownErrorException(e.message, e.toString()));
- }
- };
- ensureNotTerminated();
- var cMapOptions = {
- url: data.cMapUrl === undefined ? null : data.cMapUrl,
- packed: data.cMapPacked === true
- };
- var evaluatorOptions = {
- forceDataSchema: data.disableCreateObjectURL,
- maxImageSize: data.maxImageSize === undefined ? -1 : data.maxImageSize,
- disableFontFace: data.disableFontFace,
- cMapOptions: cMapOptions
- };
- getPdfManager(data, evaluatorOptions).then(function (newPdfManager) {
- if (terminated) {
- // We were in a process of setting up the manager, but it got
- // terminated in the middle.
- newPdfManager.terminate();
- throw new Error('Worker was terminated');
- }
- pdfManager = newPdfManager;
- handler.send('PDFManagerReady', null);
- pdfManager.onLoadedStream().then(function (stream) {
- handler.send('DataLoaded', { length: stream.bytes.byteLength });
- });
- }).then(function pdfManagerReady() {
- ensureNotTerminated();
- loadDocument(false).then(onSuccess, function loadFailure(ex) {
- ensureNotTerminated();
- // Try again with recoveryMode == true
- if (!(ex instanceof XRefParseException)) {
- if (ex instanceof PasswordException) {
- // after password exception prepare to receive a new password
- // to repeat loading
- pdfManager.passwordChanged().then(pdfManagerReady);
- }
- onFailure(ex);
- return;
- }
- pdfManager.requestLoadedStream();
- pdfManager.onLoadedStream().then(function () {
- ensureNotTerminated();
- loadDocument(true).then(onSuccess, onFailure);
- });
- }, onFailure);
- }, onFailure);
- };
- handler.on('GetPage', function wphSetupGetPage(data) {
- return pdfManager.getPage(data.pageIndex).then(function (page) {
- var rotatePromise = pdfManager.ensure(page, 'rotate');
- var refPromise = pdfManager.ensure(page, 'ref');
- var viewPromise = pdfManager.ensure(page, 'view');
- return Promise.all([
- rotatePromise,
- refPromise,
- viewPromise
- ]).then(function (results) {
- return {
- rotate: results[0],
- ref: results[1],
- view: results[2]
- };
- });
- });
- });
- handler.on('GetPageIndex', function wphSetupGetPageIndex(data) {
- var ref = new Ref(data.ref.num, data.ref.gen);
- var catalog = pdfManager.pdfDocument.catalog;
- return catalog.getPageIndex(ref);
- });
- handler.on('GetDestinations', function wphSetupGetDestinations(data) {
- return pdfManager.ensureCatalog('destinations');
- });
- handler.on('GetDestination', function wphSetupGetDestination(data) {
- return pdfManager.ensureCatalog('getDestination', [data.id]);
- });
- handler.on('GetPageLabels', function wphSetupGetPageLabels(data) {
- return pdfManager.ensureCatalog('pageLabels');
- });
- handler.on('GetAttachments', function wphSetupGetAttachments(data) {
- return pdfManager.ensureCatalog('attachments');
- });
- handler.on('GetJavaScript', function wphSetupGetJavaScript(data) {
- return pdfManager.ensureCatalog('javaScript');
- });
- handler.on('GetOutline', function wphSetupGetOutline(data) {
- return pdfManager.ensureCatalog('documentOutline');
- });
- handler.on('GetMetadata', function wphSetupGetMetadata(data) {
- return Promise.all([
- pdfManager.ensureDoc('documentInfo'),
- pdfManager.ensureCatalog('metadata')
- ]);
- });
- handler.on('GetData', function wphSetupGetData(data) {
- pdfManager.requestLoadedStream();
- return pdfManager.onLoadedStream().then(function (stream) {
- return stream.bytes;
- });
- });
- handler.on('GetStats', function wphSetupGetStats(data) {
- return pdfManager.pdfDocument.xref.stats;
- });
- handler.on('UpdatePassword', function wphSetupUpdatePassword(data) {
- pdfManager.updatePassword(data);
- });
- handler.on('GetAnnotations', function wphSetupGetAnnotations(data) {
- return pdfManager.getPage(data.pageIndex).then(function (page) {
- return pdfManager.ensure(page, 'getAnnotationsData', [data.intent]);
- });
- });
- handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
- var pageIndex = data.pageIndex;
- pdfManager.getPage(pageIndex).then(function (page) {
- var task = new WorkerTask('RenderPageRequest: page ' + pageIndex);
- startWorkerTask(task);
- var pageNum = pageIndex + 1;
- var start = Date.now();
- // Pre compile the pdf page and fetch the fonts/images.
- page.getOperatorList(handler, task, data.intent, data.renderInteractiveForms).then(function (operatorList) {
- finishWorkerTask(task);
- info('page=' + pageNum + ' - getOperatorList: time=' + (Date.now() - start) + 'ms, len=' + operatorList.totalLength);
- }, function (e) {
- finishWorkerTask(task);
- if (task.terminated) {
- return;
- }
- // ignoring errors from the terminated thread
- // For compatibility with older behavior, generating unknown
- // unsupported feature notification on errors.
- handler.send('UnsupportedFeature', { featureId: UNSUPPORTED_FEATURES.unknown });
- var minimumStackMessage = 'worker.js: while trying to getPage() and getOperatorList()';
- var wrappedException;
- // Turn the error into an obj that can be serialized
- if (typeof e === 'string') {
- wrappedException = {
- message: e,
- stack: minimumStackMessage
- };
- } else if (typeof e === 'object') {
- wrappedException = {
- message: e.message || e.toString(),
- stack: e.stack || minimumStackMessage
- };
- } else {
- wrappedException = {
- message: 'Unknown exception type: ' + typeof e,
- stack: minimumStackMessage
- };
- }
- handler.send('PageError', {
- pageNum: pageNum,
- error: wrappedException,
- intent: data.intent
- });
- });
- });
- }, this);
- handler.on('GetTextContent', function wphExtractText(data) {
- var pageIndex = data.pageIndex;
- var normalizeWhitespace = data.normalizeWhitespace;
- var combineTextItems = data.combineTextItems;
- return pdfManager.getPage(pageIndex).then(function (page) {
- var task = new WorkerTask('GetTextContent: page ' + pageIndex);
- startWorkerTask(task);
- var pageNum = pageIndex + 1;
- var start = Date.now();
- return page.extractTextContent(task, normalizeWhitespace, combineTextItems).then(function (textContent) {
- finishWorkerTask(task);
- info('text indexing: page=' + pageNum + ' - time=' + (Date.now() - start) + 'ms');
- return textContent;
- }, function (reason) {
- finishWorkerTask(task);
- if (task.terminated) {
- return;
- }
- // ignoring errors from the terminated thread
- throw reason;
- });
- });
- });
- handler.on('Cleanup', function wphCleanup(data) {
- return pdfManager.cleanup();
- });
- handler.on('Terminate', function wphTerminate(data) {
- terminated = true;
- if (pdfManager) {
- pdfManager.terminate();
- pdfManager = null;
- }
- if (cancelXHRs) {
- cancelXHRs();
- }
- var waitOn = [];
- WorkerTasks.forEach(function (task) {
- waitOn.push(task.finished);
- task.terminate();
- });
- return Promise.all(waitOn).then(function () {
- // Notice that even if we destroying handler, resolved response promise
- // must be sent back.
- handler.destroy();
- handler = null;
- });
- });
- handler.on('Ready', function wphReady(data) {
- setupDoc(docParams);
- docParams = null;
- });
- // we don't need docParams anymore -- saving memory.
- return workerHandlerName;
- }
- };
- function initializeWorker() {
- var handler = new MessageHandler('worker', 'main', self);
- WorkerMessageHandler.setup(handler, self);
- handler.send('ready', null);
- }
- // Worker thread (and not node.js)?
- if (typeof window === 'undefined' && !(typeof module !== 'undefined' && module.require)) {
- initializeWorker();
- }
- exports.setPDFNetworkStreamClass = setPDFNetworkStreamClass;
- exports.WorkerTask = WorkerTask;
- exports.WorkerMessageHandler = WorkerMessageHandler;
- }));
- }.call(pdfjsLibs));
- exports.WorkerMessageHandler = pdfjsLibs.pdfjsCoreWorker.WorkerMessageHandler;
-}));
diff --git a/extensions/pdfjs/content/network.js b/extensions/pdfjs/content/network.js
deleted file mode 100644
index 68c8dd1..0000000
--- a/extensions/pdfjs/content/network.js
+++ /dev/null
@@ -1,614 +0,0 @@
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// NOTE: Be careful what goes in this file, as it is also used from the context
-// of the addon. So using warn/error in here will break the addon.
-
-'use strict';
-
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- define('pdfjs/core/network', ['exports', 'pdfjs/shared/util',
- 'pdfjs/core/worker'], factory);
- } else if (typeof exports !== 'undefined') {
- factory(exports, require('../shared/util.js'), require('./worker.js'));
- } else {
- factory((root.pdfjsCoreNetwork = {}), root.pdfjsSharedUtil,
- root.pdfjsCoreWorker);
- }
-}(this, function (exports, sharedUtil, coreWorker) {
-if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
- throw new Error('Module "pdfjs/core/network" shall not ' +
- 'be used with FIREFOX or MOZCENTRAL build.');
-}
-
- var OK_RESPONSE = 200;
- var PARTIAL_CONTENT_RESPONSE = 206;
-
- function NetworkManager(url, args) {
- this.url = url;
- args = args || {};
- this.isHttp = /^https?:/i.test(url);
- this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
- this.withCredentials = args.withCredentials || false;
- this.getXhr = args.getXhr ||
- function NetworkManager_getXhr() {
- return new XMLHttpRequest();
- };
-
- this.currXhrId = 0;
- this.pendingRequests = Object.create(null);
- this.loadedRequests = Object.create(null);
- }
-
- function getArrayBuffer(xhr) {
- var data = xhr.response;
- if (typeof data !== 'string') {
- return data;
- }
- var length = data.length;
- var array = new Uint8Array(length);
- for (var i = 0; i < length; i++) {
- array[i] = data.charCodeAt(i) & 0xFF;
- }
- return array.buffer;
- }
-
- var supportsMozChunked =
- typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME') ? false :
- (function supportsMozChunkedClosure() {
- try {
- var x = new XMLHttpRequest();
- // Firefox 37- required .open() to be called before setting responseType.
- // https://bugzilla.mozilla.org/show_bug.cgi?id=707484
- // Even though the URL is not visited, .open() could fail if the URL is
- // blocked, e.g. via the connect-src CSP directive or the NoScript addon.
- // When this error occurs, this feature detection method will mistakenly
- // report that moz-chunked-arraybuffer is not supported in Firefox 37-.
- x.open('GET', 'https://example.com');
- x.responseType = 'moz-chunked-arraybuffer';
- return x.responseType === 'moz-chunked-arraybuffer';
- } catch (e) {
- return false;
- }
- })();
-
- NetworkManager.prototype = {
- requestRange: function NetworkManager_requestRange(begin, end, listeners) {
- var args = {
- begin: begin,
- end: end
- };
- for (var prop in listeners) {
- args[prop] = listeners[prop];
- }
- return this.request(args);
- },
-
- requestFull: function NetworkManager_requestFull(listeners) {
- return this.request(listeners);
- },
-
- request: function NetworkManager_request(args) {
- var xhr = this.getXhr();
- var xhrId = this.currXhrId++;
- var pendingRequest = this.pendingRequests[xhrId] = {
- xhr: xhr
- };
-
- xhr.open('GET', this.url);
- xhr.withCredentials = this.withCredentials;
- for (var property in this.httpHeaders) {
- var value = this.httpHeaders[property];
- if (typeof value === 'undefined') {
- continue;
- }
- xhr.setRequestHeader(property, value);
- }
- if (this.isHttp && 'begin' in args && 'end' in args) {
- var rangeStr = args.begin + '-' + (args.end - 1);
- xhr.setRequestHeader('Range', 'bytes=' + rangeStr);
- pendingRequest.expectedStatus = 206;
- } else {
- pendingRequest.expectedStatus = 200;
- }
-
- var useMozChunkedLoading = supportsMozChunked && !!args.onProgressiveData;
- if (useMozChunkedLoading) {
- xhr.responseType = 'moz-chunked-arraybuffer';
- pendingRequest.onProgressiveData = args.onProgressiveData;
- pendingRequest.mozChunked = true;
- } else {
- xhr.responseType = 'arraybuffer';
- }
-
- if (args.onError) {
- xhr.onerror = function(evt) {
- args.onError(xhr.status);
- };
- }
- xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
- xhr.onprogress = this.onProgress.bind(this, xhrId);
-
- pendingRequest.onHeadersReceived = args.onHeadersReceived;
- pendingRequest.onDone = args.onDone;
- pendingRequest.onError = args.onError;
- pendingRequest.onProgress = args.onProgress;
-
- xhr.send(null);
-
- return xhrId;
- },
-
- onProgress: function NetworkManager_onProgress(xhrId, evt) {
- var pendingRequest = this.pendingRequests[xhrId];
- if (!pendingRequest) {
- // Maybe abortRequest was called...
- return;
- }
-
- if (pendingRequest.mozChunked) {
- var chunk = getArrayBuffer(pendingRequest.xhr);
- pendingRequest.onProgressiveData(chunk);
- }
-
- var onProgress = pendingRequest.onProgress;
- if (onProgress) {
- onProgress(evt);
- }
- },
-
- onStateChange: function NetworkManager_onStateChange(xhrId, evt) {
- var pendingRequest = this.pendingRequests[xhrId];
- if (!pendingRequest) {
- // Maybe abortRequest was called...
- return;
- }
-
- var xhr = pendingRequest.xhr;
- if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
- pendingRequest.onHeadersReceived();
- delete pendingRequest.onHeadersReceived;
- }
-
- if (xhr.readyState !== 4) {
- return;
- }
-
- if (!(xhrId in this.pendingRequests)) {
- // The XHR request might have been aborted in onHeadersReceived()
- // callback, in which case we should abort request
- return;
- }
-
- delete this.pendingRequests[xhrId];
-
- // success status == 0 can be on ftp, file and other protocols
- if (xhr.status === 0 && this.isHttp) {
- if (pendingRequest.onError) {
- pendingRequest.onError(xhr.status);
- }
- return;
- }
- var xhrStatus = xhr.status || OK_RESPONSE;
-
- // From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2:
- // "A server MAY ignore the Range header". This means it's possible to
- // get a 200 rather than a 206 response from a range request.
- var ok_response_on_range_request =
- xhrStatus === OK_RESPONSE &&
- pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
-
- if (!ok_response_on_range_request &&
- xhrStatus !== pendingRequest.expectedStatus) {
- if (pendingRequest.onError) {
- pendingRequest.onError(xhr.status);
- }
- return;
- }
-
- this.loadedRequests[xhrId] = true;
-
- var chunk = getArrayBuffer(xhr);
- if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
- var rangeHeader = xhr.getResponseHeader('Content-Range');
- var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
- var begin = parseInt(matches[1], 10);
- pendingRequest.onDone({
- begin: begin,
- chunk: chunk
- });
- } else if (pendingRequest.onProgressiveData) {
- pendingRequest.onDone(null);
- } else if (chunk) {
- pendingRequest.onDone({
- begin: 0,
- chunk: chunk
- });
- } else if (pendingRequest.onError) {
- pendingRequest.onError(xhr.status);
- }
- },
-
- hasPendingRequests: function NetworkManager_hasPendingRequests() {
- for (var xhrId in this.pendingRequests) {
- return true;
- }
- return false;
- },
-
- getRequestXhr: function NetworkManager_getXhr(xhrId) {
- return this.pendingRequests[xhrId].xhr;
- },
-
- isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) {
- return !!(this.pendingRequests[xhrId].onProgressiveData);
- },
-
- isPendingRequest: function NetworkManager_isPendingRequest(xhrId) {
- return xhrId in this.pendingRequests;
- },
-
- isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) {
- return xhrId in this.loadedRequests;
- },
-
- abortAllRequests: function NetworkManager_abortAllRequests() {
- for (var xhrId in this.pendingRequests) {
- this.abortRequest(xhrId | 0);
- }
- },
-
- abortRequest: function NetworkManager_abortRequest(xhrId) {
- var xhr = this.pendingRequests[xhrId].xhr;
- delete this.pendingRequests[xhrId];
- xhr.abort();
- }
- };
-
- var assert = sharedUtil.assert;
- var createPromiseCapability = sharedUtil.createPromiseCapability;
- var isInt = sharedUtil.isInt;
- var MissingPDFException = sharedUtil.MissingPDFException;
- var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
-
- /** @implements {IPDFStream} */
- function PDFNetworkStream(options) {
- this._options = options;
- var source = options.source;
- this._manager = new NetworkManager(source.url, {
- httpHeaders: source.httpHeaders,
- withCredentials: source.withCredentials
- });
- this._rangeChunkSize = source.rangeChunkSize;
- this._fullRequestReader = null;
- this._rangeRequestReaders = [];
- }
-
- PDFNetworkStream.prototype = {
- _onRangeRequestReaderClosed:
- function PDFNetworkStream_onRangeRequestReaderClosed(reader) {
- var i = this._rangeRequestReaders.indexOf(reader);
- if (i >= 0) {
- this._rangeRequestReaders.splice(i, 1);
- }
- },
-
- getFullReader: function PDFNetworkStream_getFullReader() {
- assert(!this._fullRequestReader);
- this._fullRequestReader =
- new PDFNetworkStreamFullRequestReader(this._manager, this._options);
- return this._fullRequestReader;
- },
-
- getRangeReader: function PDFNetworkStream_getRangeReader(begin, end) {
- var reader = new PDFNetworkStreamRangeRequestReader(this._manager,
- begin, end);
- reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
- this._rangeRequestReaders.push(reader);
- return reader;
- },
-
- cancelAllRequests: function PDFNetworkStream_cancelAllRequests(reason) {
- if (this._fullRequestReader) {
- this._fullRequestReader.cancel(reason);
- }
- var readers = this._rangeRequestReaders.slice(0);
- readers.forEach(function (reader) {
- reader.cancel(reason);
- });
- }
- };
-
- /** @implements {IPDFStreamReader} */
- function PDFNetworkStreamFullRequestReader(manager, options) {
- this._manager = manager;
-
- var source = options.source;
- var args = {
- onHeadersReceived: this._onHeadersReceived.bind(this),
- onProgressiveData: source.disableStream ? null :
- this._onProgressiveData.bind(this),
- onDone: this._onDone.bind(this),
- onError: this._onError.bind(this),
- onProgress: this._onProgress.bind(this)
- };
- this._url = source.url;
- this._fullRequestId = manager.requestFull(args);
- this._headersReceivedCapability = createPromiseCapability();
- this._disableRange = options.disableRange || false;
- this._contentLength = source.length; // optional
- this._rangeChunkSize = source.rangeChunkSize;
- if (!this._rangeChunkSize && !this._disableRange) {
- this._disableRange = true;
- }
-
- this._isStreamingSupported = false;
- this._isRangeSupported = false;
-
- this._cachedChunks = [];
- this._requests = [];
- this._done = false;
- this._storedError = undefined;
-
- this.onProgress = null;
- }
-
- PDFNetworkStreamFullRequestReader.prototype = {
- _validateRangeRequestCapabilities: function
- PDFNetworkStreamFullRequestReader_validateRangeRequestCapabilities() {
-
- if (this._disableRange) {
- return false;
- }
-
- var networkManager = this._manager;
- var fullRequestXhrId = this._fullRequestId;
- var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId);
- if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') {
- return false;
- }
-
- var contentEncoding =
- fullRequestXhr.getResponseHeader('Content-Encoding') || 'identity';
- if (contentEncoding !== 'identity') {
- return false;
- }
-
- var length = fullRequestXhr.getResponseHeader('Content-Length');
- length = parseInt(length, 10);
- if (!isInt(length)) {
- return false;
- }
-
- this._contentLength = length; // setting right content length
-
- if (length <= 2 * this._rangeChunkSize) {
- // The file size is smaller than the size of two chunks, so it does
- // not make any sense to abort the request and retry with a range
- // request.
- return false;
- }
-
- return true;
- },
-
- _onHeadersReceived:
- function PDFNetworkStreamFullRequestReader_onHeadersReceived() {
-
- if (this._validateRangeRequestCapabilities()) {
- this._isRangeSupported = true;
- }
-
- var networkManager = this._manager;
- var fullRequestXhrId = this._fullRequestId;
- if (networkManager.isStreamingRequest(fullRequestXhrId)) {
- // We can continue fetching when progressive loading is enabled,
- // and we don't need the autoFetch feature.
- this._isStreamingSupported = true;
- } else if (this._isRangeSupported) {
- // NOTE: by cancelling the full request, and then issuing range
- // requests, there will be an issue for sites where you can only
- // request the pdf once. However, if this is the case, then the
- // server should not be returning that it can support range
- // requests.
- networkManager.abortRequest(fullRequestXhrId);
- }
-
- this._headersReceivedCapability.resolve();
- },
-
- _onProgressiveData:
- function PDFNetworkStreamFullRequestReader_onProgressiveData(chunk) {
- if (this._requests.length > 0) {
- var requestCapability = this._requests.shift();
- requestCapability.resolve({value: chunk, done: false});
- } else {
- this._cachedChunks.push(chunk);
- }
- },
-
- _onDone: function PDFNetworkStreamFullRequestReader_onDone(args) {
- if (args) {
- this._onProgressiveData(args.chunk);
- }
- this._done = true;
- if (this._cachedChunks.length > 0) {
- return;
- }
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({value: undefined, done: true});
- });
- this._requests = [];
- },
-
- _onError: function PDFNetworkStreamFullRequestReader_onError(status) {
- var url = this._url;
- var exception;
- if (status === 404 || status === 0 && /^file:/.test(url)) {
- exception = new MissingPDFException('Missing PDF "' + url + '".');
- } else {
- exception = new UnexpectedResponseException(
- 'Unexpected server response (' + status +
- ') while retrieving PDF "' + url + '".', status);
- }
- this._storedError = exception;
- this._headersReceivedCapability.reject(exception);
- this._requests.forEach(function (requestCapability) {
- requestCapability.reject(exception);
- });
- this._requests = [];
- this._cachedChunks = [];
- },
-
- _onProgress: function PDFNetworkStreamFullRequestReader_onProgress(data) {
- if (this.onProgress) {
- this.onProgress({
- loaded: data.loaded,
- total: data.lengthComputable ? data.total : this._contentLength
- });
- }
- },
-
- get isRangeSupported() {
- return this._isRangeSupported;
- },
-
- get isStreamingSupported() {
- return this._isStreamingSupported;
- },
-
- get contentLength() {
- return this._contentLength;
- },
-
- get headersReady() {
- return this._headersReceivedCapability.promise;
- },
-
- read: function PDFNetworkStreamFullRequestReader_read() {
- if (this._storedError) {
- return Promise.reject(this._storedError);
- }
- if (this._cachedChunks.length > 0) {
- var chunk = this._cachedChunks.shift();
- return Promise.resolve(chunk);
- }
- if (this._done) {
- return Promise.resolve({value: undefined, done: true});
- }
- var requestCapability = createPromiseCapability();
- this._requests.push(requestCapability);
- return requestCapability.promise;
- },
-
- cancel: function PDFNetworkStreamFullRequestReader_cancel(reason) {
- this._done = true;
- this._headersReceivedCapability.reject(reason);
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({value: undefined, done: true});
- });
- this._requests = [];
- if (this._manager.isPendingRequest(this._fullRequestId)) {
- this._manager.abortRequest(this._fullRequestId);
- }
- this._fullRequestReader = null;
- }
- };
-
- /** @implements {IPDFStreamRangeReader} */
- function PDFNetworkStreamRangeRequestReader(manager, begin, end) {
- this._manager = manager;
- var args = {
- onDone: this._onDone.bind(this),
- onProgress: this._onProgress.bind(this)
- };
- this._requestId = manager.requestRange(begin, end, args);
- this._requests = [];
- this._queuedChunk = null;
- this._done = false;
-
- this.onProgress = null;
- this.onClosed = null;
- }
-
- PDFNetworkStreamRangeRequestReader.prototype = {
- _close: function PDFNetworkStreamRangeRequestReader_close() {
- if (this.onClosed) {
- this.onClosed(this);
- }
- },
-
- _onDone: function PDFNetworkStreamRangeRequestReader_onDone(data) {
- var chunk = data.chunk;
- if (this._requests.length > 0) {
- var requestCapability = this._requests.shift();
- requestCapability.resolve({value: chunk, done: false});
- } else {
- this._queuedChunk = chunk;
- }
- this._done = true;
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({value: undefined, done: true});
- });
- this._requests = [];
- this._close();
- },
-
- _onProgress: function PDFNetworkStreamRangeRequestReader_onProgress(evt) {
- if (!this.isStreamingSupported && this.onProgress) {
- this.onProgress({
- loaded: evt.loaded
- });
- }
- },
-
- get isStreamingSupported() {
- return false; // TODO allow progressive range bytes loading
- },
-
- read: function PDFNetworkStreamRangeRequestReader_read() {
- if (this._queuedChunk !== null) {
- var chunk = this._queuedChunk;
- this._queuedChunk = null;
- return Promise.resolve({value: chunk, done: false});
- }
- if (this._done) {
- return Promise.resolve({value: undefined, done: true});
- }
- var requestCapability = createPromiseCapability();
- this._requests.push(requestCapability);
- return requestCapability.promise;
- },
-
- cancel: function PDFNetworkStreamRangeRequestReader_cancel(reason) {
- this._done = true;
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({value: undefined, done: true});
- });
- this._requests = [];
- if (this._manager.isPendingRequest(this._requestId)) {
- this._manager.abortRequest(this._requestId);
- }
- this._close();
- }
- };
-
- coreWorker.setPDFNetworkStreamClass(PDFNetworkStream);
-
- exports.PDFNetworkStream = PDFNetworkStream;
- exports.NetworkManager = NetworkManager;
-}));
-
diff --git a/extensions/pdfjs/content/pdfjschildbootstrap.js b/extensions/pdfjs/content/pdfjschildbootstrap.js
deleted file mode 100644
index 1f44b9c..0000000
--- a/extensions/pdfjs/content/pdfjschildbootstrap.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright 2014 Mozilla Foundation
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-/* jshint esnext:true */
-/* globals Components, PdfjsContentUtils, PdfJs, Services */
-
-'use strict';
-
-/*
- * pdfjschildbootstrap.js loads into the content process to take care of
- * initializing our built-in version of pdfjs when running remote.
- */
-
-Components.utils.import('resource://gre/modules/Services.jsm');
-Components.utils.import('resource://pdf.js/PdfJs.jsm');
-Components.utils.import('resource://pdf.js/PdfjsContentUtils.jsm');
-
-// init content utils shim pdfjs will use to access privileged apis.
-PdfjsContentUtils.init();
-
-if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) {
- // register various pdfjs factories that hook us into content loading.
- PdfJs.updateRegistration();
-}
-
diff --git a/extensions/pdfjs/content/web/cmaps/78-EUC-H.bcmap b/extensions/pdfjs/content/web/cmaps/78-EUC-H.bcmap
deleted file mode 100644
index 2655fc7..0000000
--- a/extensions/pdfjs/content/web/cmaps/78-EUC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/78-EUC-V.bcmap b/extensions/pdfjs/content/web/cmaps/78-EUC-V.bcmap
deleted file mode 100644
index f1ed853..0000000
--- a/extensions/pdfjs/content/web/cmaps/78-EUC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/78-H.bcmap b/extensions/pdfjs/content/web/cmaps/78-H.bcmap
deleted file mode 100644
index 39e89d3..0000000
--- a/extensions/pdfjs/content/web/cmaps/78-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/78-RKSJ-H.bcmap b/extensions/pdfjs/content/web/cmaps/78-RKSJ-H.bcmap
deleted file mode 100644
index e4167cb..0000000
--- a/extensions/pdfjs/content/web/cmaps/78-RKSJ-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/78-RKSJ-V.bcmap b/extensions/pdfjs/content/web/cmaps/78-RKSJ-V.bcmap
deleted file mode 100644
index 50b1646..0000000
--- a/extensions/pdfjs/content/web/cmaps/78-RKSJ-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/78-V.bcmap b/extensions/pdfjs/content/web/cmaps/78-V.bcmap
deleted file mode 100644
index d7af99b..0000000
--- a/extensions/pdfjs/content/web/cmaps/78-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/78ms-RKSJ-H.bcmap b/extensions/pdfjs/content/web/cmaps/78ms-RKSJ-H.bcmap
deleted file mode 100644
index 37077d0..0000000
--- a/extensions/pdfjs/content/web/cmaps/78ms-RKSJ-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/78ms-RKSJ-V.bcmap b/extensions/pdfjs/content/web/cmaps/78ms-RKSJ-V.bcmap
deleted file mode 100644
index acf2323..0000000
--- a/extensions/pdfjs/content/web/cmaps/78ms-RKSJ-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/83pv-RKSJ-H.bcmap b/extensions/pdfjs/content/web/cmaps/83pv-RKSJ-H.bcmap
deleted file mode 100644
index 2359bc5..0000000
--- a/extensions/pdfjs/content/web/cmaps/83pv-RKSJ-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/90ms-RKSJ-H.bcmap b/extensions/pdfjs/content/web/cmaps/90ms-RKSJ-H.bcmap
deleted file mode 100644
index af82938..0000000
--- a/extensions/pdfjs/content/web/cmaps/90ms-RKSJ-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/90ms-RKSJ-V.bcmap b/extensions/pdfjs/content/web/cmaps/90ms-RKSJ-V.bcmap
deleted file mode 100644
index 780549d..0000000
--- a/extensions/pdfjs/content/web/cmaps/90ms-RKSJ-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/90msp-RKSJ-H.bcmap b/extensions/pdfjs/content/web/cmaps/90msp-RKSJ-H.bcmap
deleted file mode 100644
index bfd3119..0000000
--- a/extensions/pdfjs/content/web/cmaps/90msp-RKSJ-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/90msp-RKSJ-V.bcmap b/extensions/pdfjs/content/web/cmaps/90msp-RKSJ-V.bcmap
deleted file mode 100644
index 25ef14a..0000000
--- a/extensions/pdfjs/content/web/cmaps/90msp-RKSJ-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/90pv-RKSJ-H.bcmap b/extensions/pdfjs/content/web/cmaps/90pv-RKSJ-H.bcmap
deleted file mode 100644
index 02f713b..0000000
--- a/extensions/pdfjs/content/web/cmaps/90pv-RKSJ-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/90pv-RKSJ-V.bcmap b/extensions/pdfjs/content/web/cmaps/90pv-RKSJ-V.bcmap
deleted file mode 100644
index d08e0cc..0000000
--- a/extensions/pdfjs/content/web/cmaps/90pv-RKSJ-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Add-H.bcmap b/extensions/pdfjs/content/web/cmaps/Add-H.bcmap
deleted file mode 100644
index 59442ac..0000000
--- a/extensions/pdfjs/content/web/cmaps/Add-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Add-RKSJ-H.bcmap b/extensions/pdfjs/content/web/cmaps/Add-RKSJ-H.bcmap
deleted file mode 100644
index a3065e4..0000000
--- a/extensions/pdfjs/content/web/cmaps/Add-RKSJ-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Add-RKSJ-V.bcmap b/extensions/pdfjs/content/web/cmaps/Add-RKSJ-V.bcmap
deleted file mode 100644
index 040014c..0000000
--- a/extensions/pdfjs/content/web/cmaps/Add-RKSJ-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Add-V.bcmap b/extensions/pdfjs/content/web/cmaps/Add-V.bcmap
deleted file mode 100644
index 2f816d3..0000000
--- a/extensions/pdfjs/content/web/cmaps/Add-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-0.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-0.bcmap
deleted file mode 100644
index 88ec04a..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-0.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-1.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-1.bcmap
deleted file mode 100644
index 03a5014..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-1.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-2.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-2.bcmap
deleted file mode 100644
index 2aa9514..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-2.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-3.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-3.bcmap
deleted file mode 100644
index 86d8b8c..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-3.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-4.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-4.bcmap
deleted file mode 100644
index f50fc6c..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-4.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-5.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-5.bcmap
deleted file mode 100644
index 6caf4a8..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-5.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-6.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-6.bcmap
deleted file mode 100644
index b77fb07..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-6.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-UCS2.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-UCS2.bcmap
deleted file mode 100644
index 69d79a2..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-CNS1-UCS2.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-0.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-GB1-0.bcmap
deleted file mode 100644
index 3610108..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-0.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-1.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-GB1-1.bcmap
deleted file mode 100644
index 707bb10..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-1.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-2.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-GB1-2.bcmap
deleted file mode 100644
index f7648cc..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-2.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-3.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-GB1-3.bcmap
deleted file mode 100644
index 8521458..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-3.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-4.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-GB1-4.bcmap
deleted file mode 100644
index e40c63a..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-4.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-5.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-GB1-5.bcmap
deleted file mode 100644
index d7623b5..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-5.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-UCS2.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-GB1-UCS2.bcmap
deleted file mode 100644
index 7586525..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-GB1-UCS2.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-0.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-0.bcmap
deleted file mode 100644
index f0e94ec..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-0.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-1.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-1.bcmap
deleted file mode 100644
index dad42c5..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-1.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-2.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-2.bcmap
deleted file mode 100644
index 090819a..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-2.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-3.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-3.bcmap
deleted file mode 100644
index 087dfc1..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-3.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-4.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-4.bcmap
deleted file mode 100644
index 46aa9bf..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-4.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-5.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-5.bcmap
deleted file mode 100644
index 5b4b65c..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-5.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-6.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-6.bcmap
deleted file mode 100644
index e77d699..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-6.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-UCS2.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-UCS2.bcmap
deleted file mode 100644
index 128a141..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Japan1-UCS2.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-0.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-0.bcmap
deleted file mode 100644
index cef1a99..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-0.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-1.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-1.bcmap
deleted file mode 100644
index 11ffa36..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-1.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-2.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-2.bcmap
deleted file mode 100644
index 3172308..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-2.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-UCS2.bcmap b/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-UCS2.bcmap
deleted file mode 100644
index f3371c0..0000000
--- a/extensions/pdfjs/content/web/cmaps/Adobe-Korea1-UCS2.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/B5-H.bcmap b/extensions/pdfjs/content/web/cmaps/B5-H.bcmap
deleted file mode 100644
index beb4d22..0000000
--- a/extensions/pdfjs/content/web/cmaps/B5-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/B5-V.bcmap b/extensions/pdfjs/content/web/cmaps/B5-V.bcmap
deleted file mode 100644
index 2d4f87d..0000000
--- a/extensions/pdfjs/content/web/cmaps/B5-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/B5pc-H.bcmap b/extensions/pdfjs/content/web/cmaps/B5pc-H.bcmap
deleted file mode 100644
index ce00131..0000000
--- a/extensions/pdfjs/content/web/cmaps/B5pc-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/B5pc-V.bcmap b/extensions/pdfjs/content/web/cmaps/B5pc-V.bcmap
deleted file mode 100644
index 73b99ff..0000000
--- a/extensions/pdfjs/content/web/cmaps/B5pc-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/CNS-EUC-H.bcmap b/extensions/pdfjs/content/web/cmaps/CNS-EUC-H.bcmap
deleted file mode 100644
index 61d1d0c..0000000
--- a/extensions/pdfjs/content/web/cmaps/CNS-EUC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/CNS-EUC-V.bcmap b/extensions/pdfjs/content/web/cmaps/CNS-EUC-V.bcmap
deleted file mode 100644
index 1a393a5..0000000
--- a/extensions/pdfjs/content/web/cmaps/CNS-EUC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/CNS1-H.bcmap b/extensions/pdfjs/content/web/cmaps/CNS1-H.bcmap
deleted file mode 100644
index f738e21..0000000
--- a/extensions/pdfjs/content/web/cmaps/CNS1-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/CNS1-V.bcmap b/extensions/pdfjs/content/web/cmaps/CNS1-V.bcmap
deleted file mode 100644
index 9c3169f..0000000
--- a/extensions/pdfjs/content/web/cmaps/CNS1-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/CNS2-H.bcmap b/extensions/pdfjs/content/web/cmaps/CNS2-H.bcmap
deleted file mode 100644
index c89b352..0000000
--- a/extensions/pdfjs/content/web/cmaps/CNS2-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/CNS2-V.bcmap b/extensions/pdfjs/content/web/cmaps/CNS2-V.bcmap
deleted file mode 100644
index 7588cec..0000000
--- a/extensions/pdfjs/content/web/cmaps/CNS2-V.bcmap
+++ /dev/null
@@ -1,3 +0,0 @@
-àRCopyright 1990-2009 Adobe Systems Incorporated.
-All rights reserved.
-See ./LICENSEáCNS2-H \ No newline at end of file
diff --git a/extensions/pdfjs/content/web/cmaps/ETHK-B5-H.bcmap b/extensions/pdfjs/content/web/cmaps/ETHK-B5-H.bcmap
deleted file mode 100644
index cb29415..0000000
--- a/extensions/pdfjs/content/web/cmaps/ETHK-B5-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/ETHK-B5-V.bcmap b/extensions/pdfjs/content/web/cmaps/ETHK-B5-V.bcmap
deleted file mode 100644
index f09aec6..0000000
--- a/extensions/pdfjs/content/web/cmaps/ETHK-B5-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/ETen-B5-H.bcmap b/extensions/pdfjs/content/web/cmaps/ETen-B5-H.bcmap
deleted file mode 100644
index c2d7746..0000000
--- a/extensions/pdfjs/content/web/cmaps/ETen-B5-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/ETen-B5-V.bcmap b/extensions/pdfjs/content/web/cmaps/ETen-B5-V.bcmap
deleted file mode 100644
index 89bff15..0000000
--- a/extensions/pdfjs/content/web/cmaps/ETen-B5-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/ETenms-B5-H.bcmap b/extensions/pdfjs/content/web/cmaps/ETenms-B5-H.bcmap
deleted file mode 100644
index a7d69db..0000000
--- a/extensions/pdfjs/content/web/cmaps/ETenms-B5-H.bcmap
+++ /dev/null
@@ -1,3 +0,0 @@
-àRCopyright 1990-2009 Adobe Systems Incorporated.
-All rights reserved.
-See ./LICENSEá ETen-B5-H` ^ \ No newline at end of file
diff --git a/extensions/pdfjs/content/web/cmaps/ETenms-B5-V.bcmap b/extensions/pdfjs/content/web/cmaps/ETenms-B5-V.bcmap
deleted file mode 100644
index adc5d61..0000000
--- a/extensions/pdfjs/content/web/cmaps/ETenms-B5-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/EUC-H.bcmap b/extensions/pdfjs/content/web/cmaps/EUC-H.bcmap
deleted file mode 100644
index e92ea5b..0000000
--- a/extensions/pdfjs/content/web/cmaps/EUC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/EUC-V.bcmap b/extensions/pdfjs/content/web/cmaps/EUC-V.bcmap
deleted file mode 100644
index 7a7c183..0000000
--- a/extensions/pdfjs/content/web/cmaps/EUC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Ext-H.bcmap b/extensions/pdfjs/content/web/cmaps/Ext-H.bcmap
deleted file mode 100644
index 3b5cde4..0000000
--- a/extensions/pdfjs/content/web/cmaps/Ext-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Ext-RKSJ-H.bcmap b/extensions/pdfjs/content/web/cmaps/Ext-RKSJ-H.bcmap
deleted file mode 100644
index ea4d2d9..0000000
--- a/extensions/pdfjs/content/web/cmaps/Ext-RKSJ-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Ext-RKSJ-V.bcmap b/extensions/pdfjs/content/web/cmaps/Ext-RKSJ-V.bcmap
deleted file mode 100644
index 3457c27..0000000
--- a/extensions/pdfjs/content/web/cmaps/Ext-RKSJ-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Ext-V.bcmap b/extensions/pdfjs/content/web/cmaps/Ext-V.bcmap
deleted file mode 100644
index 4999ca4..0000000
--- a/extensions/pdfjs/content/web/cmaps/Ext-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GB-EUC-H.bcmap b/extensions/pdfjs/content/web/cmaps/GB-EUC-H.bcmap
deleted file mode 100644
index e39908b..0000000
--- a/extensions/pdfjs/content/web/cmaps/GB-EUC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GB-EUC-V.bcmap b/extensions/pdfjs/content/web/cmaps/GB-EUC-V.bcmap
deleted file mode 100644
index d5be544..0000000
--- a/extensions/pdfjs/content/web/cmaps/GB-EUC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GB-H.bcmap b/extensions/pdfjs/content/web/cmaps/GB-H.bcmap
deleted file mode 100644
index 39189c5..0000000
--- a/extensions/pdfjs/content/web/cmaps/GB-H.bcmap
+++ /dev/null
@@ -1,4 +0,0 @@
-àRCopyright 1990-2009 Adobe Systems Incorporated.
-All rights reserved.
-See ./LICENSE!!º]aX!!]`21> p z$]‚"R‚d-Uƒ7*„ 4„%+ „Z „{/…%…<9K…b1]†."‡ ‰`]‡,"]ˆ
-"]ˆh"]‰F"]Š$"]‹"]‹`"]Œ>"]"]z"]ŽX"]6"]"]r"]‘P"]’."]“ "]“j"]”H"]•&"]–"]–b"]—@"]˜"]˜|"]™Z"]š8"]›"]›t"]œR"]0"]ž"]žl"]ŸJ"] ("]¡"]¡d"]¢B"]£ "X£~']¤W"]¥5"]¦"]¦q"]§O"]¨-"]© "]©i"]ªG"]«%"]¬"]¬a"]­?"]®"]®{"]¯Y"]°7"]±"]±s"]²Q"]³/"]´ "]´k"]µI"]¶'"]·"]·c"]¸A"]¹"]¹}"]º["]»9 \ No newline at end of file
diff --git a/extensions/pdfjs/content/web/cmaps/GB-V.bcmap b/extensions/pdfjs/content/web/cmaps/GB-V.bcmap
deleted file mode 100644
index 3108345..0000000
--- a/extensions/pdfjs/content/web/cmaps/GB-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBK-EUC-H.bcmap b/extensions/pdfjs/content/web/cmaps/GBK-EUC-H.bcmap
deleted file mode 100644
index 05fff7e..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBK-EUC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBK-EUC-V.bcmap b/extensions/pdfjs/content/web/cmaps/GBK-EUC-V.bcmap
deleted file mode 100644
index 0cdf6be..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBK-EUC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBK2K-H.bcmap b/extensions/pdfjs/content/web/cmaps/GBK2K-H.bcmap
deleted file mode 100644
index 46f6ba5..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBK2K-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBK2K-V.bcmap b/extensions/pdfjs/content/web/cmaps/GBK2K-V.bcmap
deleted file mode 100644
index d9a9479..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBK2K-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBKp-EUC-H.bcmap b/extensions/pdfjs/content/web/cmaps/GBKp-EUC-H.bcmap
deleted file mode 100644
index 5cb0af6..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBKp-EUC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBKp-EUC-V.bcmap b/extensions/pdfjs/content/web/cmaps/GBKp-EUC-V.bcmap
deleted file mode 100644
index bca93b8..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBKp-EUC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBT-EUC-H.bcmap b/extensions/pdfjs/content/web/cmaps/GBT-EUC-H.bcmap
deleted file mode 100644
index 4b4e2d3..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBT-EUC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBT-EUC-V.bcmap b/extensions/pdfjs/content/web/cmaps/GBT-EUC-V.bcmap
deleted file mode 100644
index 38f7066..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBT-EUC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBT-H.bcmap b/extensions/pdfjs/content/web/cmaps/GBT-H.bcmap
deleted file mode 100644
index 8437ac3..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBT-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBT-V.bcmap b/extensions/pdfjs/content/web/cmaps/GBT-V.bcmap
deleted file mode 100644
index 697ab4a..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBT-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBTpc-EUC-H.bcmap b/extensions/pdfjs/content/web/cmaps/GBTpc-EUC-H.bcmap
deleted file mode 100644
index f6e50e8..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBTpc-EUC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBTpc-EUC-V.bcmap b/extensions/pdfjs/content/web/cmaps/GBTpc-EUC-V.bcmap
deleted file mode 100644
index 6c0d71a..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBTpc-EUC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBpc-EUC-H.bcmap b/extensions/pdfjs/content/web/cmaps/GBpc-EUC-H.bcmap
deleted file mode 100644
index c9edf67..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBpc-EUC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/GBpc-EUC-V.bcmap b/extensions/pdfjs/content/web/cmaps/GBpc-EUC-V.bcmap
deleted file mode 100644
index 31450c9..0000000
--- a/extensions/pdfjs/content/web/cmaps/GBpc-EUC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/H.bcmap b/extensions/pdfjs/content/web/cmaps/H.bcmap
deleted file mode 100644
index 7b24ea4..0000000
--- a/extensions/pdfjs/content/web/cmaps/H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKdla-B5-H.bcmap b/extensions/pdfjs/content/web/cmaps/HKdla-B5-H.bcmap
deleted file mode 100644
index 7d30c05..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKdla-B5-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKdla-B5-V.bcmap b/extensions/pdfjs/content/web/cmaps/HKdla-B5-V.bcmap
deleted file mode 100644
index 7894694..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKdla-B5-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKdlb-B5-H.bcmap b/extensions/pdfjs/content/web/cmaps/HKdlb-B5-H.bcmap
deleted file mode 100644
index d829a23..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKdlb-B5-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKdlb-B5-V.bcmap b/extensions/pdfjs/content/web/cmaps/HKdlb-B5-V.bcmap
deleted file mode 100644
index 2b572b5..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKdlb-B5-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKgccs-B5-H.bcmap b/extensions/pdfjs/content/web/cmaps/HKgccs-B5-H.bcmap
deleted file mode 100644
index 971a4f2..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKgccs-B5-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKgccs-B5-V.bcmap b/extensions/pdfjs/content/web/cmaps/HKgccs-B5-V.bcmap
deleted file mode 100644
index d353ca2..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKgccs-B5-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKm314-B5-H.bcmap b/extensions/pdfjs/content/web/cmaps/HKm314-B5-H.bcmap
deleted file mode 100644
index 576dc01..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKm314-B5-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKm314-B5-V.bcmap b/extensions/pdfjs/content/web/cmaps/HKm314-B5-V.bcmap
deleted file mode 100644
index 0e96d0e..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKm314-B5-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKm471-B5-H.bcmap b/extensions/pdfjs/content/web/cmaps/HKm471-B5-H.bcmap
deleted file mode 100644
index 11d170c..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKm471-B5-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKm471-B5-V.bcmap b/extensions/pdfjs/content/web/cmaps/HKm471-B5-V.bcmap
deleted file mode 100644
index 54959bf..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKm471-B5-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKscs-B5-H.bcmap b/extensions/pdfjs/content/web/cmaps/HKscs-B5-H.bcmap
deleted file mode 100644
index 6ef7857..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKscs-B5-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/HKscs-B5-V.bcmap b/extensions/pdfjs/content/web/cmaps/HKscs-B5-V.bcmap
deleted file mode 100644
index 1fb2fa2..0000000
--- a/extensions/pdfjs/content/web/cmaps/HKscs-B5-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Hankaku.bcmap b/extensions/pdfjs/content/web/cmaps/Hankaku.bcmap
deleted file mode 100644
index 4b8ec7f..0000000
--- a/extensions/pdfjs/content/web/cmaps/Hankaku.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Hiragana.bcmap b/extensions/pdfjs/content/web/cmaps/Hiragana.bcmap
deleted file mode 100644
index 17e983e..0000000
--- a/extensions/pdfjs/content/web/cmaps/Hiragana.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSC-EUC-H.bcmap b/extensions/pdfjs/content/web/cmaps/KSC-EUC-H.bcmap
deleted file mode 100644
index a45c65f..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSC-EUC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSC-EUC-V.bcmap b/extensions/pdfjs/content/web/cmaps/KSC-EUC-V.bcmap
deleted file mode 100644
index 0e7b21f..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSC-EUC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSC-H.bcmap b/extensions/pdfjs/content/web/cmaps/KSC-H.bcmap
deleted file mode 100644
index b9b22b6..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSC-Johab-H.bcmap b/extensions/pdfjs/content/web/cmaps/KSC-Johab-H.bcmap
deleted file mode 100644
index 2531ffc..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSC-Johab-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSC-Johab-V.bcmap b/extensions/pdfjs/content/web/cmaps/KSC-Johab-V.bcmap
deleted file mode 100644
index 367ceb2..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSC-Johab-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSC-V.bcmap b/extensions/pdfjs/content/web/cmaps/KSC-V.bcmap
deleted file mode 100644
index 6ae2f0b..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSCms-UHC-H.bcmap b/extensions/pdfjs/content/web/cmaps/KSCms-UHC-H.bcmap
deleted file mode 100644
index a8d4240..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSCms-UHC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSCms-UHC-HW-H.bcmap b/extensions/pdfjs/content/web/cmaps/KSCms-UHC-HW-H.bcmap
deleted file mode 100644
index 8b4ae18..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSCms-UHC-HW-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSCms-UHC-HW-V.bcmap b/extensions/pdfjs/content/web/cmaps/KSCms-UHC-HW-V.bcmap
deleted file mode 100644
index b655dbc..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSCms-UHC-HW-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSCms-UHC-V.bcmap b/extensions/pdfjs/content/web/cmaps/KSCms-UHC-V.bcmap
deleted file mode 100644
index 21f97f6..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSCms-UHC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSCpc-EUC-H.bcmap b/extensions/pdfjs/content/web/cmaps/KSCpc-EUC-H.bcmap
deleted file mode 100644
index e06f361..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSCpc-EUC-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/KSCpc-EUC-V.bcmap b/extensions/pdfjs/content/web/cmaps/KSCpc-EUC-V.bcmap
deleted file mode 100644
index f3c9113..0000000
--- a/extensions/pdfjs/content/web/cmaps/KSCpc-EUC-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Katakana.bcmap b/extensions/pdfjs/content/web/cmaps/Katakana.bcmap
deleted file mode 100644
index 524303c..0000000
--- a/extensions/pdfjs/content/web/cmaps/Katakana.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/LICENSE b/extensions/pdfjs/content/web/cmaps/LICENSE
deleted file mode 100644
index b1ad168..0000000
--- a/extensions/pdfjs/content/web/cmaps/LICENSE
+++ /dev/null
@@ -1,36 +0,0 @@
-%%Copyright: -----------------------------------------------------------
-%%Copyright: Copyright 1990-2009 Adobe Systems Incorporated.
-%%Copyright: All rights reserved.
-%%Copyright:
-%%Copyright: Redistribution and use in source and binary forms, with or
-%%Copyright: without modification, are permitted provided that the
-%%Copyright: following conditions are met:
-%%Copyright:
-%%Copyright: Redistributions of source code must retain the above
-%%Copyright: copyright notice, this list of conditions and the following
-%%Copyright: disclaimer.
-%%Copyright:
-%%Copyright: Redistributions in binary form must reproduce the above
-%%Copyright: copyright notice, this list of conditions and the following
-%%Copyright: disclaimer in the documentation and/or other materials
-%%Copyright: provided with the distribution.
-%%Copyright:
-%%Copyright: Neither the name of Adobe Systems Incorporated nor the names
-%%Copyright: of its contributors may be used to endorse or promote
-%%Copyright: products derived from this software without specific prior
-%%Copyright: written permission.
-%%Copyright:
-%%Copyright: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
-%%Copyright: CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-%%Copyright: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-%%Copyright: MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-%%Copyright: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-%%Copyright: CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-%%Copyright: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-%%Copyright: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-%%Copyright: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-%%Copyright: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-%%Copyright: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-%%Copyright: OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-%%Copyright: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-%%Copyright: -----------------------------------------------------------
diff --git a/extensions/pdfjs/content/web/cmaps/NWP-H.bcmap b/extensions/pdfjs/content/web/cmaps/NWP-H.bcmap
deleted file mode 100644
index afc5e4b..0000000
--- a/extensions/pdfjs/content/web/cmaps/NWP-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/NWP-V.bcmap b/extensions/pdfjs/content/web/cmaps/NWP-V.bcmap
deleted file mode 100644
index bb5785e..0000000
--- a/extensions/pdfjs/content/web/cmaps/NWP-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/RKSJ-H.bcmap b/extensions/pdfjs/content/web/cmaps/RKSJ-H.bcmap
deleted file mode 100644
index fb8d298..0000000
--- a/extensions/pdfjs/content/web/cmaps/RKSJ-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/RKSJ-V.bcmap b/extensions/pdfjs/content/web/cmaps/RKSJ-V.bcmap
deleted file mode 100644
index a2555a6..0000000
--- a/extensions/pdfjs/content/web/cmaps/RKSJ-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/Roman.bcmap b/extensions/pdfjs/content/web/cmaps/Roman.bcmap
deleted file mode 100644
index f896dcf..0000000
--- a/extensions/pdfjs/content/web/cmaps/Roman.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniCNS-UCS2-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniCNS-UCS2-H.bcmap
deleted file mode 100644
index d5db27c..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniCNS-UCS2-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniCNS-UCS2-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniCNS-UCS2-V.bcmap
deleted file mode 100644
index 1dc9b7a..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniCNS-UCS2-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF16-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniCNS-UTF16-H.bcmap
deleted file mode 100644
index 961afef..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF16-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF16-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniCNS-UTF16-V.bcmap
deleted file mode 100644
index df0cffe..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF16-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF32-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniCNS-UTF32-H.bcmap
deleted file mode 100644
index 1ab18a1..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF32-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF32-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniCNS-UTF32-V.bcmap
deleted file mode 100644
index ad14662..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF32-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF8-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniCNS-UTF8-H.bcmap
deleted file mode 100644
index 83c6bd7..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF8-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF8-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniCNS-UTF8-V.bcmap
deleted file mode 100644
index 22a27e4..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniCNS-UTF8-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniGB-UCS2-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniGB-UCS2-H.bcmap
deleted file mode 100644
index 5bd6228..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniGB-UCS2-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniGB-UCS2-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniGB-UCS2-V.bcmap
deleted file mode 100644
index 53c534b..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniGB-UCS2-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniGB-UTF16-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniGB-UTF16-H.bcmap
deleted file mode 100644
index b95045b..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniGB-UTF16-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniGB-UTF16-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniGB-UTF16-V.bcmap
deleted file mode 100644
index 51f023e..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniGB-UTF16-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniGB-UTF32-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniGB-UTF32-H.bcmap
deleted file mode 100644
index f0dbd14..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniGB-UTF32-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniGB-UTF32-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniGB-UTF32-V.bcmap
deleted file mode 100644
index ce9c30a..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniGB-UTF32-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniGB-UTF8-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniGB-UTF8-H.bcmap
deleted file mode 100644
index 982ca46..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniGB-UTF8-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniGB-UTF8-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniGB-UTF8-V.bcmap
deleted file mode 100644
index f78020d..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniGB-UTF8-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-H.bcmap
deleted file mode 100644
index 7daf56a..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-H.bcmap
deleted file mode 100644
index ac9975c..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-V.bcmap
deleted file mode 100644
index 3da0a1c..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-HW-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-V.bcmap
deleted file mode 100644
index c50b9dd..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS-UCS2-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF16-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS-UTF16-H.bcmap
deleted file mode 100644
index 6761344..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF16-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF16-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS-UTF16-V.bcmap
deleted file mode 100644
index 70bf90c..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF16-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF32-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS-UTF32-H.bcmap
deleted file mode 100644
index 7a83d53..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF32-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF32-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS-UTF32-V.bcmap
deleted file mode 100644
index 7a87135..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF32-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF8-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS-UTF8-H.bcmap
deleted file mode 100644
index 9f0334c..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF8-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF8-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS-UTF8-V.bcmap
deleted file mode 100644
index 808a94f..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS-UTF8-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF16-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF16-H.bcmap
deleted file mode 100644
index d768bf8..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF16-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF16-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF16-V.bcmap
deleted file mode 100644
index 3d5bf6f..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF16-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF32-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF32-H.bcmap
deleted file mode 100644
index 09eee10..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF32-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF32-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF32-V.bcmap
deleted file mode 100644
index 6c54600..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF32-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF8-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF8-H.bcmap
deleted file mode 100644
index 1b1a64f..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF8-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF8-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF8-V.bcmap
deleted file mode 100644
index 994aa9e..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJIS2004-UTF8-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJISPro-UCS2-HW-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJISPro-UCS2-HW-V.bcmap
deleted file mode 100644
index 643f921..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJISPro-UCS2-HW-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJISPro-UCS2-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJISPro-UCS2-V.bcmap
deleted file mode 100644
index c148f67..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJISPro-UCS2-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJISPro-UTF8-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJISPro-UTF8-V.bcmap
deleted file mode 100644
index 1849d80..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJISPro-UTF8-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJISX0213-UTF32-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniJISX0213-UTF32-H.bcmap
deleted file mode 100644
index a83a677..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJISX0213-UTF32-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJISX0213-UTF32-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJISX0213-UTF32-V.bcmap
deleted file mode 100644
index f527248..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJISX0213-UTF32-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-H.bcmap
deleted file mode 100644
index e1a988d..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-V.bcmap
deleted file mode 100644
index 47e054a..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniJISX02132004-UTF32-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniKS-UCS2-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniKS-UCS2-H.bcmap
deleted file mode 100644
index b5b9485..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniKS-UCS2-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniKS-UCS2-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniKS-UCS2-V.bcmap
deleted file mode 100644
index 026adca..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniKS-UCS2-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniKS-UTF16-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniKS-UTF16-H.bcmap
deleted file mode 100644
index fd4e66e..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniKS-UTF16-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniKS-UTF16-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniKS-UTF16-V.bcmap
deleted file mode 100644
index 075efb7..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniKS-UTF16-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniKS-UTF32-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniKS-UTF32-H.bcmap
deleted file mode 100644
index 769d214..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniKS-UTF32-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniKS-UTF32-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniKS-UTF32-V.bcmap
deleted file mode 100644
index bdab208..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniKS-UTF32-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniKS-UTF8-H.bcmap b/extensions/pdfjs/content/web/cmaps/UniKS-UTF8-H.bcmap
deleted file mode 100644
index 6ff8674..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniKS-UTF8-H.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/UniKS-UTF8-V.bcmap b/extensions/pdfjs/content/web/cmaps/UniKS-UTF8-V.bcmap
deleted file mode 100644
index 8dfa76a..0000000
--- a/extensions/pdfjs/content/web/cmaps/UniKS-UTF8-V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/V.bcmap b/extensions/pdfjs/content/web/cmaps/V.bcmap
deleted file mode 100644
index fdec990..0000000
--- a/extensions/pdfjs/content/web/cmaps/V.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/cmaps/WP-Symbol.bcmap b/extensions/pdfjs/content/web/cmaps/WP-Symbol.bcmap
deleted file mode 100644
index 46729bb..0000000
--- a/extensions/pdfjs/content/web/cmaps/WP-Symbol.bcmap
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/debugger.js b/extensions/pdfjs/content/web/debugger.js
deleted file mode 100644
index 8a049f4..0000000
--- a/extensions/pdfjs/content/web/debugger.js
+++ /dev/null
@@ -1,616 +0,0 @@
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-var FontInspector = (function FontInspectorClosure() {
- var fonts;
- var active = false;
- var fontAttribute = 'data-font-name';
- function removeSelection() {
- var divs = document.querySelectorAll('div[' + fontAttribute + ']');
- for (var i = 0, ii = divs.length; i < ii; ++i) {
- var div = divs[i];
- div.className = '';
- }
- }
- function resetSelection() {
- var divs = document.querySelectorAll('div[' + fontAttribute + ']');
- for (var i = 0, ii = divs.length; i < ii; ++i) {
- var div = divs[i];
- div.className = 'debuggerHideText';
- }
- }
- function selectFont(fontName, show) {
- var divs = document.querySelectorAll('div[' + fontAttribute + '=' +
- fontName + ']');
- for (var i = 0, ii = divs.length; i < ii; ++i) {
- var div = divs[i];
- div.className = show ? 'debuggerShowText' : 'debuggerHideText';
- }
- }
- function textLayerClick(e) {
- if (!e.target.dataset.fontName ||
- e.target.tagName.toUpperCase() !== 'DIV') {
- return;
- }
- var fontName = e.target.dataset.fontName;
- var selects = document.getElementsByTagName('input');
- for (var i = 0; i < selects.length; ++i) {
- var select = selects[i];
- if (select.dataset.fontName !== fontName) {
- continue;
- }
- select.checked = !select.checked;
- selectFont(fontName, select.checked);
- select.scrollIntoView();
- }
- }
- return {
- // Properties/functions needed by PDFBug.
- id: 'FontInspector',
- name: 'Font Inspector',
- panel: null,
- manager: null,
- init: function init(pdfjsLib) {
- var panel = this.panel;
- panel.setAttribute('style', 'padding: 5px;');
- var tmp = document.createElement('button');
- tmp.addEventListener('click', resetSelection);
- tmp.textContent = 'Refresh';
- panel.appendChild(tmp);
-
- fonts = document.createElement('div');
- panel.appendChild(fonts);
- },
- cleanup: function cleanup() {
- fonts.textContent = '';
- },
- enabled: false,
- get active() {
- return active;
- },
- set active(value) {
- active = value;
- if (active) {
- document.body.addEventListener('click', textLayerClick, true);
- resetSelection();
- } else {
- document.body.removeEventListener('click', textLayerClick, true);
- removeSelection();
- }
- },
- // FontInspector specific functions.
- fontAdded: function fontAdded(fontObj, url) {
- function properties(obj, list) {
- var moreInfo = document.createElement('table');
- for (var i = 0; i < list.length; i++) {
- var tr = document.createElement('tr');
- var td1 = document.createElement('td');
- td1.textContent = list[i];
- tr.appendChild(td1);
- var td2 = document.createElement('td');
- td2.textContent = obj[list[i]].toString();
- tr.appendChild(td2);
- moreInfo.appendChild(tr);
- }
- return moreInfo;
- }
- var moreInfo = properties(fontObj, ['name', 'type']);
- var fontName = fontObj.loadedName;
- var font = document.createElement('div');
- var name = document.createElement('span');
- name.textContent = fontName;
- var download = document.createElement('a');
- if (url) {
- url = /url\(['"]?([^\)"']+)/.exec(url);
- download.href = url[1];
- } else if (fontObj.data) {
- url = URL.createObjectURL(new Blob([fontObj.data], {
- type: fontObj.mimeType
- }));
- download.href = url;
- }
- download.textContent = 'Download';
- var logIt = document.createElement('a');
- logIt.href = '';
- logIt.textContent = 'Log';
- logIt.addEventListener('click', function(event) {
- event.preventDefault();
- console.log(fontObj);
- });
- var select = document.createElement('input');
- select.setAttribute('type', 'checkbox');
- select.dataset.fontName = fontName;
- select.addEventListener('click', (function(select, fontName) {
- return (function() {
- selectFont(fontName, select.checked);
- });
- })(select, fontName));
- font.appendChild(select);
- font.appendChild(name);
- font.appendChild(document.createTextNode(' '));
- font.appendChild(download);
- font.appendChild(document.createTextNode(' '));
- font.appendChild(logIt);
- font.appendChild(moreInfo);
- fonts.appendChild(font);
- // Somewhat of a hack, should probably add a hook for when the text layer
- // is done rendering.
- setTimeout(function() {
- if (this.active) {
- resetSelection();
- }
- }.bind(this), 2000);
- }
- };
-})();
-
-var opMap;
-
-// Manages all the page steppers.
-var StepperManager = (function StepperManagerClosure() {
- var steppers = [];
- var stepperDiv = null;
- var stepperControls = null;
- var stepperChooser = null;
- var breakPoints = Object.create(null);
- return {
- // Properties/functions needed by PDFBug.
- id: 'Stepper',
- name: 'Stepper',
- panel: null,
- manager: null,
- init: function init(pdfjsLib) {
- var self = this;
- this.panel.setAttribute('style', 'padding: 5px;');
- stepperControls = document.createElement('div');
- stepperChooser = document.createElement('select');
- stepperChooser.addEventListener('change', function(event) {
- self.selectStepper(this.value);
- });
- stepperControls.appendChild(stepperChooser);
- stepperDiv = document.createElement('div');
- this.panel.appendChild(stepperControls);
- this.panel.appendChild(stepperDiv);
- if (sessionStorage.getItem('pdfjsBreakPoints')) {
- breakPoints = JSON.parse(sessionStorage.getItem('pdfjsBreakPoints'));
- }
-
- opMap = Object.create(null);
- for (var key in pdfjsLib.OPS) {
- opMap[pdfjsLib.OPS[key]] = key;
- }
- },
- cleanup: function cleanup() {
- stepperChooser.textContent = '';
- stepperDiv.textContent = '';
- steppers = [];
- },
- enabled: false,
- active: false,
- // Stepper specific functions.
- create: function create(pageIndex) {
- var debug = document.createElement('div');
- debug.id = 'stepper' + pageIndex;
- debug.setAttribute('hidden', true);
- debug.className = 'stepper';
- stepperDiv.appendChild(debug);
- var b = document.createElement('option');
- b.textContent = 'Page ' + (pageIndex + 1);
- b.value = pageIndex;
- stepperChooser.appendChild(b);
- var initBreakPoints = breakPoints[pageIndex] || [];
- var stepper = new Stepper(debug, pageIndex, initBreakPoints);
- steppers.push(stepper);
- if (steppers.length === 1) {
- this.selectStepper(pageIndex, false);
- }
- return stepper;
- },
- selectStepper: function selectStepper(pageIndex, selectPanel) {
- var i;
- pageIndex = pageIndex | 0;
- if (selectPanel) {
- this.manager.selectPanel(this);
- }
- for (i = 0; i < steppers.length; ++i) {
- var stepper = steppers[i];
- if (stepper.pageIndex === pageIndex) {
- stepper.panel.removeAttribute('hidden');
- } else {
- stepper.panel.setAttribute('hidden', true);
- }
- }
- var options = stepperChooser.options;
- for (i = 0; i < options.length; ++i) {
- var option = options[i];
- option.selected = (option.value | 0) === pageIndex;
- }
- },
- saveBreakPoints: function saveBreakPoints(pageIndex, bps) {
- breakPoints[pageIndex] = bps;
- sessionStorage.setItem('pdfjsBreakPoints', JSON.stringify(breakPoints));
- }
- };
-})();
-
-// The stepper for each page's IRQueue.
-var Stepper = (function StepperClosure() {
- // Shorter way to create element and optionally set textContent.
- function c(tag, textContent) {
- var d = document.createElement(tag);
- if (textContent) {
- d.textContent = textContent;
- }
- return d;
- }
-
- function simplifyArgs(args) {
- if (typeof args === 'string') {
- var MAX_STRING_LENGTH = 75;
- return args.length <= MAX_STRING_LENGTH ? args :
- args.substr(0, MAX_STRING_LENGTH) + '...';
- }
- if (typeof args !== 'object' || args === null) {
- return args;
- }
- if ('length' in args) { // array
- var simpleArgs = [], i, ii;
- var MAX_ITEMS = 10;
- for (i = 0, ii = Math.min(MAX_ITEMS, args.length); i < ii; i++) {
- simpleArgs.push(simplifyArgs(args[i]));
- }
- if (i < args.length) {
- simpleArgs.push('...');
- }
- return simpleArgs;
- }
- var simpleObj = {};
- for (var key in args) {
- simpleObj[key] = simplifyArgs(args[key]);
- }
- return simpleObj;
- }
-
- function Stepper(panel, pageIndex, initialBreakPoints) {
- this.panel = panel;
- this.breakPoint = 0;
- this.nextBreakPoint = null;
- this.pageIndex = pageIndex;
- this.breakPoints = initialBreakPoints;
- this.currentIdx = -1;
- this.operatorListIdx = 0;
- }
- Stepper.prototype = {
- init: function init(operatorList) {
- var panel = this.panel;
- var content = c('div', 'c=continue, s=step');
- var table = c('table');
- content.appendChild(table);
- table.cellSpacing = 0;
- var headerRow = c('tr');
- table.appendChild(headerRow);
- headerRow.appendChild(c('th', 'Break'));
- headerRow.appendChild(c('th', 'Idx'));
- headerRow.appendChild(c('th', 'fn'));
- headerRow.appendChild(c('th', 'args'));
- panel.appendChild(content);
- this.table = table;
- this.updateOperatorList(operatorList);
- },
- updateOperatorList: function updateOperatorList(operatorList) {
- var self = this;
-
- function cboxOnClick() {
- var x = +this.dataset.idx;
- if (this.checked) {
- self.breakPoints.push(x);
- } else {
- self.breakPoints.splice(self.breakPoints.indexOf(x), 1);
- }
- StepperManager.saveBreakPoints(self.pageIndex, self.breakPoints);
- }
-
- var MAX_OPERATORS_COUNT = 15000;
- if (this.operatorListIdx > MAX_OPERATORS_COUNT) {
- return;
- }
-
- var chunk = document.createDocumentFragment();
- var operatorsToDisplay = Math.min(MAX_OPERATORS_COUNT,
- operatorList.fnArray.length);
- for (var i = this.operatorListIdx; i < operatorsToDisplay; i++) {
- var line = c('tr');
- line.className = 'line';
- line.dataset.idx = i;
- chunk.appendChild(line);
- var checked = this.breakPoints.indexOf(i) !== -1;
- var args = operatorList.argsArray[i] || [];
-
- var breakCell = c('td');
- var cbox = c('input');
- cbox.type = 'checkbox';
- cbox.className = 'points';
- cbox.checked = checked;
- cbox.dataset.idx = i;
- cbox.onclick = cboxOnClick;
-
- breakCell.appendChild(cbox);
- line.appendChild(breakCell);
- line.appendChild(c('td', i.toString()));
- var fn = opMap[operatorList.fnArray[i]];
- var decArgs = args;
- if (fn === 'showText') {
- var glyphs = args[0];
- var newArgs = [];
- var str = [];
- for (var j = 0; j < glyphs.length; j++) {
- var glyph = glyphs[j];
- if (typeof glyph === 'object' && glyph !== null) {
- str.push(glyph.fontChar);
- } else {
- if (str.length > 0) {
- newArgs.push(str.join(''));
- str = [];
- }
- newArgs.push(glyph); // null or number
- }
- }
- if (str.length > 0) {
- newArgs.push(str.join(''));
- }
- decArgs = [newArgs];
- }
- line.appendChild(c('td', fn));
- line.appendChild(c('td', JSON.stringify(simplifyArgs(decArgs))));
- }
- if (operatorsToDisplay < operatorList.fnArray.length) {
- line = c('tr');
- var lastCell = c('td', '...');
- lastCell.colspan = 4;
- chunk.appendChild(lastCell);
- }
- this.operatorListIdx = operatorList.fnArray.length;
- this.table.appendChild(chunk);
- },
- getNextBreakPoint: function getNextBreakPoint() {
- this.breakPoints.sort(function(a, b) { return a - b; });
- for (var i = 0; i < this.breakPoints.length; i++) {
- if (this.breakPoints[i] > this.currentIdx) {
- return this.breakPoints[i];
- }
- }
- return null;
- },
- breakIt: function breakIt(idx, callback) {
- StepperManager.selectStepper(this.pageIndex, true);
- var self = this;
- var dom = document;
- self.currentIdx = idx;
- var listener = function(e) {
- switch (e.keyCode) {
- case 83: // step
- dom.removeEventListener('keydown', listener, false);
- self.nextBreakPoint = self.currentIdx + 1;
- self.goTo(-1);
- callback();
- break;
- case 67: // continue
- dom.removeEventListener('keydown', listener, false);
- var breakPoint = self.getNextBreakPoint();
- self.nextBreakPoint = breakPoint;
- self.goTo(-1);
- callback();
- break;
- }
- };
- dom.addEventListener('keydown', listener, false);
- self.goTo(idx);
- },
- goTo: function goTo(idx) {
- var allRows = this.panel.getElementsByClassName('line');
- for (var x = 0, xx = allRows.length; x < xx; ++x) {
- var row = allRows[x];
- if ((row.dataset.idx | 0) === idx) {
- row.style.backgroundColor = 'rgb(251,250,207)';
- row.scrollIntoView();
- } else {
- row.style.backgroundColor = null;
- }
- }
- }
- };
- return Stepper;
-})();
-
-var Stats = (function Stats() {
- var stats = [];
- function clear(node) {
- while (node.hasChildNodes()) {
- node.removeChild(node.lastChild);
- }
- }
- function getStatIndex(pageNumber) {
- for (var i = 0, ii = stats.length; i < ii; ++i) {
- if (stats[i].pageNumber === pageNumber) {
- return i;
- }
- }
- return false;
- }
- return {
- // Properties/functions needed by PDFBug.
- id: 'Stats',
- name: 'Stats',
- panel: null,
- manager: null,
- init: function init(pdfjsLib) {
- this.panel.setAttribute('style', 'padding: 5px;');
- pdfjsLib.PDFJS.enableStats = true;
- },
- enabled: false,
- active: false,
- // Stats specific functions.
- add: function(pageNumber, stat) {
- if (!stat) {
- return;
- }
- var statsIndex = getStatIndex(pageNumber);
- if (statsIndex !== false) {
- var b = stats[statsIndex];
- this.panel.removeChild(b.div);
- stats.splice(statsIndex, 1);
- }
- var wrapper = document.createElement('div');
- wrapper.className = 'stats';
- var title = document.createElement('div');
- title.className = 'title';
- title.textContent = 'Page: ' + pageNumber;
- var statsDiv = document.createElement('div');
- statsDiv.textContent = stat.toString();
- wrapper.appendChild(title);
- wrapper.appendChild(statsDiv);
- stats.push({ pageNumber: pageNumber, div: wrapper });
- stats.sort(function(a, b) { return a.pageNumber - b.pageNumber; });
- clear(this.panel);
- for (var i = 0, ii = stats.length; i < ii; ++i) {
- this.panel.appendChild(stats[i].div);
- }
- },
- cleanup: function () {
- stats = [];
- clear(this.panel);
- }
- };
-})();
-
-// Manages all the debugging tools.
-var PDFBug = (function PDFBugClosure() {
- var panelWidth = 300;
- var buttons = [];
- var activePanel = null;
-
- return {
- tools: [
- FontInspector,
- StepperManager,
- Stats
- ],
- enable: function(ids) {
- var all = false, tools = this.tools;
- if (ids.length === 1 && ids[0] === 'all') {
- all = true;
- }
- for (var i = 0; i < tools.length; ++i) {
- var tool = tools[i];
- if (all || ids.indexOf(tool.id) !== -1) {
- tool.enabled = true;
- }
- }
- if (!all) {
- // Sort the tools by the order they are enabled.
- tools.sort(function(a, b) {
- var indexA = ids.indexOf(a.id);
- indexA = indexA < 0 ? tools.length : indexA;
- var indexB = ids.indexOf(b.id);
- indexB = indexB < 0 ? tools.length : indexB;
- return indexA - indexB;
- });
- }
- },
- init: function init(pdfjsLib, container) {
- /*
- * Basic Layout:
- * PDFBug
- * Controls
- * Panels
- * Panel
- * Panel
- * ...
- */
- var ui = document.createElement('div');
- ui.id = 'PDFBug';
-
- var controls = document.createElement('div');
- controls.setAttribute('class', 'controls');
- ui.appendChild(controls);
-
- var panels = document.createElement('div');
- panels.setAttribute('class', 'panels');
- ui.appendChild(panels);
-
- container.appendChild(ui);
- container.style.right = panelWidth + 'px';
-
- // Initialize all the debugging tools.
- var tools = this.tools;
- var self = this;
- for (var i = 0; i < tools.length; ++i) {
- var tool = tools[i];
- var panel = document.createElement('div');
- var panelButton = document.createElement('button');
- panelButton.textContent = tool.name;
- panelButton.addEventListener('click', (function(selected) {
- return function(event) {
- event.preventDefault();
- self.selectPanel(selected);
- };
- })(i));
- controls.appendChild(panelButton);
- panels.appendChild(panel);
- tool.panel = panel;
- tool.manager = this;
- if (tool.enabled) {
- tool.init(pdfjsLib);
- } else {
- panel.textContent = tool.name + ' is disabled. To enable add ' +
- ' "' + tool.id + '" to the pdfBug parameter ' +
- 'and refresh (separate multiple by commas).';
- }
- buttons.push(panelButton);
- }
- this.selectPanel(0);
- },
- cleanup: function cleanup() {
- for (var i = 0, ii = this.tools.length; i < ii; i++) {
- if (this.tools[i].enabled) {
- this.tools[i].cleanup();
- }
- }
- },
- selectPanel: function selectPanel(index) {
- if (typeof index !== 'number') {
- index = this.tools.indexOf(index);
- }
- if (index === activePanel) {
- return;
- }
- activePanel = index;
- var tools = this.tools;
- for (var j = 0; j < tools.length; ++j) {
- if (j === index) {
- buttons[j].setAttribute('class', 'active');
- tools[j].active = true;
- tools[j].panel.removeAttribute('hidden');
- } else {
- buttons[j].setAttribute('class', '');
- tools[j].active = false;
- tools[j].panel.setAttribute('hidden', 'true');
- }
- }
- }
- };
-})();
diff --git a/extensions/pdfjs/content/web/images/annotation-check.svg b/extensions/pdfjs/content/web/images/annotation-check.svg
deleted file mode 100644
index 71cd16d..0000000
--- a/extensions/pdfjs/content/web/images/annotation-check.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns="http://www.w3.org/2000/svg"
- width="40"
- height="40"
- viewBox="0 0 40 40">
- <path
- d="M 1.5006714,23.536225 6.8925879,18.994244 14.585721,26.037937 34.019683,4.5410479 38.499329,9.2235032 14.585721,35.458952 z"
- id="path4"
- style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1.25402856;stroke-opacity:1" />
-</svg>
diff --git a/extensions/pdfjs/content/web/images/annotation-comment.svg b/extensions/pdfjs/content/web/images/annotation-comment.svg
deleted file mode 100644
index 86f1f17..0000000
--- a/extensions/pdfjs/content/web/images/annotation-comment.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns="http://www.w3.org/2000/svg"
- height="40"
- width="40"
- viewBox="0 0 40 40">
- <rect
- style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- width="33.76017"
- height="33.76017"
- x="3.119915"
- y="3.119915" />
- <path
- d="m 20.677967,8.54499 c -7.342801,0 -13.295293,4.954293 -13.295293,11.065751 0,2.088793 0.3647173,3.484376 1.575539,5.150563 L 6.0267418,31.45501 13.560595,29.011117 c 2.221262,1.387962 4.125932,1.665377 7.117372,1.665377 7.3428,0 13.295291,-4.954295 13.295291,-11.065753 0,-6.111458 -5.952491,-11.065751 -13.295291,-11.065751 z"
- style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.93031836;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"/>
-</svg>
diff --git a/extensions/pdfjs/content/web/images/annotation-help.svg b/extensions/pdfjs/content/web/images/annotation-help.svg
deleted file mode 100644
index 00938fe..0000000
--- a/extensions/pdfjs/content/web/images/annotation-help.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns="http://www.w3.org/2000/svg"
- width="40"
- height="40"
- viewBox="0 0 40 40">
- <g
- transform="translate(0,-60)"
- id="layer1">
- <rect
- width="36.460953"
- height="34.805603"
- x="1.7695236"
- y="62.597198"
- style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.30826771;stroke-opacity:1" />
- <g
- transform="matrix(0.88763677,0,0,0.88763677,2.2472646,8.9890584)">
- <path
- d="M 20,64.526342 C 11.454135,64.526342 4.5263421,71.454135 4.5263421,80 4.5263421,88.545865 11.454135,95.473658 20,95.473658 28.545865,95.473658 35.473658,88.545865 35.473658,80 35.473658,71.454135 28.545865,64.526342 20,64.526342 z m -0.408738,9.488564 c 3.527079,0 6.393832,2.84061 6.393832,6.335441 0,3.494831 -2.866753,6.335441 -6.393832,6.335441 -3.527079,0 -6.393832,-2.84061 -6.393832,-6.335441 0,-3.494831 2.866753,-6.335441 6.393832,-6.335441 z"
- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.02768445;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
- <path
- d="m 7.2335209,71.819938 4.9702591,4.161823 c -1.679956,2.581606 -1.443939,6.069592 0.159325,8.677725 l -5.1263071,3.424463 c 0.67516,1.231452 3.0166401,3.547686 4.2331971,4.194757 l 3.907728,-4.567277 c 2.541952,1.45975 5.730694,1.392161 8.438683,-0.12614 l 3.469517,6.108336 c 1.129779,-0.44367 4.742234,-3.449633 5.416358,-5.003859 l -5.46204,-4.415541 c 1.44319,-2.424098 1.651175,-5.267515 0.557303,-7.748623 l 5.903195,-3.833951 C 33.14257,71.704996 30.616217,69.018606 29.02952,67.99296 l -4.118813,4.981678 C 22.411934,71.205099 18.900853,70.937534 16.041319,72.32916 l -3.595408,-5.322091 c -1.345962,0.579488 -4.1293881,2.921233 -5.2123901,4.812869 z m 8.1010311,3.426672 c 2.75284,-2.446266 6.769149,-2.144694 9.048998,0.420874 2.279848,2.56557 2.113919,6.596919 -0.638924,9.043185 -2.752841,2.446267 -6.775754,2.13726 -9.055604,-0.428308 -2.279851,-2.565568 -2.107313,-6.589485 0.64553,-9.035751 z"
- style="fill:#000000;fill-opacity:1;stroke:none" />
- </g>
- </g>
-</svg>
diff --git a/extensions/pdfjs/content/web/images/annotation-insert.svg b/extensions/pdfjs/content/web/images/annotation-insert.svg
deleted file mode 100644
index 519ef68..0000000
--- a/extensions/pdfjs/content/web/images/annotation-insert.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns="http://www.w3.org/2000/svg"
- width="64"
- height="64"
- viewBox="0 0 64 64">
- <path
- d="M 32.003143,1.4044602 57.432701,62.632577 6.5672991,62.627924 z"
- style="fill:#ffff00;fill-opacity:0.94117647;fill-rule:nonzero;stroke:#000000;stroke-width:1.00493038;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-</svg>
diff --git a/extensions/pdfjs/content/web/images/annotation-key.svg b/extensions/pdfjs/content/web/images/annotation-key.svg
deleted file mode 100644
index 8d09d53..0000000
--- a/extensions/pdfjs/content/web/images/annotation-key.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns="http://www.w3.org/2000/svg"
- width="64"
- height="64"
- viewBox="0 0 64 64">
- <path
- d="M 25.470843,9.4933766 C 25.30219,12.141818 30.139101,14.445969 34.704831,13.529144 40.62635,12.541995 41.398833,7.3856498 35.97505,5.777863 31.400921,4.1549155 25.157674,6.5445892 25.470843,9.4933766 z M 4.5246282,17.652051 C 4.068249,11.832873 9.2742983,5.9270407 18.437379,3.0977088 29.751911,-0.87185184 45.495663,1.4008022 53.603953,7.1104009 c 9.275765,6.1889221 7.158128,16.2079421 -3.171076,21.5939521 -1.784316,1.635815 -6.380222,1.21421 -7.068351,3.186186 -1.04003,0.972427 -1.288046,2.050158 -1.232864,3.168203 1.015111,2.000108 -3.831548,1.633216 -3.270553,3.759574 0.589477,5.264544 -0.179276,10.53738 -0.362842,15.806257 -0.492006,2.184998 1.163456,4.574232 -0.734888,6.610642 -2.482919,2.325184 -7.30604,2.189143 -9.193497,-0.274767 -2.733688,-1.740626 -8.254447,-3.615254 -6.104247,-6.339626 3.468112,-1.708686 -2.116197,-3.449897 0.431242,-5.080274 5.058402,-1.39256 -2.393215,-2.304318 -0.146889,-4.334645 3.069198,-0.977415 2.056986,-2.518352 -0.219121,-3.540397 1.876567,-1.807151 1.484149,-4.868919 -2.565455,-5.942205 0.150866,-1.805474 2.905737,-4.136876 -1.679967,-5.20493 C 10.260902,27.882167 4.6872697,22.95045 4.5245945,17.652051 z"
- id="path604"
- style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1.72665179;stroke-opacity:1" />
-</svg>
diff --git a/extensions/pdfjs/content/web/images/annotation-newparagraph.svg b/extensions/pdfjs/content/web/images/annotation-newparagraph.svg
deleted file mode 100644
index 38d2497..0000000
--- a/extensions/pdfjs/content/web/images/annotation-newparagraph.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns="http://www.w3.org/2000/svg"
- width="64"
- height="64"
- viewBox="0 0 64 64">
- <path
- d="M 32.003143,10.913072 57.432701,53.086929 6.567299,53.083723 z"
- id="path2985"
- style="fill:#ffff00;fill-opacity:0.94117647;fill-rule:nonzero;stroke:#000000;stroke-width:0.83403099;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-</svg>
diff --git a/extensions/pdfjs/content/web/images/annotation-noicon.svg b/extensions/pdfjs/content/web/images/annotation-noicon.svg
deleted file mode 100644
index c07d108..0000000
--- a/extensions/pdfjs/content/web/images/annotation-noicon.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns="http://www.w3.org/2000/svg"
- width="40"
- height="40"
- viewBox="0 0 40 40">
-</svg>
diff --git a/extensions/pdfjs/content/web/images/annotation-note.svg b/extensions/pdfjs/content/web/images/annotation-note.svg
deleted file mode 100644
index 7017365..0000000
--- a/extensions/pdfjs/content/web/images/annotation-note.svg
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns="http://www.w3.org/2000/svg"
- width="40"
- height="40"
- viewBox="0 0 40 40">
- <rect
- width="36.075428"
- height="31.096582"
- x="1.962286"
- y="4.4517088"
- id="rect4"
- style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.23004246;stroke-opacity:1" />
- <rect
- width="27.96859"
- height="1.5012145"
- x="6.0157046"
- y="10.285"
- id="rect6"
- style="fill:#000000;fill-opacity:1;stroke:none" />
- <rect
- width="27.96859"
- height="0.85783684"
- x="6.0157056"
- y="23.21689"
- id="rect8"
- style="fill:#000000;fill-opacity:1;stroke:none" />
- <rect
- width="27.96859"
- height="0.85783684"
- x="5.8130345"
- y="28.964394"
- id="rect10"
- style="fill:#000000;fill-opacity:1;stroke:none" />
- <rect
- width="27.96859"
- height="0.85783684"
- x="6.0157046"
- y="17.426493"
- id="rect12"
- style="fill:#000000;fill-opacity:1;stroke:none" />
-</svg>
diff --git a/extensions/pdfjs/content/web/images/annotation-paragraph.svg b/extensions/pdfjs/content/web/images/annotation-paragraph.svg
deleted file mode 100644
index 6ae5212..0000000
--- a/extensions/pdfjs/content/web/images/annotation-paragraph.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns="http://www.w3.org/2000/svg"
- width="40"
- height="40"
- viewBox="0 0 40 40">
- <rect
- width="33.76017"
- height="33.76017"
- x="3.119915"
- y="3.119915"
- style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
- <path
- d="m 17.692678,34.50206 0,-16.182224 c -1.930515,-0.103225 -3.455824,-0.730383 -4.57593,-1.881473 -1.12011,-1.151067 -1.680164,-2.619596 -1.680164,-4.405591 0,-1.992435 0.621995,-3.5796849 1.865988,-4.7617553 1.243989,-1.1820288 3.06352,-1.7730536 5.458598,-1.7730764 l 9.802246,0 0,2.6789711 -2.229895,0 0,26.3251486 -2.632515,0 0,-26.3251486 -3.45324,0 0,26.3251486 z"
- style="font-size:29.42051125px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.07795751;stroke-opacity:1;font-family:Arial;-inkscape-font-specification:Arial" />
-</svg>
diff --git a/extensions/pdfjs/content/web/images/findbarButton-next-rtl.png b/extensions/pdfjs/content/web/images/findbarButton-next-rtl.png
deleted file mode 100644
index bef0274..0000000
--- a/extensions/pdfjs/content/web/images/findbarButton-next-rtl.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/findbarButton-next-rtl@2x.png b/extensions/pdfjs/content/web/images/findbarButton-next-rtl@2x.png
deleted file mode 100644
index 1da6dc9..0000000
--- a/extensions/pdfjs/content/web/images/findbarButton-next-rtl@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/findbarButton-next.png b/extensions/pdfjs/content/web/images/findbarButton-next.png
deleted file mode 100644
index de1d0fc..0000000
--- a/extensions/pdfjs/content/web/images/findbarButton-next.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/findbarButton-next@2x.png b/extensions/pdfjs/content/web/images/findbarButton-next@2x.png
deleted file mode 100644
index 0250307..0000000
--- a/extensions/pdfjs/content/web/images/findbarButton-next@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/findbarButton-previous-rtl.png b/extensions/pdfjs/content/web/images/findbarButton-previous-rtl.png
deleted file mode 100644
index de1d0fc..0000000
--- a/extensions/pdfjs/content/web/images/findbarButton-previous-rtl.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/findbarButton-previous-rtl@2x.png b/extensions/pdfjs/content/web/images/findbarButton-previous-rtl@2x.png
deleted file mode 100644
index 0250307..0000000
--- a/extensions/pdfjs/content/web/images/findbarButton-previous-rtl@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/findbarButton-previous.png b/extensions/pdfjs/content/web/images/findbarButton-previous.png
deleted file mode 100644
index bef0274..0000000
--- a/extensions/pdfjs/content/web/images/findbarButton-previous.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/findbarButton-previous@2x.png b/extensions/pdfjs/content/web/images/findbarButton-previous@2x.png
deleted file mode 100644
index 1da6dc9..0000000
--- a/extensions/pdfjs/content/web/images/findbarButton-previous@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/grab.cur b/extensions/pdfjs/content/web/images/grab.cur
deleted file mode 100644
index db7ad5a..0000000
--- a/extensions/pdfjs/content/web/images/grab.cur
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/grabbing.cur b/extensions/pdfjs/content/web/images/grabbing.cur
deleted file mode 100644
index e0dfd04..0000000
--- a/extensions/pdfjs/content/web/images/grabbing.cur
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/loading-icon.gif b/extensions/pdfjs/content/web/images/loading-icon.gif
deleted file mode 100644
index 1c72ebb..0000000
--- a/extensions/pdfjs/content/web/images/loading-icon.gif
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/loading-small.png b/extensions/pdfjs/content/web/images/loading-small.png
deleted file mode 100644
index 8831a80..0000000
--- a/extensions/pdfjs/content/web/images/loading-small.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/loading-small@2x.png b/extensions/pdfjs/content/web/images/loading-small@2x.png
deleted file mode 100644
index b25b445..0000000
--- a/extensions/pdfjs/content/web/images/loading-small@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-documentProperties.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-documentProperties.png
deleted file mode 100644
index 40925e2..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-documentProperties.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-documentProperties@2x.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-documentProperties@2x.png
deleted file mode 100644
index adb240e..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-documentProperties@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-firstPage.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-firstPage.png
deleted file mode 100644
index e68846a..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-firstPage.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-firstPage@2x.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-firstPage@2x.png
deleted file mode 100644
index 3ad8af5..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-firstPage@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-handTool.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-handTool.png
deleted file mode 100644
index cb85a84..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-handTool.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-handTool@2x.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-handTool@2x.png
deleted file mode 100644
index 5c13f77..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-handTool@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-lastPage.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-lastPage.png
deleted file mode 100644
index be763e0..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-lastPage.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-lastPage@2x.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-lastPage@2x.png
deleted file mode 100644
index 8570984..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-lastPage@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw.png
deleted file mode 100644
index 675d6da..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw@2x.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw@2x.png
deleted file mode 100644
index b9e7431..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCcw@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCw.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCw.png
deleted file mode 100644
index e1c7598..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCw.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCw@2x.png b/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCw@2x.png
deleted file mode 100644
index cb257b4..0000000
--- a/extensions/pdfjs/content/web/images/secondaryToolbarButton-rotateCw@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/shadow.png b/extensions/pdfjs/content/web/images/shadow.png
deleted file mode 100644
index 31d3bdb..0000000
--- a/extensions/pdfjs/content/web/images/shadow.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/texture.png b/extensions/pdfjs/content/web/images/texture.png
deleted file mode 100644
index 12bae83..0000000
--- a/extensions/pdfjs/content/web/images/texture.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-bookmark.png b/extensions/pdfjs/content/web/images/toolbarButton-bookmark.png
deleted file mode 100644
index a187be6..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-bookmark.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-bookmark@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-bookmark@2x.png
deleted file mode 100644
index 4efbaa6..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-bookmark@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-download.png b/extensions/pdfjs/content/web/images/toolbarButton-download.png
deleted file mode 100644
index eaab35f..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-download.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-download@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-download@2x.png
deleted file mode 100644
index 896face..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-download@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-menuArrows.png b/extensions/pdfjs/content/web/images/toolbarButton-menuArrows.png
deleted file mode 100644
index e50ca4e..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-menuArrows.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-menuArrows@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-menuArrows@2x.png
deleted file mode 100644
index f7570bc..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-menuArrows@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-openFile.png b/extensions/pdfjs/content/web/images/toolbarButton-openFile.png
deleted file mode 100644
index b5cf1bd..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-openFile.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-openFile@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-openFile@2x.png
deleted file mode 100644
index 91ab765..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-openFile@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-pageDown-rtl.png b/extensions/pdfjs/content/web/images/toolbarButton-pageDown-rtl.png
deleted file mode 100644
index 1957f79..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-pageDown-rtl.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-pageDown-rtl@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-pageDown-rtl@2x.png
deleted file mode 100644
index 16ebcb8..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-pageDown-rtl@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-pageDown.png b/extensions/pdfjs/content/web/images/toolbarButton-pageDown.png
deleted file mode 100644
index 8219ecf..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-pageDown.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-pageDown@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-pageDown@2x.png
deleted file mode 100644
index 758c01d..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-pageDown@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-pageUp-rtl.png b/extensions/pdfjs/content/web/images/toolbarButton-pageUp-rtl.png
deleted file mode 100644
index 98e7ce4..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-pageUp-rtl.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-pageUp-rtl@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-pageUp-rtl@2x.png
deleted file mode 100644
index a01b023..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-pageUp-rtl@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-pageUp.png b/extensions/pdfjs/content/web/images/toolbarButton-pageUp.png
deleted file mode 100644
index fb9daa3..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-pageUp.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-pageUp@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-pageUp@2x.png
deleted file mode 100644
index a5cfd75..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-pageUp@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-presentationMode.png b/extensions/pdfjs/content/web/images/toolbarButton-presentationMode.png
deleted file mode 100644
index 3ac2124..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-presentationMode.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-presentationMode@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-presentationMode@2x.png
deleted file mode 100644
index cada9e7..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-presentationMode@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-print.png b/extensions/pdfjs/content/web/images/toolbarButton-print.png
deleted file mode 100644
index 51275e5..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-print.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-print@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-print@2x.png
deleted file mode 100644
index 53d18da..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-print@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-search.png b/extensions/pdfjs/content/web/images/toolbarButton-search.png
deleted file mode 100644
index f9b7557..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-search.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-search@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-search@2x.png
deleted file mode 100644
index 456b133..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-search@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle-rtl.png b/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle-rtl.png
deleted file mode 100644
index 8437095..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle-rtl.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle-rtl@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle-rtl@2x.png
deleted file mode 100644
index 9d9bfa4..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle-rtl@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle.png b/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle.png
deleted file mode 100644
index 1f90f83..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle@2x.png
deleted file mode 100644
index b066fe5..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-secondaryToolbarToggle@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle-rtl.png b/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle-rtl.png
deleted file mode 100644
index 6f85ec0..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle-rtl.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle-rtl@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle-rtl@2x.png
deleted file mode 100644
index 291e006..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle-rtl@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle.png b/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle.png
deleted file mode 100644
index 025dc90..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle@2x.png
deleted file mode 100644
index 7f834df..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-sidebarToggle@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-viewAttachments.png b/extensions/pdfjs/content/web/images/toolbarButton-viewAttachments.png
deleted file mode 100644
index fcd0b26..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-viewAttachments.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-viewAttachments@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-viewAttachments@2x.png
deleted file mode 100644
index 4a5e2b8..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-viewAttachments@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-viewOutline-rtl.png b/extensions/pdfjs/content/web/images/toolbarButton-viewOutline-rtl.png
deleted file mode 100644
index aaa9430..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-viewOutline-rtl.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-viewOutline-rtl@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-viewOutline-rtl@2x.png
deleted file mode 100644
index 3410f70..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-viewOutline-rtl@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-viewOutline.png b/extensions/pdfjs/content/web/images/toolbarButton-viewOutline.png
deleted file mode 100644
index 976365a..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-viewOutline.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-viewOutline@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-viewOutline@2x.png
deleted file mode 100644
index b6a197f..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-viewOutline@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail.png b/extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail.png
deleted file mode 100644
index 584ba55..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail@2x.png
deleted file mode 100644
index a0208b4..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-zoomIn.png b/extensions/pdfjs/content/web/images/toolbarButton-zoomIn.png
deleted file mode 100644
index 513d081..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-zoomIn.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-zoomIn@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-zoomIn@2x.png
deleted file mode 100644
index d5d49d5..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-zoomIn@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-zoomOut.png b/extensions/pdfjs/content/web/images/toolbarButton-zoomOut.png
deleted file mode 100644
index 156c26b..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-zoomOut.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/toolbarButton-zoomOut@2x.png b/extensions/pdfjs/content/web/images/toolbarButton-zoomOut@2x.png
deleted file mode 100644
index 959e191..0000000
--- a/extensions/pdfjs/content/web/images/toolbarButton-zoomOut@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/treeitem-collapsed-rtl.png b/extensions/pdfjs/content/web/images/treeitem-collapsed-rtl.png
deleted file mode 100644
index 0496b35..0000000
--- a/extensions/pdfjs/content/web/images/treeitem-collapsed-rtl.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/treeitem-collapsed-rtl@2x.png b/extensions/pdfjs/content/web/images/treeitem-collapsed-rtl@2x.png
deleted file mode 100644
index 6ad9ebc..0000000
--- a/extensions/pdfjs/content/web/images/treeitem-collapsed-rtl@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/treeitem-collapsed.png b/extensions/pdfjs/content/web/images/treeitem-collapsed.png
deleted file mode 100644
index 06d4d37..0000000
--- a/extensions/pdfjs/content/web/images/treeitem-collapsed.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/treeitem-collapsed@2x.png b/extensions/pdfjs/content/web/images/treeitem-collapsed@2x.png
deleted file mode 100644
index eec1e58..0000000
--- a/extensions/pdfjs/content/web/images/treeitem-collapsed@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/treeitem-expanded.png b/extensions/pdfjs/content/web/images/treeitem-expanded.png
deleted file mode 100644
index c8d5573..0000000
--- a/extensions/pdfjs/content/web/images/treeitem-expanded.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/images/treeitem-expanded@2x.png b/extensions/pdfjs/content/web/images/treeitem-expanded@2x.png
deleted file mode 100644
index 3b3b610..0000000
--- a/extensions/pdfjs/content/web/images/treeitem-expanded@2x.png
+++ /dev/null
Binary files differ
diff --git a/extensions/pdfjs/content/web/l10n.js b/extensions/pdfjs/content/web/l10n.js
deleted file mode 100644
index 2e0684e..0000000
--- a/extensions/pdfjs/content/web/l10n.js
+++ /dev/null
@@ -1,151 +0,0 @@
-
-'use strict';
-
-// Small subset of the webL10n API by Fabien Cazenave for pdf.js extension.
-(function(window) {
- var gLanguage = '';
- var gExternalLocalizerServices = null;
-
- // fetch an l10n objects
- function getL10nData(key) {
- var response = gExternalLocalizerServices.getStrings(key);
- var data = JSON.parse(response);
- if (!data) {
- console.warn('[l10n] #' + key + ' missing for [' + gLanguage + ']');
- }
- return data;
- }
-
- // replace {{arguments}} with their values
- function substArguments(text, args) {
- if (!args) {
- return text;
- }
- return text.replace(/\{\{\s*(\w+)\s*\}\}/g, function(all, name) {
- return (name in args ? args[name] : '{{' + name + '}}');
- });
- }
-
- // translate a string
- function translateString(key, args, fallback) {
- var i = key.lastIndexOf('.');
- var name, property;
- if (i >= 0) {
- name = key.substring(0, i);
- property = key.substring(i + 1);
- } else {
- name = key;
- property = 'textContent';
- }
- var data = getL10nData(name);
- var value = (data && data[property]) || fallback;
- if (!value) {
- return '{{' + key + '}}';
- }
- return substArguments(value, args);
- }
-
- // translate an HTML element
- function translateElement(element) {
- if (!element || !element.dataset) {
- return;
- }
-
- // get the related l10n object
- var key = element.dataset.l10nId;
- var data = getL10nData(key);
- if (!data) {
- return;
- }
-
- // get arguments (if any)
- // TODO: more flexible parser?
- var args;
- if (element.dataset.l10nArgs) {
- try {
- args = JSON.parse(element.dataset.l10nArgs);
- } catch (e) {
- console.warn('[l10n] could not parse arguments for #' + key + '');
- }
- }
-
- // translate element
- // TODO: security check?
- for (var k in data) {
- element[k] = substArguments(data[k], args);
- }
- }
-
-
- // translate an HTML subtree
- function translateFragment(element) {
- element = element || document.querySelector('html');
-
- // check all translatable children (= w/ a `data-l10n-id' attribute)
- var children = element.querySelectorAll('*[data-l10n-id]');
- var elementCount = children.length;
- for (var i = 0; i < elementCount; i++) {
- translateElement(children[i]);
- }
-
- // translate element itself if necessary
- if (element.dataset.l10nId) {
- translateElement(element);
- }
- }
-
- function translateDocument() {
- gLanguage = gExternalLocalizerServices.getLocale();
-
- translateFragment();
-
- // fire a 'localized' DOM event
- var evtObject = document.createEvent('Event');
- evtObject.initEvent('localized', false, false);
- evtObject.language = gLanguage;
- window.dispatchEvent(evtObject);
- }
-
- window.addEventListener('DOMContentLoaded', function() {
- if (gExternalLocalizerServices) {
- translateDocument();
- }
- // ... else see setExternalLocalizerServices below
- });
-
- // Public API
- document.mozL10n = {
- // get a localized string
- get: translateString,
-
- // get the document language
- getLanguage: function() {
- return gLanguage;
- },
-
- // get the direction (ltr|rtl) of the current language
- getDirection: function() {
- // http://www.w3.org/International/questions/qa-scripts
- // Arabic, Hebrew, Farsi, Pashto, Urdu
- var rtlList = ['ar', 'he', 'fa', 'ps', 'ur'];
-
- // use the short language code for "full" codes like 'ar-sa' (issue 5440)
- var shortCode = gLanguage.split('-')[0];
-
- return (rtlList.indexOf(shortCode) >= 0) ? 'rtl' : 'ltr';
- },
-
- setExternalLocalizerServices: function (externalLocalizerServices) {
- gExternalLocalizerServices = externalLocalizerServices;
-
- // ... in case if we missed DOMContentLoaded above.
- if (window.document.readyState === 'interactive' ||
- window.document.readyState === 'complete') {
- translateDocument();
- }
- },
-
- // translate an element or document fragment
- translate: translateFragment
- };
-})(this);
diff --git a/extensions/pdfjs/content/web/viewer.css b/extensions/pdfjs/content/web/viewer.css
deleted file mode 100644
index 74b6fab..0000000
--- a/extensions/pdfjs/content/web/viewer.css
+++ /dev/null
@@ -1,2034 +0,0 @@
-/* Copyright 2014 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-.textLayer {
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- overflow: hidden;
- opacity: 0.2;
- line-height: 1.0;
-}
-
-.textLayer > div {
- color: transparent;
- position: absolute;
- white-space: pre;
- cursor: text;
- -moz-transform-origin: 0% 0%;
- transform-origin: 0% 0%;
-}
-
-.textLayer .highlight {
- margin: -1px;
- padding: 1px;
-
- background-color: rgb(180, 0, 170);
- border-radius: 4px;
-}
-
-.textLayer .highlight.begin {
- border-radius: 4px 0px 0px 4px;
-}
-
-.textLayer .highlight.end {
- border-radius: 0px 4px 4px 0px;
-}
-
-.textLayer .highlight.middle {
- border-radius: 0px;
-}
-
-.textLayer .highlight.selected {
- background-color: rgb(0, 100, 0);
-}
-
-.textLayer ::selection { background: rgb(0,0,255); }
-.textLayer ::-moz-selection { background: rgb(0,0,255); }
-
-.textLayer .endOfContent {
- display: block;
- position: absolute;
- left: 0px;
- top: 100%;
- right: 0px;
- bottom: 0px;
- z-index: -1;
- cursor: default;
- -moz-user-select: none;
-}
-
-.textLayer .endOfContent.active {
- top: 0px;
-}
-
-
-.annotationLayer section {
- position: absolute;
-}
-
-.annotationLayer .linkAnnotation > a {
- position: absolute;
- font-size: 1em;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
-}
-
-.annotationLayer .linkAnnotation > a:hover {
- opacity: 0.2;
- background: #ff0;
- box-shadow: 0px 2px 10px #ff0;
-}
-
-.annotationLayer .textAnnotation img {
- position: absolute;
- cursor: pointer;
-}
-
-.annotationLayer .textWidgetAnnotation input,
-.annotationLayer .textWidgetAnnotation textarea,
-.annotationLayer .choiceWidgetAnnotation select {
- background-color: rgba(0, 54, 255, 0.13);
- border: 1px solid transparent;
- box-sizing: border-box;
- font-size: 9px;
- height: 100%;
- padding: 0 3px;
- vertical-align: top;
- width: 100%;
-}
-
-.annotationLayer .textWidgetAnnotation textarea {
- font: message-box;
- font-size: 9px;
- resize: none;
-}
-
-.annotationLayer .textWidgetAnnotation input[disabled],
-.annotationLayer .textWidgetAnnotation textarea[disabled],
-.annotationLayer .choiceWidgetAnnotation select[disabled] {
- background: none;
- border: 1px solid transparent;
- cursor: not-allowed;
-}
-
-.annotationLayer .textWidgetAnnotation input:hover,
-.annotationLayer .textWidgetAnnotation textarea:hover,
-.annotationLayer .choiceWidgetAnnotation select:hover {
- border: 1px solid #000;
-}
-
-.annotationLayer .textWidgetAnnotation input:focus,
-.annotationLayer .textWidgetAnnotation textarea:focus,
-.annotationLayer .choiceWidgetAnnotation select:focus {
- background: none;
- border: 1px solid transparent;
-}
-
-.annotationLayer .textWidgetAnnotation input.comb {
- font-family: monospace;
- padding-left: 2px;
- padding-right: 0;
-}
-
-.annotationLayer .textWidgetAnnotation input.comb:focus {
- /*
- * Letter spacing is placed on the right side of each character. Hence, the
- * letter spacing of the last character may be placed outside the visible
- * area, causing horizontal scrolling. We avoid this by extending the width
- * when the element has focus and revert this when it loses focus.
- */
- width: 115%;
-}
-
-.annotationLayer .popupWrapper {
- position: absolute;
- width: 20em;
-}
-
-.annotationLayer .popup {
- position: absolute;
- z-index: 200;
- max-width: 20em;
- background-color: #FFFF99;
- box-shadow: 0px 2px 5px #333;
- border-radius: 2px;
- padding: 0.6em;
- margin-left: 5px;
- cursor: pointer;
- word-wrap: break-word;
-}
-
-.annotationLayer .popup h1 {
- font-size: 1em;
- border-bottom: 1px solid #000000;
- padding-bottom: 0.2em;
-}
-
-.annotationLayer .popup p {
- padding-top: 0.2em;
-}
-
-.annotationLayer .highlightAnnotation,
-.annotationLayer .underlineAnnotation,
-.annotationLayer .squigglyAnnotation,
-.annotationLayer .strikeoutAnnotation,
-.annotationLayer .fileAttachmentAnnotation {
- cursor: pointer;
-}
-
-.pdfViewer .canvasWrapper {
- overflow: hidden;
-}
-
-.pdfViewer .page {
- direction: ltr;
- width: 816px;
- height: 1056px;
- margin: 1px auto -8px auto;
- position: relative;
- overflow: visible;
- border: 9px solid transparent;
- background-clip: content-box;
- border-image: url(images/shadow.png) 9 9 repeat;
- background-color: white;
-}
-
-.pdfViewer.removePageBorders .page {
- margin: 0px auto 10px auto;
- border: none;
-}
-
-.pdfViewer.singlePageView {
- display: inline-block;
-}
-
-.pdfViewer.singlePageView .page {
- margin: 0;
- border: none;
-}
-
-.pdfViewer .page canvas {
- margin: 0;
- display: block;
-}
-
-.pdfViewer .page .loadingIcon {
- position: absolute;
- display: block;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- background: url('images/loading-icon.gif') center no-repeat;
-}
-
-.pdfPresentationMode:-moz-full-screen .pdfViewer .page {
- margin-bottom: 100%;
- border: 0;
-}
-
-.pdfPresentationMode:fullscreen .pdfViewer .page {
- margin-bottom: 100%;
- border: 0;
-}
-
-* {
- padding: 0;
- margin: 0;
-}
-
-html {
- height: 100%;
- width: 100%;
- /* Font size is needed to make the activity bar the correct size. */
- font-size: 10px;
-}
-
-body {
- height: 100%;
- width: 100%;
- background-color: #404040;
- background-image: url(images/texture.png);
-}
-
-body,
-input,
-button,
-select {
- font: message-box;
- outline: none;
-}
-
-.hidden {
- display: none !important;
-}
-[hidden] {
- display: none !important;
-}
-
-#viewerContainer.pdfPresentationMode:-moz-full-screen {
- top: 0px;
- border-top: 2px solid transparent;
- background-color: #000;
- width: 100%;
- height: 100%;
- overflow: hidden;
- cursor: none;
- -moz-user-select: none;
-}
-
-#viewerContainer.pdfPresentationMode:fullscreen {
- top: 0px;
- border-top: 2px solid transparent;
- background-color: #000;
- width: 100%;
- height: 100%;
- overflow: hidden;
- cursor: none;
- -moz-user-select: none;
-}
-
-.pdfPresentationMode:-moz-full-screen a:not(.internalLink) {
- display: none;
-}
-
-.pdfPresentationMode:fullscreen a:not(.internalLink) {
- display: none;
-}
-
-.pdfPresentationMode:-moz-full-screen .textLayer > div {
- cursor: none;
-}
-
-.pdfPresentationMode:fullscreen .textLayer > div {
- cursor: none;
-}
-
-.pdfPresentationMode.pdfPresentationModeControls > *,
-.pdfPresentationMode.pdfPresentationModeControls .textLayer > div {
- cursor: default;
-}
-
-#outerContainer {
- width: 100%;
- height: 100%;
- position: relative;
-}
-
-#sidebarContainer {
- position: absolute;
- top: 0;
- bottom: 0;
- width: 200px;
- visibility: hidden;
- transition-duration: 200ms;
- transition-timing-function: ease;
-
-}
-html[dir='ltr'] #sidebarContainer {
- transition-property: left;
- left: -200px;
-}
-html[dir='rtl'] #sidebarContainer {
- transition-property: right;
- right: -200px;
-}
-
-#outerContainer.sidebarMoving > #sidebarContainer,
-#outerContainer.sidebarOpen > #sidebarContainer {
- visibility: visible;
-}
-html[dir='ltr'] #outerContainer.sidebarOpen > #sidebarContainer {
- left: 0px;
-}
-html[dir='rtl'] #outerContainer.sidebarOpen > #sidebarContainer {
- right: 0px;
-}
-
-#mainContainer {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- min-width: 320px;
- transition-duration: 200ms;
- transition-timing-function: ease;
-}
-html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer {
- transition-property: left;
- left: 200px;
-}
-html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer {
- transition-property: right;
- right: 200px;
-}
-
-#sidebarContent {
- top: 32px;
- bottom: 0;
- overflow: auto;
- position: absolute;
- width: 200px;
- background-color: hsla(0,0%,0%,.1);
-}
-html[dir='ltr'] #sidebarContent {
- left: 0;
- box-shadow: inset -1px 0 0 hsla(0,0%,0%,.25);
-}
-html[dir='rtl'] #sidebarContent {
- right: 0;
- box-shadow: inset 1px 0 0 hsla(0,0%,0%,.25);
-}
-
-#viewerContainer {
- overflow: auto;
- position: absolute;
- top: 32px;
- right: 0;
- bottom: 0;
- left: 0;
- outline: none;
-}
-html[dir='ltr'] #viewerContainer {
- box-shadow: inset 1px 0 0 hsla(0,0%,100%,.05);
-}
-html[dir='rtl'] #viewerContainer {
- box-shadow: inset -1px 0 0 hsla(0,0%,100%,.05);
-}
-
-.toolbar {
- position: relative;
- left: 0;
- right: 0;
- z-index: 9999;
- cursor: default;
-}
-
-#toolbarContainer {
- width: 100%;
-}
-
-#toolbarSidebar {
- width: 200px;
- height: 32px;
- background-color: #424242; /* fallback */
- background-image: url(images/texture.png),
- linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
-}
-html[dir='ltr'] #toolbarSidebar {
- box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.25),
- inset 0 -1px 0 hsla(0,0%,100%,.05),
- 0 1px 0 hsla(0,0%,0%,.15),
- 0 0 1px hsla(0,0%,0%,.1);
-}
-html[dir='rtl'] #toolbarSidebar {
- box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.25),
- inset 0 1px 0 hsla(0,0%,100%,.05),
- 0 1px 0 hsla(0,0%,0%,.15),
- 0 0 1px hsla(0,0%,0%,.1);
-}
-
-#toolbarContainer, .findbar, .secondaryToolbar {
- position: relative;
- height: 32px;
- background-color: #474747; /* fallback */
- background-image: url(images/texture.png),
- linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
-}
-html[dir='ltr'] #toolbarContainer, .findbar, .secondaryToolbar {
- box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08),
- inset 0 1px 1px hsla(0,0%,0%,.15),
- inset 0 -1px 0 hsla(0,0%,100%,.05),
- 0 1px 0 hsla(0,0%,0%,.15),
- 0 1px 1px hsla(0,0%,0%,.1);
-}
-html[dir='rtl'] #toolbarContainer, .findbar, .secondaryToolbar {
- box-shadow: inset -1px 0 0 hsla(0,0%,100%,.08),
- inset 0 1px 1px hsla(0,0%,0%,.15),
- inset 0 -1px 0 hsla(0,0%,100%,.05),
- 0 1px 0 hsla(0,0%,0%,.15),
- 0 1px 1px hsla(0,0%,0%,.1);
-}
-
-#toolbarViewer {
- height: 32px;
-}
-
-#loadingBar {
- position: relative;
- width: 100%;
- height: 4px;
- background-color: #333;
- border-bottom: 1px solid #333;
-}
-
-#loadingBar .progress {
- position: absolute;
- top: 0;
- left: 0;
- width: 0%;
- height: 100%;
- background-color: #ddd;
- overflow: hidden;
- transition: width 200ms;
-}
-
-@keyframes progressIndeterminate {
- 0% { left: -142px; }
- 100% { left: 0; }
-}
-
-#loadingBar .progress.indeterminate {
- background-color: #999;
- transition: none;
-}
-
-#loadingBar .progress.indeterminate .glimmer {
- position: absolute;
- top: 0;
- left: 0;
- height: 100%;
- width: calc(100% + 150px);
-
- background: repeating-linear-gradient(135deg,
- #bbb 0, #999 5px,
- #999 45px, #ddd 55px,
- #ddd 95px, #bbb 100px);
-
- animation: progressIndeterminate 950ms linear infinite;
-}
-
-.findbar, .secondaryToolbar {
- top: 32px;
- position: absolute;
- z-index: 10000;
- height: 32px;
-
- min-width: 16px;
- padding: 0px 6px 0px 6px;
- margin: 4px 2px 4px 2px;
- color: hsl(0,0%,85%);
- font-size: 12px;
- line-height: 14px;
- text-align: left;
- cursor: default;
-}
-
-html[dir='ltr'] .findbar {
- left: 68px;
-}
-
-html[dir='rtl'] .findbar {
- right: 68px;
-}
-
-.findbar label {
- -moz-user-select: none;
-}
-
-#findInput[data-status="pending"] {
- background-image: url(images/loading-small.png);
- background-repeat: no-repeat;
- background-position: right;
-}
-html[dir='rtl'] #findInput[data-status="pending"] {
- background-position: left;
-}
-
-.secondaryToolbar {
- padding: 6px;
- height: auto;
- z-index: 30000;
-}
-html[dir='ltr'] .secondaryToolbar {
- right: 4px;
-}
-html[dir='rtl'] .secondaryToolbar {
- left: 4px;
-}
-
-#secondaryToolbarButtonContainer {
- max-width: 200px;
- max-height: 400px;
- overflow-y: auto;
- margin-bottom: -4px;
-}
-
-.doorHanger,
-.doorHangerRight {
- border: 1px solid hsla(0,0%,0%,.5);
- border-radius: 2px;
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
-}
-.doorHanger:after, .doorHanger:before,
-.doorHangerRight:after, .doorHangerRight:before {
- bottom: 100%;
- border: solid transparent;
- content: " ";
- height: 0;
- width: 0;
- position: absolute;
- pointer-events: none;
-}
-.doorHanger:after,
-.doorHangerRight:after {
- border-bottom-color: hsla(0,0%,32%,.99);
- border-width: 8px;
-}
-.doorHanger:before,
-.doorHangerRight:before {
- border-bottom-color: hsla(0,0%,0%,.5);
- border-width: 9px;
-}
-
-html[dir='ltr'] .doorHanger:after,
-html[dir='rtl'] .doorHangerRight:after {
- left: 13px;
- margin-left: -8px;
-}
-
-html[dir='ltr'] .doorHanger:before,
-html[dir='rtl'] .doorHangerRight:before {
- left: 13px;
- margin-left: -9px;
-}
-
-html[dir='rtl'] .doorHanger:after,
-html[dir='ltr'] .doorHangerRight:after {
- right: 13px;
- margin-right: -8px;
-}
-
-html[dir='rtl'] .doorHanger:before,
-html[dir='ltr'] .doorHangerRight:before {
- right: 13px;
- margin-right: -9px;
-}
-
-#findResultsCount {
- background-color: hsl(0, 0%, 85%);
- color: hsl(0, 0%, 32%);
- text-align: center;
- padding: 3px 4px;
-}
-
-#findMsg {
- font-style: italic;
- color: #A6B7D0;
-}
-
-#findInput.notFound {
- background-color: rgb(255, 102, 102);
-}
-
-#toolbarViewerMiddle {
- position: absolute;
- left: 50%;
- transform: translateX(-50%);
-}
-
-html[dir='ltr'] #toolbarViewerLeft,
-html[dir='rtl'] #toolbarViewerRight {
- float: left;
-}
-html[dir='ltr'] #toolbarViewerRight,
-html[dir='rtl'] #toolbarViewerLeft {
- float: right;
-}
-html[dir='ltr'] #toolbarViewerLeft > *,
-html[dir='ltr'] #toolbarViewerMiddle > *,
-html[dir='ltr'] #toolbarViewerRight > *,
-html[dir='ltr'] .findbar > * {
- position: relative;
- float: left;
-}
-html[dir='rtl'] #toolbarViewerLeft > *,
-html[dir='rtl'] #toolbarViewerMiddle > *,
-html[dir='rtl'] #toolbarViewerRight > *,
-html[dir='rtl'] .findbar > * {
- position: relative;
- float: right;
-}
-
-html[dir='ltr'] .splitToolbarButton {
- margin: 3px 2px 4px 0;
- display: inline-block;
-}
-html[dir='rtl'] .splitToolbarButton {
- margin: 3px 0 4px 2px;
- display: inline-block;
-}
-html[dir='ltr'] .splitToolbarButton > .toolbarButton {
- border-radius: 0;
- float: left;
-}
-html[dir='rtl'] .splitToolbarButton > .toolbarButton {
- border-radius: 0;
- float: right;
-}
-
-.toolbarButton,
-.secondaryToolbarButton,
-.overlayButton {
- border: 0 none;
- background: none;
- width: 32px;
- height: 25px;
-}
-
-.toolbarButton > span {
- display: inline-block;
- width: 0;
- height: 0;
- overflow: hidden;
-}
-
-.toolbarButton[disabled],
-.secondaryToolbarButton[disabled],
-.overlayButton[disabled] {
- opacity: .5;
-}
-
-.toolbarButton.group {
- margin-right: 0;
-}
-
-.splitToolbarButton.toggled .toolbarButton {
- margin: 0;
-}
-
-.splitToolbarButton:hover > .toolbarButton,
-.splitToolbarButton:focus > .toolbarButton,
-.splitToolbarButton.toggled > .toolbarButton,
-.toolbarButton.textButton {
- background-color: hsla(0,0%,0%,.12);
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- border: 1px solid hsla(0,0%,0%,.35);
- border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.15) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
- transition-timing-function: ease;
-
-}
-.splitToolbarButton > .toolbarButton:hover,
-.splitToolbarButton > .toolbarButton:focus,
-.dropdownToolbarButton:hover,
-.overlayButton:hover,
-.overlayButton:focus,
-.toolbarButton.textButton:hover,
-.toolbarButton.textButton:focus {
- background-color: hsla(0,0%,0%,.2);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.15) inset,
- 0 0 1px hsla(0,0%,0%,.05);
- z-index: 199;
-}
-.splitToolbarButton > .toolbarButton {
- position: relative;
-}
-html[dir='ltr'] .splitToolbarButton > .toolbarButton:first-child,
-html[dir='rtl'] .splitToolbarButton > .toolbarButton:last-child {
- position: relative;
- margin: 0;
- margin-right: -1px;
- border-top-left-radius: 2px;
- border-bottom-left-radius: 2px;
- border-right-color: transparent;
-}
-html[dir='ltr'] .splitToolbarButton > .toolbarButton:last-child,
-html[dir='rtl'] .splitToolbarButton > .toolbarButton:first-child {
- position: relative;
- margin: 0;
- margin-left: -1px;
- border-top-right-radius: 2px;
- border-bottom-right-radius: 2px;
- border-left-color: transparent;
-}
-.splitToolbarButtonSeparator {
- padding: 8px 0;
- width: 1px;
- background-color: hsla(0,0%,0%,.5);
- z-index: 99;
- box-shadow: 0 0 0 1px hsla(0,0%,100%,.08);
- display: inline-block;
- margin: 5px 0;
-}
-html[dir='ltr'] .splitToolbarButtonSeparator {
- float: left;
-}
-html[dir='rtl'] .splitToolbarButtonSeparator {
- float: right;
-}
-.splitToolbarButton:hover > .splitToolbarButtonSeparator,
-.splitToolbarButton.toggled > .splitToolbarButtonSeparator {
- padding: 12px 0;
- margin: 1px 0;
- box-shadow: 0 0 0 1px hsla(0,0%,100%,.03);
- transition-property: padding;
- transition-duration: 10ms;
- transition-timing-function: ease;
-}
-
-.toolbarButton,
-.dropdownToolbarButton,
-.secondaryToolbarButton,
-.overlayButton {
- min-width: 16px;
- padding: 2px 6px 0;
- border: 1px solid transparent;
- border-radius: 2px;
- color: hsla(0,0%,100%,.8);
- font-size: 12px;
- line-height: 14px;
- -moz-user-select: none;
- /* Opera does not support user-select, use <... unselectable="on"> instead */
- cursor: default;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
- transition-timing-function: ease;
-}
-
-html[dir='ltr'] .toolbarButton,
-html[dir='ltr'] .overlayButton,
-html[dir='ltr'] .dropdownToolbarButton {
- margin: 3px 2px 4px 0;
-}
-html[dir='rtl'] .toolbarButton,
-html[dir='rtl'] .overlayButton,
-html[dir='rtl'] .dropdownToolbarButton {
- margin: 3px 0 4px 2px;
-}
-
-.toolbarButton:hover,
-.toolbarButton:focus,
-.dropdownToolbarButton,
-.overlayButton,
-.secondaryToolbarButton:hover,
-.secondaryToolbarButton:focus {
- background-color: hsla(0,0%,0%,.12);
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- border: 1px solid hsla(0,0%,0%,.35);
- border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.15) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
-}
-
-.toolbarButton:hover:active,
-.overlayButton:hover:active,
-.dropdownToolbarButton:hover:active,
-.secondaryToolbarButton:hover:active {
- background-color: hsla(0,0%,0%,.2);
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.4) hsla(0,0%,0%,.45);
- box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
- 0 0 1px hsla(0,0%,0%,.2) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 10ms;
- transition-timing-function: linear;
-}
-
-.toolbarButton.toggled,
-.splitToolbarButton.toggled > .toolbarButton.toggled,
-.secondaryToolbarButton.toggled {
- background-color: hsla(0,0%,0%,.3);
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.45) hsla(0,0%,0%,.5);
- box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
- 0 0 1px hsla(0,0%,0%,.2) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 10ms;
- transition-timing-function: linear;
-}
-
-.toolbarButton.toggled:hover:active,
-.splitToolbarButton.toggled > .toolbarButton.toggled:hover:active,
-.secondaryToolbarButton.toggled:hover:active {
- background-color: hsla(0,0%,0%,.4);
- border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.5) hsla(0,0%,0%,.55);
- box-shadow: 0 1px 1px hsla(0,0%,0%,.2) inset,
- 0 0 1px hsla(0,0%,0%,.3) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
-}
-
-.dropdownToolbarButton {
- width: 120px;
- max-width: 120px;
- padding: 0;
- overflow: hidden;
- background: url(images/toolbarButton-menuArrows.png) no-repeat;
-}
-html[dir='ltr'] .dropdownToolbarButton {
- background-position: 95%;
-}
-html[dir='rtl'] .dropdownToolbarButton {
- background-position: 5%;
-}
-
-.dropdownToolbarButton > select {
- min-width: 140px;
- font-size: 12px;
- color: hsl(0,0%,95%);
- margin: 0;
- padding: 3px 2px 2px;
- border: none;
- background: rgba(0,0,0,0); /* Opera does not support 'transparent' <select> background */
-}
-
-.dropdownToolbarButton > select > option {
- background: hsl(0,0%,24%);
-}
-
-#customScaleOption {
- display: none;
-}
-
-#pageWidthOption {
- border-bottom: 1px rgba(255, 255, 255, .5) solid;
-}
-
-html[dir='ltr'] .splitToolbarButton:first-child,
-html[dir='ltr'] .toolbarButton:first-child,
-html[dir='rtl'] .splitToolbarButton:last-child,
-html[dir='rtl'] .toolbarButton:last-child {
- margin-left: 4px;
-}
-html[dir='ltr'] .splitToolbarButton:last-child,
-html[dir='ltr'] .toolbarButton:last-child,
-html[dir='rtl'] .splitToolbarButton:first-child,
-html[dir='rtl'] .toolbarButton:first-child {
- margin-right: 4px;
-}
-
-.toolbarButtonSpacer {
- width: 30px;
- display: inline-block;
- height: 1px;
-}
-
-.toolbarButtonFlexibleSpacer {
- -moz-box-flex: 1;
- min-width: 30px;
-}
-
-html[dir='ltr'] #findPrevious {
- margin-left: 3px;
-}
-html[dir='ltr'] #findNext {
- margin-right: 3px;
-}
-
-html[dir='rtl'] #findPrevious {
- margin-right: 3px;
-}
-html[dir='rtl'] #findNext {
- margin-left: 3px;
-}
-
-.toolbarButton::before,
-.secondaryToolbarButton::before {
- /* All matching images have a size of 16x16
- * All relevant containers have a size of 32x25 */
- position: absolute;
- display: inline-block;
- top: 4px;
- left: 7px;
-}
-
-html[dir="ltr"] .secondaryToolbarButton::before {
- left: 4px;
-}
-html[dir="rtl"] .secondaryToolbarButton::before {
- right: 4px;
-}
-
-html[dir='ltr'] .toolbarButton#sidebarToggle::before {
- content: url(images/toolbarButton-sidebarToggle.png);
-}
-html[dir='rtl'] .toolbarButton#sidebarToggle::before {
- content: url(images/toolbarButton-sidebarToggle-rtl.png);
-}
-
-html[dir='ltr'] .toolbarButton#secondaryToolbarToggle::before {
- content: url(images/toolbarButton-secondaryToolbarToggle.png);
-}
-html[dir='rtl'] .toolbarButton#secondaryToolbarToggle::before {
- content: url(images/toolbarButton-secondaryToolbarToggle-rtl.png);
-}
-
-html[dir='ltr'] .toolbarButton.findPrevious::before {
- content: url(images/findbarButton-previous.png);
-}
-html[dir='rtl'] .toolbarButton.findPrevious::before {
- content: url(images/findbarButton-previous-rtl.png);
-}
-
-html[dir='ltr'] .toolbarButton.findNext::before {
- content: url(images/findbarButton-next.png);
-}
-html[dir='rtl'] .toolbarButton.findNext::before {
- content: url(images/findbarButton-next-rtl.png);
-}
-
-html[dir='ltr'] .toolbarButton.pageUp::before {
- content: url(images/toolbarButton-pageUp.png);
-}
-html[dir='rtl'] .toolbarButton.pageUp::before {
- content: url(images/toolbarButton-pageUp-rtl.png);
-}
-
-html[dir='ltr'] .toolbarButton.pageDown::before {
- content: url(images/toolbarButton-pageDown.png);
-}
-html[dir='rtl'] .toolbarButton.pageDown::before {
- content: url(images/toolbarButton-pageDown-rtl.png);
-}
-
-.toolbarButton.zoomOut::before {
- content: url(images/toolbarButton-zoomOut.png);
-}
-
-.toolbarButton.zoomIn::before {
- content: url(images/toolbarButton-zoomIn.png);
-}
-
-.toolbarButton.presentationMode::before,
-.secondaryToolbarButton.presentationMode::before {
- content: url(images/toolbarButton-presentationMode.png);
-}
-
-.toolbarButton.print::before,
-.secondaryToolbarButton.print::before {
- content: url(images/toolbarButton-print.png);
-}
-
-.toolbarButton.openFile::before,
-.secondaryToolbarButton.openFile::before {
- content: url(images/toolbarButton-openFile.png);
-}
-
-.toolbarButton.download::before,
-.secondaryToolbarButton.download::before {
- content: url(images/toolbarButton-download.png);
-}
-
-.toolbarButton.bookmark,
-.secondaryToolbarButton.bookmark {
- box-sizing: border-box;
- outline: none;
- padding-top: 4px;
- text-decoration: none;
-}
-.secondaryToolbarButton.bookmark {
- padding-top: 5px;
-}
-
-.bookmark[href='#'] {
- opacity: .5;
- pointer-events: none;
-}
-
-.toolbarButton.bookmark::before,
-.secondaryToolbarButton.bookmark::before {
- content: url(images/toolbarButton-bookmark.png);
-}
-
-#viewThumbnail.toolbarButton::before {
- content: url(images/toolbarButton-viewThumbnail.png);
-}
-
-html[dir="ltr"] #viewOutline.toolbarButton::before {
- content: url(images/toolbarButton-viewOutline.png);
-}
-html[dir="rtl"] #viewOutline.toolbarButton::before {
- content: url(images/toolbarButton-viewOutline-rtl.png);
-}
-
-#viewAttachments.toolbarButton::before {
- content: url(images/toolbarButton-viewAttachments.png);
-}
-
-#viewFind.toolbarButton::before {
- content: url(images/toolbarButton-search.png);
-}
-
-.secondaryToolbarButton {
- position: relative;
- margin: 0 0 4px 0;
- padding: 3px 0 1px 0;
- height: auto;
- min-height: 25px;
- width: auto;
- min-width: 100%;
- white-space: normal;
-}
-html[dir="ltr"] .secondaryToolbarButton {
- padding-left: 24px;
- text-align: left;
-}
-html[dir="rtl"] .secondaryToolbarButton {
- padding-right: 24px;
- text-align: right;
-}
-html[dir="ltr"] .secondaryToolbarButton.bookmark {
- padding-left: 27px;
-}
-html[dir="rtl"] .secondaryToolbarButton.bookmark {
- padding-right: 27px;
-}
-
-html[dir="ltr"] .secondaryToolbarButton > span {
- padding-right: 4px;
-}
-html[dir="rtl"] .secondaryToolbarButton > span {
- padding-left: 4px;
-}
-
-.secondaryToolbarButton.firstPage::before {
- content: url(images/secondaryToolbarButton-firstPage.png);
-}
-
-.secondaryToolbarButton.lastPage::before {
- content: url(images/secondaryToolbarButton-lastPage.png);
-}
-
-.secondaryToolbarButton.rotateCcw::before {
- content: url(images/secondaryToolbarButton-rotateCcw.png);
-}
-
-.secondaryToolbarButton.rotateCw::before {
- content: url(images/secondaryToolbarButton-rotateCw.png);
-}
-
-.secondaryToolbarButton.handTool::before {
- content: url(images/secondaryToolbarButton-handTool.png);
-}
-
-.secondaryToolbarButton.documentProperties::before {
- content: url(images/secondaryToolbarButton-documentProperties.png);
-}
-
-.verticalToolbarSeparator {
- display: block;
- padding: 8px 0;
- margin: 8px 4px;
- width: 1px;
- background-color: hsla(0,0%,0%,.5);
- box-shadow: 0 0 0 1px hsla(0,0%,100%,.08);
-}
-html[dir='ltr'] .verticalToolbarSeparator {
- margin-left: 2px;
-}
-html[dir='rtl'] .verticalToolbarSeparator {
- margin-right: 2px;
-}
-
-.horizontalToolbarSeparator {
- display: block;
- margin: 0 0 4px 0;
- height: 1px;
- width: 100%;
- background-color: hsla(0,0%,0%,.5);
- box-shadow: 0 0 0 1px hsla(0,0%,100%,.08);
-}
-
-.toolbarField {
- padding: 3px 6px;
- margin: 4px 0 4px 0;
- border: 1px solid transparent;
- border-radius: 2px;
- background-color: hsla(0,0%,100%,.09);
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- border: 1px solid hsla(0,0%,0%,.35);
- border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
- box-shadow: 0 1px 0 hsla(0,0%,0%,.05) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
- color: hsl(0,0%,95%);
- font-size: 12px;
- line-height: 14px;
- outline-style: none;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
- transition-timing-function: ease;
-}
-
-.toolbarField[type=checkbox] {
- display: inline-block;
- margin: 8px 0px;
-}
-
-.toolbarField.pageNumber {
- -moz-appearance: textfield; /* hides the spinner in moz */
- min-width: 16px;
- text-align: right;
- width: 40px;
-}
-
-.toolbarField.pageNumber.visiblePageIsLoading {
- background-image: url(images/loading-small.png);
- background-repeat: no-repeat;
- background-position: 1px;
-}
-
-.toolbarField:hover {
- background-color: hsla(0,0%,100%,.11);
- border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.43) hsla(0,0%,0%,.45);
-}
-
-.toolbarField:focus {
- background-color: hsla(0,0%,100%,.15);
- border-color: hsla(204,100%,65%,.8) hsla(204,100%,65%,.85) hsla(204,100%,65%,.9);
-}
-
-.toolbarLabel {
- min-width: 16px;
- padding: 3px 6px 3px 2px;
- margin: 4px 2px 4px 0;
- border: 1px solid transparent;
- border-radius: 2px;
- color: hsl(0,0%,85%);
- font-size: 12px;
- line-height: 14px;
- text-align: left;
- -moz-user-select: none;
- cursor: default;
-}
-
-#thumbnailView {
- position: absolute;
- width: 120px;
- top: 0;
- bottom: 0;
- padding: 10px 40px 0;
- overflow: auto;
-}
-
-.thumbnail {
- float: left;
- margin-bottom: 5px;
-}
-
-#thumbnailView > a:last-of-type > .thumbnail {
- margin-bottom: 10px;
-}
-
-#thumbnailView > a:last-of-type > .thumbnail:not([data-loaded]) {
- margin-bottom: 9px;
-}
-
-.thumbnail:not([data-loaded]) {
- border: 1px dashed rgba(255, 255, 255, 0.5);
- margin: -1px -1px 4px -1px;
-}
-
-.thumbnailImage {
- border: 1px solid transparent;
- box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);
- opacity: 0.8;
- z-index: 99;
- background-color: white;
- background-clip: content-box;
-}
-
-.thumbnailSelectionRing {
- border-radius: 2px;
- padding: 7px;
-}
-
-a:focus > .thumbnail > .thumbnailSelectionRing > .thumbnailImage,
-.thumbnail:hover > .thumbnailSelectionRing > .thumbnailImage {
- opacity: .9;
-}
-
-a:focus > .thumbnail > .thumbnailSelectionRing,
-.thumbnail:hover > .thumbnailSelectionRing {
- background-color: hsla(0,0%,100%,.15);
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.2) inset,
- 0 0 1px hsla(0,0%,0%,.2);
- color: hsla(0,0%,100%,.9);
-}
-
-.thumbnail.selected > .thumbnailSelectionRing > .thumbnailImage {
- box-shadow: 0 0 0 1px hsla(0,0%,0%,.5);
- opacity: 1;
-}
-
-.thumbnail.selected > .thumbnailSelectionRing {
- background-color: hsla(0,0%,100%,.3);
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.1) inset,
- 0 0 1px hsla(0,0%,0%,.2);
- color: hsla(0,0%,100%,1);
-}
-
-#outlineView,
-#attachmentsView {
- position: absolute;
- width: 192px;
- top: 0;
- bottom: 0;
- overflow: auto;
- -moz-user-select: none;
-}
-
-#outlineView {
- padding: 4px 4px 0;
-}
-#attachmentsView {
- padding: 3px 4px 0;
-}
-
-html[dir='ltr'] .outlineWithDeepNesting > .outlineItem,
-html[dir='ltr'] .outlineItem > .outlineItems {
- margin-left: 20px;
-}
-
-html[dir='rtl'] .outlineWithDeepNesting > .outlineItem,
-html[dir='rtl'] .outlineItem > .outlineItems {
- margin-right: 20px;
-}
-
-.outlineItem > a,
-.attachmentsItem > button {
- text-decoration: none;
- display: inline-block;
- min-width: 95%;
- min-width: calc(100% - 4px); /* Subtract the right padding (left, in RTL mode)
- of the container. */
- height: auto;
- margin-bottom: 1px;
- border-radius: 2px;
- color: hsla(0,0%,100%,.8);
- font-size: 13px;
- line-height: 15px;
- -moz-user-select: none;
- white-space: normal;
-}
-
-.attachmentsItem > button {
- border: 0 none;
- background: none;
- cursor: pointer;
- width: 100%;
-}
-
-html[dir='ltr'] .outlineItem > a {
- padding: 2px 0 5px 4px;
-}
-html[dir='ltr'] .attachmentsItem > button {
- padding: 2px 0 3px 7px;
- text-align: left;
-}
-
-html[dir='rtl'] .outlineItem > a {
- padding: 2px 4px 5px 0;
-}
-html[dir='rtl'] .attachmentsItem > button {
- padding: 2px 7px 3px 0;
- text-align: right;
-}
-
-.outlineItemToggler {
- position: relative;
- height: 0;
- width: 0;
- color: hsla(0,0%,100%,.5);
-}
-.outlineItemToggler::before {
- content: url(images/treeitem-expanded.png);
- display: inline-block;
- position: absolute;
-}
-html[dir='ltr'] .outlineItemToggler.outlineItemsHidden::before {
- content: url(images/treeitem-collapsed.png);
-}
-html[dir='rtl'] .outlineItemToggler.outlineItemsHidden::before {
- content: url(images/treeitem-collapsed-rtl.png);
-}
-.outlineItemToggler.outlineItemsHidden ~ .outlineItems {
- display: none;
-}
-html[dir='ltr'] .outlineItemToggler {
- float: left;
-}
-html[dir='rtl'] .outlineItemToggler {
- float: right;
-}
-html[dir='ltr'] .outlineItemToggler::before {
- right: 4px;
-}
-html[dir='rtl'] .outlineItemToggler::before {
- left: 4px;
-}
-
-.outlineItemToggler:hover,
-.outlineItemToggler:hover + a,
-.outlineItemToggler:hover ~ .outlineItems,
-.outlineItem > a:hover,
-.attachmentsItem > button:hover {
- background-color: hsla(0,0%,100%,.02);
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.2) inset,
- 0 0 1px hsla(0,0%,0%,.2);
- border-radius: 2px;
- color: hsla(0,0%,100%,.9);
-}
-
-.outlineItem.selected {
- background-color: hsla(0,0%,100%,.08);
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.1) inset,
- 0 0 1px hsla(0,0%,0%,.2);
- color: hsla(0,0%,100%,1);
-}
-
-.noResults {
- font-size: 12px;
- color: hsla(0,0%,100%,.8);
- font-style: italic;
- cursor: default;
-}
-
-/* TODO: file FF bug to support ::-moz-selection:window-inactive
- so we can override the opaque grey background when the window is inactive;
- see https://bugzilla.mozilla.org/show_bug.cgi?id=706209 */
-::selection { background: rgba(0,0,255,0.3); }
-::-moz-selection { background: rgba(0,0,255,0.3); }
-
-#errorWrapper {
- background: none repeat scroll 0 0 #FF5555;
- color: white;
- left: 0;
- position: absolute;
- right: 0;
- z-index: 1000;
- padding: 3px;
- font-size: 0.8em;
-}
-.loadingInProgress #errorWrapper {
- top: 37px;
-}
-
-#errorMessageLeft {
- float: left;
-}
-
-#errorMessageRight {
- float: right;
-}
-
-#errorMoreInfo {
- background-color: #FFFFFF;
- color: black;
- padding: 3px;
- margin: 3px;
- width: 98%;
-}
-
-.overlayButton {
- width: auto;
- margin: 3px 4px 2px 4px !important;
- padding: 2px 6px 3px 6px;
-}
-
-#overlayContainer {
- display: table;
- position: absolute;
- width: 100%;
- height: 100%;
- background-color: hsla(0,0%,0%,.2);
- z-index: 40000;
-}
-#overlayContainer > * {
- overflow: auto;
-}
-
-#overlayContainer > .container {
- display: table-cell;
- vertical-align: middle;
- text-align: center;
-}
-
-#overlayContainer > .container > .dialog {
- display: inline-block;
- padding: 15px;
- border-spacing: 4px;
- color: hsl(0,0%,85%);
- font-size: 12px;
- line-height: 14px;
- background-color: #474747; /* fallback */
- background-image: url(images/texture.png),
- linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
- box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08),
- inset 0 1px 1px hsla(0,0%,0%,.15),
- inset 0 -1px 0 hsla(0,0%,100%,.05),
- 0 1px 0 hsla(0,0%,0%,.15),
- 0 1px 1px hsla(0,0%,0%,.1);
- border: 1px solid hsla(0,0%,0%,.5);
- border-radius: 4px;
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
-}
-
-.dialog > .row {
- display: table-row;
-}
-
-.dialog > .row > * {
- display: table-cell;
-}
-
-.dialog .toolbarField {
- margin: 5px 0;
-}
-
-.dialog .separator {
- display: block;
- margin: 4px 0 4px 0;
- height: 1px;
- width: 100%;
- background-color: hsla(0,0%,0%,.5);
- box-shadow: 0 0 0 1px hsla(0,0%,100%,.08);
-}
-
-.dialog .buttonRow {
- text-align: center;
- vertical-align: middle;
-}
-
-.dialog :link {
- color: white;
-}
-
-#passwordOverlay > .dialog {
- text-align: center;
-}
-#passwordOverlay .toolbarField {
- width: 200px;
-}
-
-#documentPropertiesOverlay > .dialog {
- text-align: left;
-}
-#documentPropertiesOverlay .row > * {
- min-width: 100px;
-}
-html[dir='ltr'] #documentPropertiesOverlay .row > * {
- text-align: left;
-}
-html[dir='rtl'] #documentPropertiesOverlay .row > * {
- text-align: right;
-}
-#documentPropertiesOverlay .row > span {
- width: 125px;
- word-wrap: break-word;
-}
-#documentPropertiesOverlay .row > p {
- max-width: 225px;
- word-wrap: break-word;
-}
-#documentPropertiesOverlay .buttonRow {
- margin-top: 10px;
-}
-
-.clearBoth {
- clear: both;
-}
-
-.fileInput {
- background: white;
- color: black;
- margin-top: 5px;
- visibility: hidden;
- position: fixed;
- right: 0;
- top: 0;
-}
-
-#PDFBug {
- background: none repeat scroll 0 0 white;
- border: 1px solid #666666;
- position: fixed;
- top: 32px;
- right: 0;
- bottom: 0;
- font-size: 10px;
- padding: 0;
- width: 300px;
-}
-#PDFBug .controls {
- background:#EEEEEE;
- border-bottom: 1px solid #666666;
- padding: 3px;
-}
-#PDFBug .panels {
- bottom: 0;
- left: 0;
- overflow: auto;
- position: absolute;
- right: 0;
- top: 27px;
-}
-#PDFBug button.active {
- font-weight: bold;
-}
-.debuggerShowText {
- background: none repeat scroll 0 0 yellow;
- color: blue;
-}
-.debuggerHideText:hover {
- background: none repeat scroll 0 0 yellow;
-}
-#PDFBug .stats {
- font-family: courier;
- font-size: 10px;
- white-space: pre;
-}
-#PDFBug .stats .title {
- font-weight: bold;
-}
-#PDFBug table {
- font-size: 10px;
-}
-
-#viewer.textLayer-visible .textLayer {
- opacity: 1.0;
-}
-
-#viewer.textLayer-visible .canvasWrapper {
- background-color: rgb(128,255,128);
-}
-
-#viewer.textLayer-visible .canvasWrapper canvas {
- mix-blend-mode: screen;
-}
-
-#viewer.textLayer-visible .textLayer > div {
- background-color: rgba(255, 255, 0, 0.1);
- color: black;
- border: solid 1px rgba(255, 0, 0, 0.5);
- box-sizing: border-box;
-}
-
-#viewer.textLayer-hover .textLayer > div:hover {
- background-color: white;
- color: black;
-}
-
-#viewer.textLayer-shadow .textLayer > div {
- background-color: rgba(255,255,255, .6);
- color: black;
-}
-
-.grab-to-pan-grab {
- cursor: url("images/grab.cur"), move !important;
- cursor: grab !important;
-}
-.grab-to-pan-grab *:not(input):not(textarea):not(button):not(select):not(:link) {
- cursor: inherit !important;
-}
-.grab-to-pan-grab:active,
-.grab-to-pan-grabbing {
- cursor: url("images/grabbing.cur"), move !important;
- cursor: grabbing !important;
-
- position: fixed;
- background: transparent;
- display: block;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- overflow: hidden;
- z-index: 50000; /* should be higher than anything else in PDF.js! */
-}
-
-@page {
- margin: 0;
-}
-
-#printContainer {
- display: none;
-}
-
-@media screen and (min-resolution: 2dppx) {
- /* Rules for Retina screens */
- .toolbarButton::before {
- transform: scale(0.5);
- top: -5px;
- }
-
- .secondaryToolbarButton::before {
- transform: scale(0.5);
- top: -4px;
- }
-
- html[dir='ltr'] .toolbarButton::before,
- html[dir='rtl'] .toolbarButton::before {
- left: -1px;
- }
-
- html[dir='ltr'] .secondaryToolbarButton::before {
- left: -2px;
- }
- html[dir='rtl'] .secondaryToolbarButton::before {
- left: 186px;
- }
-
- .toolbarField.pageNumber.visiblePageIsLoading,
- #findInput[data-status="pending"] {
- background-image: url(images/loading-small@2x.png);
- background-size: 16px 17px;
- }
-
- .dropdownToolbarButton {
- background: url(images/toolbarButton-menuArrows@2x.png) no-repeat;
- background-size: 7px 16px;
- }
-
- html[dir='ltr'] .toolbarButton#sidebarToggle::before {
- content: url(images/toolbarButton-sidebarToggle@2x.png);
- }
- html[dir='rtl'] .toolbarButton#sidebarToggle::before {
- content: url(images/toolbarButton-sidebarToggle-rtl@2x.png);
- }
-
- html[dir='ltr'] .toolbarButton#secondaryToolbarToggle::before {
- content: url(images/toolbarButton-secondaryToolbarToggle@2x.png);
- }
- html[dir='rtl'] .toolbarButton#secondaryToolbarToggle::before {
- content: url(images/toolbarButton-secondaryToolbarToggle-rtl@2x.png);
- }
-
- html[dir='ltr'] .toolbarButton.findPrevious::before {
- content: url(images/findbarButton-previous@2x.png);
- }
- html[dir='rtl'] .toolbarButton.findPrevious::before {
- content: url(images/findbarButton-previous-rtl@2x.png);
- }
-
- html[dir='ltr'] .toolbarButton.findNext::before {
- content: url(images/findbarButton-next@2x.png);
- }
- html[dir='rtl'] .toolbarButton.findNext::before {
- content: url(images/findbarButton-next-rtl@2x.png);
- }
-
- html[dir='ltr'] .toolbarButton.pageUp::before {
- content: url(images/toolbarButton-pageUp@2x.png);
- }
- html[dir='rtl'] .toolbarButton.pageUp::before {
- content: url(images/toolbarButton-pageUp-rtl@2x.png);
- }
-
- html[dir='ltr'] .toolbarButton.pageDown::before {
- content: url(images/toolbarButton-pageDown@2x.png);
- }
- html[dir='rtl'] .toolbarButton.pageDown::before {
- content: url(images/toolbarButton-pageDown-rtl@2x.png);
- }
-
- .toolbarButton.zoomIn::before {
- content: url(images/toolbarButton-zoomIn@2x.png);
- }
-
- .toolbarButton.zoomOut::before {
- content: url(images/toolbarButton-zoomOut@2x.png);
- }
-
- .toolbarButton.presentationMode::before,
- .secondaryToolbarButton.presentationMode::before {
- content: url(images/toolbarButton-presentationMode@2x.png);
- }
-
- .toolbarButton.print::before,
- .secondaryToolbarButton.print::before {
- content: url(images/toolbarButton-print@2x.png);
- }
-
- .toolbarButton.openFile::before,
- .secondaryToolbarButton.openFile::before {
- content: url(images/toolbarButton-openFile@2x.png);
- }
-
- .toolbarButton.download::before,
- .secondaryToolbarButton.download::before {
- content: url(images/toolbarButton-download@2x.png);
- }
-
- .toolbarButton.bookmark::before,
- .secondaryToolbarButton.bookmark::before {
- content: url(images/toolbarButton-bookmark@2x.png);
- }
-
- #viewThumbnail.toolbarButton::before {
- content: url(images/toolbarButton-viewThumbnail@2x.png);
- }
-
- html[dir="ltr"] #viewOutline.toolbarButton::before {
- content: url(images/toolbarButton-viewOutline@2x.png);
- }
- html[dir="rtl"] #viewOutline.toolbarButton::before {
- content: url(images/toolbarButton-viewOutline-rtl@2x.png);
- }
-
- #viewAttachments.toolbarButton::before {
- content: url(images/toolbarButton-viewAttachments@2x.png);
- }
-
- #viewFind.toolbarButton::before {
- content: url(images/toolbarButton-search@2x.png);
- }
-
- .secondaryToolbarButton.firstPage::before {
- content: url(images/secondaryToolbarButton-firstPage@2x.png);
- }
-
- .secondaryToolbarButton.lastPage::before {
- content: url(images/secondaryToolbarButton-lastPage@2x.png);
- }
-
- .secondaryToolbarButton.rotateCcw::before {
- content: url(images/secondaryToolbarButton-rotateCcw@2x.png);
- }
-
- .secondaryToolbarButton.rotateCw::before {
- content: url(images/secondaryToolbarButton-rotateCw@2x.png);
- }
-
- .secondaryToolbarButton.handTool::before {
- content: url(images/secondaryToolbarButton-handTool@2x.png);
- }
-
- .secondaryToolbarButton.documentProperties::before {
- content: url(images/secondaryToolbarButton-documentProperties@2x.png);
- }
-
- .outlineItemToggler::before {
- transform: scale(0.5);
- top: -1px;
- content: url(images/treeitem-expanded@2x.png);
- }
- html[dir='ltr'] .outlineItemToggler.outlineItemsHidden::before {
- content: url(images/treeitem-collapsed@2x.png);
- }
- html[dir='rtl'] .outlineItemToggler.outlineItemsHidden::before {
- content: url(images/treeitem-collapsed-rtl@2x.png);
- }
- html[dir='ltr'] .outlineItemToggler::before {
- right: 0;
- }
- html[dir='rtl'] .outlineItemToggler::before {
- left: 0;
- }
-}
-
-@media print {
- /* General rules for printing. */
- body {
- background: transparent none;
- }
-
- /* Rules for browsers that don't support mozPrintCallback. */
- #sidebarContainer, #secondaryToolbar, .toolbar, #loadingBox, #errorWrapper, .textLayer {
- display: none;
- }
- #viewerContainer {
- overflow: visible;
- }
-
- #mainContainer, #viewerContainer, .page, .page canvas {
- position: static;
- padding: 0;
- margin: 0;
- }
-
- .page {
- float: left;
- display: none;
- border: none;
- box-shadow: none;
- background-clip: content-box;
- background-color: white;
- }
-
- .page[data-loaded] {
- display: block;
- }
-
- .fileInput {
- display: none;
- }
-
- /* Rules for browsers that support PDF.js printing */
- body[data-pdfjsprinting] #outerContainer {
- display: none;
- }
- body[data-pdfjsprinting] #printContainer {
- display: block;
- }
- #printContainer {
- height: 100%;
- }
- /* wrapper around (scaled) print canvas elements */
- #printContainer > div {
- position: relative;
- top: 0;
- left: 0;
- width: 1px;
- height: 1px;
- overflow: visible;
- page-break-after: always;
- page-break-inside: avoid;
- }
- #printContainer canvas,
- #printContainer img {
- display: block;
- }
-}
-
-.visibleLargeView,
-.visibleMediumView,
-.visibleSmallView {
- display: none;
-}
-
-@media all and (max-width: 1040px) {
- #outerContainer.sidebarMoving #toolbarViewerMiddle,
- #outerContainer.sidebarOpen #toolbarViewerMiddle {
- display: table;
- margin: auto;
- left: auto;
- position: inherit;
- transform: none;
- }
-}
-
-@media all and (max-width: 980px) {
- .sidebarMoving .hiddenLargeView,
- .sidebarOpen .hiddenLargeView {
- display: none;
- }
- .sidebarMoving .visibleLargeView,
- .sidebarOpen .visibleLargeView {
- display: inherit;
- }
-}
-
-@media all and (max-width: 900px) {
- #toolbarViewerMiddle {
- display: table;
- margin: auto;
- left: auto;
- position: inherit;
- transform: none;
- }
- .sidebarMoving .hiddenMediumView,
- .sidebarOpen .hiddenMediumView {
- display: none;
- }
- .sidebarMoving .visibleMediumView,
- .sidebarOpen .visibleMediumView {
- display: inherit;
- }
-}
-
-@media all and (max-width: 840px) {
- #sidebarContainer {
- top: 32px;
- z-index: 100;
- }
- .loadingInProgress #sidebarContainer {
- top: 37px;
- }
- #sidebarContent {
- top: 32px;
- background-color: hsla(0,0%,0%,.7);
- }
-
- html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer {
- left: 0px;
- }
- html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer {
- right: 0px;
- }
-
- #outerContainer .hiddenLargeView,
- #outerContainer .hiddenMediumView {
- display: inherit;
- }
- #outerContainer .visibleLargeView,
- #outerContainer .visibleMediumView {
- display: none;
- }
-}
-
-@media all and (max-width: 770px) {
- #outerContainer .hiddenLargeView {
- display: none;
- }
- #outerContainer .visibleLargeView {
- display: inherit;
- }
-}
-
-@media all and (max-width: 700px) {
- #outerContainer .hiddenMediumView {
- display: none;
- }
- #outerContainer .visibleMediumView {
- display: inherit;
- }
-}
-
-@media all and (max-width: 640px) {
- .hiddenSmallView {
- display: none;
- }
- .visibleSmallView {
- display: inherit;
- }
- .toolbarButtonSpacer {
- width: 0;
- }
-}
-
-@media all and (max-width: 535px) {
- #scaleSelectContainer {
- display: none;
- }
-}
diff --git a/extensions/pdfjs/content/web/viewer.html b/extensions/pdfjs/content/web/viewer.html
deleted file mode 100644
index 3a06aa7..0000000
--- a/extensions/pdfjs/content/web/viewer.html
+++ /dev/null
@@ -1,337 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright 2012 Mozilla Foundation
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-Adobe CMap resources are covered by their own copyright but the same license:
-
- Copyright 1990-2015 Adobe Systems Incorporated.
-
-See https://github.com/adobe-type-tools/cmap-resources
--->
-<html dir="ltr" mozdisallowselectionprint moznomarginboxes>
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
- <title>PDF.js viewer</title>
-
-<!-- This snippet is used in the Firefox extension (included from viewer.html) -->
-<base href="resource://pdf.js/web/">
-<script src="l10n.js"></script>
-<script src="../build/pdf.js"></script>
-
-
- <link rel="stylesheet" href="viewer.css">
-
-
-
-
-
-
- <script src="viewer.js"></script>
-
- </head>
-
- <body tabindex="1" class="loadingInProgress">
- <div id="outerContainer">
-
- <div id="sidebarContainer">
- <div id="toolbarSidebar">
- <div class="splitToolbarButton toggled">
- <button id="viewThumbnail" class="toolbarButton group toggled" title="Show Thumbnails" tabindex="2" data-l10n-id="thumbs">
- <span data-l10n-id="thumbs_label">Thumbnails</span>
- </button>
- <button id="viewOutline" class="toolbarButton group" title="Show Document Outline (double-click to expand/collapse all items)" tabindex="3" data-l10n-id="document_outline">
- <span data-l10n-id="document_outline_label">Document Outline</span>
- </button>
- <button id="viewAttachments" class="toolbarButton group" title="Show Attachments" tabindex="4" data-l10n-id="attachments">
- <span data-l10n-id="attachments_label">Attachments</span>
- </button>
- </div>
- </div>
- <div id="sidebarContent">
- <div id="thumbnailView">
- </div>
- <div id="outlineView" class="hidden">
- </div>
- <div id="attachmentsView" class="hidden">
- </div>
- </div>
- </div> <!-- sidebarContainer -->
-
- <div id="mainContainer">
- <div class="findbar hidden doorHanger hiddenSmallView" id="findbar">
- <label for="findInput" class="toolbarLabel" data-l10n-id="find_label">Find:</label>
- <input id="findInput" class="toolbarField" tabindex="91">
- <div class="splitToolbarButton">
- <button class="toolbarButton findPrevious" title="" id="findPrevious" tabindex="92" data-l10n-id="find_previous">
- <span data-l10n-id="find_previous_label">Previous</span>
- </button>
- <div class="splitToolbarButtonSeparator"></div>
- <button class="toolbarButton findNext" title="" id="findNext" tabindex="93" data-l10n-id="find_next">
- <span data-l10n-id="find_next_label">Next</span>
- </button>
- </div>
- <input type="checkbox" id="findHighlightAll" class="toolbarField" tabindex="94">
- <label for="findHighlightAll" class="toolbarLabel" data-l10n-id="find_highlight">Highlight all</label>
- <input type="checkbox" id="findMatchCase" class="toolbarField" tabindex="95">
- <label for="findMatchCase" class="toolbarLabel" data-l10n-id="find_match_case_label">Match case</label>
- <span id="findResultsCount" class="toolbarLabel hidden"></span>
- <span id="findMsg" class="toolbarLabel"></span>
- </div> <!-- findbar -->
-
- <div id="secondaryToolbar" class="secondaryToolbar hidden doorHangerRight">
- <div id="secondaryToolbarButtonContainer">
- <button id="secondaryPresentationMode" class="secondaryToolbarButton presentationMode visibleLargeView" title="Switch to Presentation Mode" tabindex="51" data-l10n-id="presentation_mode">
- <span data-l10n-id="presentation_mode_label">Presentation Mode</span>
- </button>
-
- <button id="secondaryOpenFile" class="secondaryToolbarButton openFile visibleLargeView" title="Open File" tabindex="52" data-l10n-id="open_file">
- <span data-l10n-id="open_file_label">Open</span>
- </button>
-
- <button id="secondaryPrint" class="secondaryToolbarButton print visibleMediumView" title="Print" tabindex="53" data-l10n-id="print">
- <span data-l10n-id="print_label">Print</span>
- </button>
-
- <button id="secondaryDownload" class="secondaryToolbarButton download visibleMediumView" title="Download" tabindex="54" data-l10n-id="download">
- <span data-l10n-id="download_label">Download</span>
- </button>
-
- <a href="#" id="secondaryViewBookmark" class="secondaryToolbarButton bookmark visibleSmallView" title="Current view (copy or open in new window)" tabindex="55" data-l10n-id="bookmark">
- <span data-l10n-id="bookmark_label">Current View</span>
- </a>
-
- <div class="horizontalToolbarSeparator visibleLargeView"></div>
-
- <button id="firstPage" class="secondaryToolbarButton firstPage" title="Go to First Page" tabindex="56" data-l10n-id="first_page">
- <span data-l10n-id="first_page_label">Go to First Page</span>
- </button>
- <button id="lastPage" class="secondaryToolbarButton lastPage" title="Go to Last Page" tabindex="57" data-l10n-id="last_page">
- <span data-l10n-id="last_page_label">Go to Last Page</span>
- </button>
-
- <div class="horizontalToolbarSeparator"></div>
-
- <button id="pageRotateCw" class="secondaryToolbarButton rotateCw" title="Rotate Clockwise" tabindex="58" data-l10n-id="page_rotate_cw">
- <span data-l10n-id="page_rotate_cw_label">Rotate Clockwise</span>
- </button>
- <button id="pageRotateCcw" class="secondaryToolbarButton rotateCcw" title="Rotate Counterclockwise" tabindex="59" data-l10n-id="page_rotate_ccw">
- <span data-l10n-id="page_rotate_ccw_label">Rotate Counterclockwise</span>
- </button>
-
- <div class="horizontalToolbarSeparator"></div>
-
- <button id="toggleHandTool" class="secondaryToolbarButton handTool" title="Enable hand tool" tabindex="60" data-l10n-id="hand_tool_enable">
- <span data-l10n-id="hand_tool_enable_label">Enable hand tool</span>
- </button>
-
- <div class="horizontalToolbarSeparator"></div>
-
- <button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="61" data-l10n-id="document_properties">
- <span data-l10n-id="document_properties_label">Document Properties…</span>
- </button>
- </div>
- </div> <!-- secondaryToolbar -->
-
- <div class="toolbar">
- <div id="toolbarContainer">
- <div id="toolbarViewer">
- <div id="toolbarViewerLeft">
- <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="11" data-l10n-id="toggle_sidebar">
- <span data-l10n-id="toggle_sidebar_label">Toggle Sidebar</span>
- </button>
- <div class="toolbarButtonSpacer"></div>
- <button id="viewFind" class="toolbarButton group hiddenSmallView" title="Find in Document" tabindex="12" data-l10n-id="findbar">
- <span data-l10n-id="findbar_label">Find</span>
- </button>
- <div class="splitToolbarButton">
- <button class="toolbarButton pageUp" title="Previous Page" id="previous" tabindex="13" data-l10n-id="previous">
- <span data-l10n-id="previous_label">Previous</span>
- </button>
- <div class="splitToolbarButtonSeparator"></div>
- <button class="toolbarButton pageDown" title="Next Page" id="next" tabindex="14" data-l10n-id="next">
- <span data-l10n-id="next_label">Next</span>
- </button>
- </div>
- <input type="number" id="pageNumber" class="toolbarField pageNumber" title="Page" value="1" size="4" min="1" tabindex="15" data-l10n-id="page">
- <span id="numPages" class="toolbarLabel"></span>
- </div>
- <div id="toolbarViewerRight">
- <button id="presentationMode" class="toolbarButton presentationMode hiddenLargeView" title="Switch to Presentation Mode" tabindex="31" data-l10n-id="presentation_mode">
- <span data-l10n-id="presentation_mode_label">Presentation Mode</span>
- </button>
-
- <button id="openFile" class="toolbarButton openFile hiddenLargeView" title="Open File" tabindex="32" data-l10n-id="open_file">
- <span data-l10n-id="open_file_label">Open</span>
- </button>
-
- <button id="print" class="toolbarButton print hiddenMediumView" title="Print" tabindex="33" data-l10n-id="print">
- <span data-l10n-id="print_label">Print</span>
- </button>
-
- <button id="download" class="toolbarButton download hiddenMediumView" title="Download" tabindex="34" data-l10n-id="download">
- <span data-l10n-id="download_label">Download</span>
- </button>
- <a href="#" id="viewBookmark" class="toolbarButton bookmark hiddenSmallView" title="Current view (copy or open in new window)" tabindex="35" data-l10n-id="bookmark">
- <span data-l10n-id="bookmark_label">Current View</span>
- </a>
-
- <div class="verticalToolbarSeparator hiddenSmallView"></div>
-
- <button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="36" data-l10n-id="tools">
- <span data-l10n-id="tools_label">Tools</span>
- </button>
- </div>
- <div id="toolbarViewerMiddle">
- <div class="splitToolbarButton">
- <button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out" tabindex="21" data-l10n-id="zoom_out">
- <span data-l10n-id="zoom_out_label">Zoom Out</span>
- </button>
- <div class="splitToolbarButtonSeparator"></div>
- <button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In" tabindex="22" data-l10n-id="zoom_in">
- <span data-l10n-id="zoom_in_label">Zoom In</span>
- </button>
- </div>
- <span id="scaleSelectContainer" class="dropdownToolbarButton">
- <select id="scaleSelect" title="Zoom" tabindex="23" data-l10n-id="zoom">
- <option id="pageAutoOption" title="" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option>
- <option id="pageActualOption" title="" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option>
- <option id="pageFitOption" title="" value="page-fit" data-l10n-id="page_scale_fit">Fit Page</option>
- <option id="pageWidthOption" title="" value="page-width" data-l10n-id="page_scale_width">Full Width</option>
- <option id="customScaleOption" title="" value="custom" disabled="disabled" hidden="true"></option>
- <option title="" value="0.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 50 }'>50%</option>
- <option title="" value="0.75" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 75 }'>75%</option>
- <option title="" value="1" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 100 }'>100%</option>
- <option title="" value="1.25" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 125 }'>125%</option>
- <option title="" value="1.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 150 }'>150%</option>
- <option title="" value="2" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 200 }'>200%</option>
- <option title="" value="3" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 300 }'>300%</option>
- <option title="" value="4" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 400 }'>400%</option>
- </select>
- </span>
- </div>
- </div>
- <div id="loadingBar">
- <div class="progress">
- <div class="glimmer">
- </div>
- </div>
- </div>
- </div>
- </div>
-
- <menu type="context" id="viewerContextMenu">
- <menuitem id="contextFirstPage" label="First Page"
- data-l10n-id="first_page"></menuitem>
- <menuitem id="contextLastPage" label="Last Page"
- data-l10n-id="last_page"></menuitem>
- <menuitem id="contextPageRotateCw" label="Rotate Clockwise"
- data-l10n-id="page_rotate_cw"></menuitem>
- <menuitem id="contextPageRotateCcw" label="Rotate Counter-Clockwise"
- data-l10n-id="page_rotate_ccw"></menuitem>
- </menu>
-
- <div id="viewerContainer" tabindex="0">
- <div id="viewer" class="pdfViewer"></div>
- </div>
-
- <div id="errorWrapper" hidden='true'>
- <div id="errorMessageLeft">
- <span id="errorMessage"></span>
- <button id="errorShowMore" data-l10n-id="error_more_info">
- More Information
- </button>
- <button id="errorShowLess" data-l10n-id="error_less_info" hidden='true'>
- Less Information
- </button>
- </div>
- <div id="errorMessageRight">
- <button id="errorClose" data-l10n-id="error_close">
- Close
- </button>
- </div>
- <div class="clearBoth"></div>
- <textarea id="errorMoreInfo" hidden='true' readonly="readonly"></textarea>
- </div>
- </div> <!-- mainContainer -->
-
- <div id="overlayContainer" class="hidden">
- <div id="passwordOverlay" class="container hidden">
- <div class="dialog">
- <div class="row">
- <p id="passwordText" data-l10n-id="password_label">Enter the password to open this PDF file:</p>
- </div>
- <div class="row">
- <!-- The type="password" attribute is set via script, to prevent warnings in Firefox for all http:// documents. -->
- <input id="password" class="toolbarField">
- </div>
- <div class="buttonRow">
- <button id="passwordCancel" class="overlayButton"><span data-l10n-id="password_cancel">Cancel</span></button>
- <button id="passwordSubmit" class="overlayButton"><span data-l10n-id="password_ok">OK</span></button>
- </div>
- </div>
- </div>
- <div id="documentPropertiesOverlay" class="container hidden">
- <div class="dialog">
- <div class="row">
- <span data-l10n-id="document_properties_file_name">File name:</span> <p id="fileNameField">-</p>
- </div>
- <div class="row">
- <span data-l10n-id="document_properties_file_size">File size:</span> <p id="fileSizeField">-</p>
- </div>
- <div class="separator"></div>
- <div class="row">
- <span data-l10n-id="document_properties_title">Title:</span> <p id="titleField">-</p>
- </div>
- <div class="row">
- <span data-l10n-id="document_properties_author">Author:</span> <p id="authorField">-</p>
- </div>
- <div class="row">
- <span data-l10n-id="document_properties_subject">Subject:</span> <p id="subjectField">-</p>
- </div>
- <div class="row">
- <span data-l10n-id="document_properties_keywords">Keywords:</span> <p id="keywordsField">-</p>
- </div>
- <div class="row">
- <span data-l10n-id="document_properties_creation_date">Creation Date:</span> <p id="creationDateField">-</p>
- </div>
- <div class="row">
- <span data-l10n-id="document_properties_modification_date">Modification Date:</span> <p id="modificationDateField">-</p>
- </div>
- <div class="row">
- <span data-l10n-id="document_properties_creator">Creator:</span> <p id="creatorField">-</p>
- </div>
- <div class="separator"></div>
- <div class="row">
- <span data-l10n-id="document_properties_producer">PDF Producer:</span> <p id="producerField">-</p>
- </div>
- <div class="row">
- <span data-l10n-id="document_properties_version">PDF Version:</span> <p id="versionField">-</p>
- </div>
- <div class="row">
- <span data-l10n-id="document_properties_page_count">Page Count:</span> <p id="pageCountField">-</p>
- </div>
- <div class="buttonRow">
- <button id="documentPropertiesClose" class="overlayButton"><span data-l10n-id="document_properties_close">Close</span></button>
- </div>
- </div>
- </div>
- </div> <!-- overlayContainer -->
-
- </div> <!-- outerContainer -->
- <div id="printContainer"></div>
- </body>
-</html>
-
diff --git a/extensions/pdfjs/content/web/viewer.js b/extensions/pdfjs/content/web/viewer.js
deleted file mode 100644
index 35fef2c..0000000
--- a/extensions/pdfjs/content/web/viewer.js
+++ /dev/null
@@ -1,8671 +0,0 @@
-/* Copyright 2016 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-'use strict';
-var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf';
-;
-var pdfjsWebLibs;
-{
- pdfjsWebLibs = { pdfjsWebPDFJS: window.pdfjsDistBuildPdf };
- (function () {
- (function (root, factory) {
- factory(root.pdfjsWebGrabToPan = {});
- }(this, function (exports) {
- /**
- * Construct a GrabToPan instance for a given HTML element.
- * @param options.element {Element}
- * @param options.ignoreTarget {function} optional. See `ignoreTarget(node)`
- * @param options.onActiveChanged {function(boolean)} optional. Called
- * when grab-to-pan is (de)activated. The first argument is a boolean that
- * shows whether grab-to-pan is activated.
- */
- function GrabToPan(options) {
- this.element = options.element;
- this.document = options.element.ownerDocument;
- if (typeof options.ignoreTarget === 'function') {
- this.ignoreTarget = options.ignoreTarget;
- }
- this.onActiveChanged = options.onActiveChanged;
- // Bind the contexts to ensure that `this` always points to
- // the GrabToPan instance.
- this.activate = this.activate.bind(this);
- this.deactivate = this.deactivate.bind(this);
- this.toggle = this.toggle.bind(this);
- this._onmousedown = this._onmousedown.bind(this);
- this._onmousemove = this._onmousemove.bind(this);
- this._endPan = this._endPan.bind(this);
- // This overlay will be inserted in the document when the mouse moves during
- // a grab operation, to ensure that the cursor has the desired appearance.
- var overlay = this.overlay = document.createElement('div');
- overlay.className = 'grab-to-pan-grabbing';
- }
- GrabToPan.prototype = {
- /**
- * Class name of element which can be grabbed
- */
- CSS_CLASS_GRAB: 'grab-to-pan-grab',
- /**
- * Bind a mousedown event to the element to enable grab-detection.
- */
- activate: function GrabToPan_activate() {
- if (!this.active) {
- this.active = true;
- this.element.addEventListener('mousedown', this._onmousedown, true);
- this.element.classList.add(this.CSS_CLASS_GRAB);
- if (this.onActiveChanged) {
- this.onActiveChanged(true);
- }
- }
- },
- /**
- * Removes all events. Any pending pan session is immediately stopped.
- */
- deactivate: function GrabToPan_deactivate() {
- if (this.active) {
- this.active = false;
- this.element.removeEventListener('mousedown', this._onmousedown, true);
- this._endPan();
- this.element.classList.remove(this.CSS_CLASS_GRAB);
- if (this.onActiveChanged) {
- this.onActiveChanged(false);
- }
- }
- },
- toggle: function GrabToPan_toggle() {
- if (this.active) {
- this.deactivate();
- } else {
- this.activate();
- }
- },
- /**
- * Whether to not pan if the target element is clicked.
- * Override this method to change the default behaviour.
- *
- * @param node {Element} The target of the event
- * @return {boolean} Whether to not react to the click event.
- */
- ignoreTarget: function GrabToPan_ignoreTarget(node) {
- // Use matchesSelector to check whether the clicked element
- // is (a child of) an input element / link
- return node[matchesSelector]('a[href], a[href] *, input, textarea, button, button *, select, option');
- },
- /**
- * @private
- */
- _onmousedown: function GrabToPan__onmousedown(event) {
- if (event.button !== 0 || this.ignoreTarget(event.target)) {
- return;
- }
- if (event.originalTarget) {
- try {
- event.originalTarget.tagName;
- } catch (e) {
- // Mozilla-specific: element is a scrollbar (XUL element)
- return;
- }
- }
- this.scrollLeftStart = this.element.scrollLeft;
- this.scrollTopStart = this.element.scrollTop;
- this.clientXStart = event.clientX;
- this.clientYStart = event.clientY;
- this.document.addEventListener('mousemove', this._onmousemove, true);
- this.document.addEventListener('mouseup', this._endPan, true);
- // When a scroll event occurs before a mousemove, assume that the user
- // dragged a scrollbar (necessary for Opera Presto, Safari and IE)
- // (not needed for Chrome/Firefox)
- this.element.addEventListener('scroll', this._endPan, true);
- event.preventDefault();
- event.stopPropagation();
- var focusedElement = document.activeElement;
- if (focusedElement && !focusedElement.contains(event.target)) {
- focusedElement.blur();
- }
- },
- /**
- * @private
- */
- _onmousemove: function GrabToPan__onmousemove(event) {
- this.element.removeEventListener('scroll', this._endPan, true);
- if (isLeftMouseReleased(event)) {
- this._endPan();
- return;
- }
- var xDiff = event.clientX - this.clientXStart;
- var yDiff = event.clientY - this.clientYStart;
- var scrollTop = this.scrollTopStart - yDiff;
- var scrollLeft = this.scrollLeftStart - xDiff;
- if (this.element.scrollTo) {
- this.element.scrollTo({
- top: scrollTop,
- left: scrollLeft,
- behavior: 'instant'
- });
- } else {
- this.element.scrollTop = scrollTop;
- this.element.scrollLeft = scrollLeft;
- }
- if (!this.overlay.parentNode) {
- document.body.appendChild(this.overlay);
- }
- },
- /**
- * @private
- */
- _endPan: function GrabToPan__endPan() {
- this.element.removeEventListener('scroll', this._endPan, true);
- this.document.removeEventListener('mousemove', this._onmousemove, true);
- this.document.removeEventListener('mouseup', this._endPan, true);
- if (this.overlay.parentNode) {
- this.overlay.parentNode.removeChild(this.overlay);
- }
- }
- };
- // Get the correct (vendor-prefixed) name of the matches method.
- var matchesSelector;
- [
- 'webkitM',
- 'mozM',
- 'msM',
- 'oM',
- 'm'
- ].some(function (prefix) {
- var name = prefix + 'atches';
- if (name in document.documentElement) {
- matchesSelector = name;
- }
- name += 'Selector';
- if (name in document.documentElement) {
- matchesSelector = name;
- }
- return matchesSelector;
- });
- // If found, then truthy, and [].some() ends.
- // Browser sniffing because it's impossible to feature-detect
- // whether event.which for onmousemove is reliable
- var isNotIEorIsIE10plus = !document.documentMode || document.documentMode > 9;
- var chrome = window.chrome;
- var isChrome15OrOpera15plus = chrome && (chrome.webstore || chrome.app);
- // ^ Chrome 15+ ^ Opera 15+
- var isSafari6plus = /Apple/.test(navigator.vendor) && /Version\/([6-9]\d*|[1-5]\d+)/.test(navigator.userAgent);
- /**
- * Whether the left mouse is not pressed.
- * @param event {MouseEvent}
- * @return {boolean} True if the left mouse button is not pressed.
- * False if unsure or if the left mouse button is pressed.
- */
- function isLeftMouseReleased(event) {
- if ('buttons' in event && isNotIEorIsIE10plus) {
- // http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-buttons
- // Firefox 15+
- // Internet Explorer 10+
- return !(event.buttons & 1);
- }
- if (isChrome15OrOpera15plus || isSafari6plus) {
- // Chrome 14+
- // Opera 15+
- // Safari 6.0+
- return event.which === 0;
- }
- }
- exports.GrabToPan = GrabToPan;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebOverlayManager = {});
- }(this, function (exports) {
- var OverlayManager = {
- overlays: {},
- active: null,
- /**
- * @param {string} name The name of the overlay that is registered.
- * @param {HTMLDivElement} element The overlay's DOM element.
- * @param {function} callerCloseMethod (optional) The method that, if present,
- * will call OverlayManager.close from the Object
- * registering the overlay. Access to this method is
- * necessary in order to run cleanup code when e.g.
- * the overlay is force closed. The default is null.
- * @param {boolean} canForceClose (optional) Indicates if opening the overlay
- * will close an active overlay. The default is false.
- * @returns {Promise} A promise that is resolved when the overlay has been
- * registered.
- */
- register: function overlayManagerRegister(name, element, callerCloseMethod, canForceClose) {
- return new Promise(function (resolve) {
- var container;
- if (!name || !element || !(container = element.parentNode)) {
- throw new Error('Not enough parameters.');
- } else if (this.overlays[name]) {
- throw new Error('The overlay is already registered.');
- }
- this.overlays[name] = {
- element: element,
- container: container,
- callerCloseMethod: callerCloseMethod || null,
- canForceClose: canForceClose || false
- };
- resolve();
- }.bind(this));
- },
- /**
- * @param {string} name The name of the overlay that is unregistered.
- * @returns {Promise} A promise that is resolved when the overlay has been
- * unregistered.
- */
- unregister: function overlayManagerUnregister(name) {
- return new Promise(function (resolve) {
- if (!this.overlays[name]) {
- throw new Error('The overlay does not exist.');
- } else if (this.active === name) {
- throw new Error('The overlay cannot be removed while it is active.');
- }
- delete this.overlays[name];
- resolve();
- }.bind(this));
- },
- /**
- * @param {string} name The name of the overlay that should be opened.
- * @returns {Promise} A promise that is resolved when the overlay has been
- * opened.
- */
- open: function overlayManagerOpen(name) {
- return new Promise(function (resolve) {
- if (!this.overlays[name]) {
- throw new Error('The overlay does not exist.');
- } else if (this.active) {
- if (this.overlays[name].canForceClose) {
- this._closeThroughCaller();
- } else if (this.active === name) {
- throw new Error('The overlay is already active.');
- } else {
- throw new Error('Another overlay is currently active.');
- }
- }
- this.active = name;
- this.overlays[this.active].element.classList.remove('hidden');
- this.overlays[this.active].container.classList.remove('hidden');
- window.addEventListener('keydown', this._keyDown);
- resolve();
- }.bind(this));
- },
- /**
- * @param {string} name The name of the overlay that should be closed.
- * @returns {Promise} A promise that is resolved when the overlay has been
- * closed.
- */
- close: function overlayManagerClose(name) {
- return new Promise(function (resolve) {
- if (!this.overlays[name]) {
- throw new Error('The overlay does not exist.');
- } else if (!this.active) {
- throw new Error('The overlay is currently not active.');
- } else if (this.active !== name) {
- throw new Error('Another overlay is currently active.');
- }
- this.overlays[this.active].container.classList.add('hidden');
- this.overlays[this.active].element.classList.add('hidden');
- this.active = null;
- window.removeEventListener('keydown', this._keyDown);
- resolve();
- }.bind(this));
- },
- /**
- * @private
- */
- _keyDown: function overlayManager_keyDown(evt) {
- var self = OverlayManager;
- if (self.active && evt.keyCode === 27) {
- // Esc key.
- self._closeThroughCaller();
- evt.preventDefault();
- }
- },
- /**
- * @private
- */
- _closeThroughCaller: function overlayManager_closeThroughCaller() {
- if (this.overlays[this.active].callerCloseMethod) {
- this.overlays[this.active].callerCloseMethod();
- }
- if (this.active) {
- this.close(this.active);
- }
- }
- };
- exports.OverlayManager = OverlayManager;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFRenderingQueue = {});
- }(this, function (exports) {
- var CLEANUP_TIMEOUT = 30000;
- var RenderingStates = {
- INITIAL: 0,
- RUNNING: 1,
- PAUSED: 2,
- FINISHED: 3
- };
- /**
- * Controls rendering of the views for pages and thumbnails.
- * @class
- */
- var PDFRenderingQueue = function PDFRenderingQueueClosure() {
- /**
- * @constructs
- */
- function PDFRenderingQueue() {
- this.pdfViewer = null;
- this.pdfThumbnailViewer = null;
- this.onIdle = null;
- this.highestPriorityPage = null;
- this.idleTimeout = null;
- this.printing = false;
- this.isThumbnailViewEnabled = false;
- }
- PDFRenderingQueue.prototype = /** @lends PDFRenderingQueue.prototype */
- {
- /**
- * @param {PDFViewer} pdfViewer
- */
- setViewer: function PDFRenderingQueue_setViewer(pdfViewer) {
- this.pdfViewer = pdfViewer;
- },
- /**
- * @param {PDFThumbnailViewer} pdfThumbnailViewer
- */
- setThumbnailViewer: function PDFRenderingQueue_setThumbnailViewer(pdfThumbnailViewer) {
- this.pdfThumbnailViewer = pdfThumbnailViewer;
- },
- /**
- * @param {IRenderableView} view
- * @returns {boolean}
- */
- isHighestPriority: function PDFRenderingQueue_isHighestPriority(view) {
- return this.highestPriorityPage === view.renderingId;
- },
- renderHighestPriority: function PDFRenderingQueue_renderHighestPriority(currentlyVisiblePages) {
- if (this.idleTimeout) {
- clearTimeout(this.idleTimeout);
- this.idleTimeout = null;
- }
- // Pages have a higher priority than thumbnails, so check them first.
- if (this.pdfViewer.forceRendering(currentlyVisiblePages)) {
- return;
- }
- // No pages needed rendering so check thumbnails.
- if (this.pdfThumbnailViewer && this.isThumbnailViewEnabled) {
- if (this.pdfThumbnailViewer.forceRendering()) {
- return;
- }
- }
- if (this.printing) {
- // If printing is currently ongoing do not reschedule cleanup.
- return;
- }
- if (this.onIdle) {
- this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT);
- }
- },
- getHighestPriority: function PDFRenderingQueue_getHighestPriority(visible, views, scrolledDown) {
- // The state has changed figure out which page has the highest priority to
- // render next (if any).
- // Priority:
- // 1 visible pages
- // 2 if last scrolled down page after the visible pages
- // 2 if last scrolled up page before the visible pages
- var visibleViews = visible.views;
- var numVisible = visibleViews.length;
- if (numVisible === 0) {
- return false;
- }
- for (var i = 0; i < numVisible; ++i) {
- var view = visibleViews[i].view;
- if (!this.isViewFinished(view)) {
- return view;
- }
- }
- // All the visible views have rendered, try to render next/previous pages.
- if (scrolledDown) {
- var nextPageIndex = visible.last.id;
- // ID's start at 1 so no need to add 1.
- if (views[nextPageIndex] && !this.isViewFinished(views[nextPageIndex])) {
- return views[nextPageIndex];
- }
- } else {
- var previousPageIndex = visible.first.id - 2;
- if (views[previousPageIndex] && !this.isViewFinished(views[previousPageIndex])) {
- return views[previousPageIndex];
- }
- }
- // Everything that needs to be rendered has been.
- return null;
- },
- /**
- * @param {IRenderableView} view
- * @returns {boolean}
- */
- isViewFinished: function PDFRenderingQueue_isViewFinished(view) {
- return view.renderingState === RenderingStates.FINISHED;
- },
- /**
- * Render a page or thumbnail view. This calls the appropriate function
- * based on the views state. If the view is already rendered it will return
- * false.
- * @param {IRenderableView} view
- */
- renderView: function PDFRenderingQueue_renderView(view) {
- var state = view.renderingState;
- switch (state) {
- case RenderingStates.FINISHED:
- return false;
- case RenderingStates.PAUSED:
- this.highestPriorityPage = view.renderingId;
- view.resume();
- break;
- case RenderingStates.RUNNING:
- this.highestPriorityPage = view.renderingId;
- break;
- case RenderingStates.INITIAL:
- this.highestPriorityPage = view.renderingId;
- var continueRendering = function () {
- this.renderHighestPriority();
- }.bind(this);
- view.draw().then(continueRendering, continueRendering);
- break;
- }
- return true;
- }
- };
- return PDFRenderingQueue;
- }();
- exports.RenderingStates = RenderingStates;
- exports.PDFRenderingQueue = PDFRenderingQueue;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPreferences = {});
- }(this, function (exports) {
- var defaultPreferences;
- defaultPreferences = Promise.resolve({
- "showPreviousViewOnLoad": true,
- "defaultZoomValue": "",
- "sidebarViewOnLoad": 0,
- "enableHandToolOnLoad": false,
- "enableWebGL": false,
- "pdfBugEnabled": false,
- "disableRange": false,
- "disableStream": false,
- "disableAutoFetch": false,
- "disableFontFace": false,
- "disableTextLayer": false,
- "useOnlyCssZoom": false,
- "externalLinkTarget": 0,
- "enhanceTextSelection": false,
- "renderInteractiveForms": false,
- "disablePageLabels": false
- });
- function cloneObj(obj) {
- var result = {};
- for (var i in obj) {
- if (Object.prototype.hasOwnProperty.call(obj, i)) {
- result[i] = obj[i];
- }
- }
- return result;
- }
- /**
- * Preferences - Utility for storing persistent settings.
- * Used for settings that should be applied to all opened documents,
- * or every time the viewer is loaded.
- */
- var Preferences = {
- prefs: null,
- isInitializedPromiseResolved: false,
- initializedPromise: null,
- /**
- * Initialize and fetch the current preference values from storage.
- * @return {Promise} A promise that is resolved when the preferences
- * have been initialized.
- */
- initialize: function preferencesInitialize() {
- return this.initializedPromise = defaultPreferences.then(function (defaults) {
- Object.defineProperty(this, 'defaults', {
- value: Object.freeze(defaults),
- writable: false,
- enumerable: true,
- configurable: false
- });
- this.prefs = cloneObj(defaults);
- return this._readFromStorage(defaults);
- }.bind(this)).then(function (prefObj) {
- this.isInitializedPromiseResolved = true;
- if (prefObj) {
- this.prefs = prefObj;
- }
- }.bind(this));
- },
- /**
- * Stub function for writing preferences to storage.
- * NOTE: This should be overridden by a build-specific function defined below.
- * @param {Object} prefObj The preferences that should be written to storage.
- * @return {Promise} A promise that is resolved when the preference values
- * have been written.
- */
- _writeToStorage: function preferences_writeToStorage(prefObj) {
- return Promise.resolve();
- },
- /**
- * Stub function for reading preferences from storage.
- * NOTE: This should be overridden by a build-specific function defined below.
- * @param {Object} prefObj The preferences that should be read from storage.
- * @return {Promise} A promise that is resolved with an {Object} containing
- * the preferences that have been read.
- */
- _readFromStorage: function preferences_readFromStorage(prefObj) {
- return Promise.resolve();
- },
- /**
- * Reset the preferences to their default values and update storage.
- * @return {Promise} A promise that is resolved when the preference values
- * have been reset.
- */
- reset: function preferencesReset() {
- return this.initializedPromise.then(function () {
- this.prefs = cloneObj(this.defaults);
- return this._writeToStorage(this.defaults);
- }.bind(this));
- },
- /**
- * Replace the current preference values with the ones from storage.
- * @return {Promise} A promise that is resolved when the preference values
- * have been updated.
- */
- reload: function preferencesReload() {
- return this.initializedPromise.then(function () {
- this._readFromStorage(this.defaults).then(function (prefObj) {
- if (prefObj) {
- this.prefs = prefObj;
- }
- }.bind(this));
- }.bind(this));
- },
- /**
- * Set the value of a preference.
- * @param {string} name The name of the preference that should be changed.
- * @param {boolean|number|string} value The new value of the preference.
- * @return {Promise} A promise that is resolved when the value has been set,
- * provided that the preference exists and the types match.
- */
- set: function preferencesSet(name, value) {
- return this.initializedPromise.then(function () {
- if (this.defaults[name] === undefined) {
- throw new Error('preferencesSet: \'' + name + '\' is undefined.');
- } else if (value === undefined) {
- throw new Error('preferencesSet: no value is specified.');
- }
- var valueType = typeof value;
- var defaultType = typeof this.defaults[name];
- if (valueType !== defaultType) {
- if (valueType === 'number' && defaultType === 'string') {
- value = value.toString();
- } else {
- throw new Error('Preferences_set: \'' + value + '\' is a \"' + valueType + '\", expected \"' + defaultType + '\".');
- }
- } else {
- if (valueType === 'number' && (value | 0) !== value) {
- throw new Error('Preferences_set: \'' + value + '\' must be an \"integer\".');
- }
- }
- this.prefs[name] = value;
- return this._writeToStorage(this.prefs);
- }.bind(this));
- },
- /**
- * Get the value of a preference.
- * @param {string} name The name of the preference whose value is requested.
- * @return {Promise} A promise that is resolved with a {boolean|number|string}
- * containing the value of the preference.
- */
- get: function preferencesGet(name) {
- return this.initializedPromise.then(function () {
- var defaultValue = this.defaults[name];
- if (defaultValue === undefined) {
- throw new Error('preferencesGet: \'' + name + '\' is undefined.');
- } else {
- var prefValue = this.prefs[name];
- if (prefValue !== undefined) {
- return prefValue;
- }
- }
- return defaultValue;
- }.bind(this));
- }
- };
- exports.Preferences = Preferences;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebViewHistory = {});
- }(this, function (exports) {
- var DEFAULT_VIEW_HISTORY_CACHE_SIZE = 20;
- /**
- * View History - This is a utility for saving various view parameters for
- * recently opened files.
- *
- * The way that the view parameters are stored depends on how PDF.js is built,
- * for 'gulp <flag>' the following cases exist:
- * - FIREFOX or MOZCENTRAL - uses sessionStorage.
- * - GENERIC or CHROME - uses localStorage, if it is available.
- */
- var ViewHistory = function ViewHistoryClosure() {
- function ViewHistory(fingerprint, cacheSize) {
- this.fingerprint = fingerprint;
- this.cacheSize = cacheSize || DEFAULT_VIEW_HISTORY_CACHE_SIZE;
- this.isInitializedPromiseResolved = false;
- this.initializedPromise = this._readFromStorage().then(function (databaseStr) {
- this.isInitializedPromiseResolved = true;
- var database = JSON.parse(databaseStr || '{}');
- if (!('files' in database)) {
- database.files = [];
- }
- if (database.files.length >= this.cacheSize) {
- database.files.shift();
- }
- var index;
- for (var i = 0, length = database.files.length; i < length; i++) {
- var branch = database.files[i];
- if (branch.fingerprint === this.fingerprint) {
- index = i;
- break;
- }
- }
- if (typeof index !== 'number') {
- index = database.files.push({ fingerprint: this.fingerprint }) - 1;
- }
- this.file = database.files[index];
- this.database = database;
- }.bind(this));
- }
- ViewHistory.prototype = {
- _writeToStorage: function ViewHistory_writeToStorage() {
- return new Promise(function (resolve) {
- var databaseStr = JSON.stringify(this.database);
- sessionStorage.setItem('pdfjsHistory', databaseStr);
- resolve();
- }.bind(this));
- },
- _readFromStorage: function ViewHistory_readFromStorage() {
- return new Promise(function (resolve) {
- resolve(sessionStorage.getItem('pdfjsHistory'));
- });
- },
- set: function ViewHistory_set(name, val) {
- if (!this.isInitializedPromiseResolved) {
- return;
- }
- this.file[name] = val;
- return this._writeToStorage();
- },
- setMultiple: function ViewHistory_setMultiple(properties) {
- if (!this.isInitializedPromiseResolved) {
- return;
- }
- for (var name in properties) {
- this.file[name] = properties[name];
- }
- return this._writeToStorage();
- },
- get: function ViewHistory_get(name, defaultValue) {
- if (!this.isInitializedPromiseResolved) {
- return defaultValue;
- }
- return this.file[name] || defaultValue;
- }
- };
- return ViewHistory;
- }();
- exports.ViewHistory = ViewHistory;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebDownloadManager = {}, root.pdfjsWebPDFJS);
- }(this, function (exports, pdfjsLib) {
- }));
- (function (root, factory) {
- factory(root.pdfjsWebHandTool = {}, root.pdfjsWebGrabToPan, root.pdfjsWebPreferences);
- }(this, function (exports, grabToPan, preferences) {
- var GrabToPan = grabToPan.GrabToPan;
- var Preferences = preferences.Preferences;
- /**
- * @typedef {Object} HandToolOptions
- * @property {HTMLDivElement} container - The document container.
- * @property {EventBus} eventBus - The application event bus.
- */
- /**
- * @class
- */
- var HandTool = function HandToolClosure() {
- /**
- * @constructs HandTool
- * @param {HandToolOptions} options
- */
- function HandTool(options) {
- this.container = options.container;
- this.eventBus = options.eventBus;
- this.wasActive = false;
- this.handTool = new GrabToPan({
- element: this.container,
- onActiveChanged: function (isActive) {
- this.eventBus.dispatch('handtoolchanged', { isActive: isActive });
- }.bind(this)
- });
- this.eventBus.on('togglehandtool', this.toggle.bind(this));
- this.eventBus.on('localized', function (e) {
- Preferences.get('enableHandToolOnLoad').then(function resolved(value) {
- if (value) {
- this.handTool.activate();
- }
- }.bind(this), function rejected(reason) {
- });
- }.bind(this));
- this.eventBus.on('presentationmodechanged', function (e) {
- if (e.switchInProgress) {
- return;
- }
- if (e.active) {
- this.enterPresentationMode();
- } else {
- this.exitPresentationMode();
- }
- }.bind(this));
- }
- HandTool.prototype = {
- /**
- * @return {boolean}
- */
- get isActive() {
- return !!this.handTool.active;
- },
- toggle: function HandTool_toggle() {
- this.handTool.toggle();
- },
- enterPresentationMode: function HandTool_enterPresentationMode() {
- if (this.isActive) {
- this.wasActive = true;
- this.handTool.deactivate();
- }
- },
- exitPresentationMode: function HandTool_exitPresentationMode() {
- if (this.wasActive) {
- this.wasActive = false;
- this.handTool.activate();
- }
- }
- };
- return HandTool;
- }();
- exports.HandTool = HandTool;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFAttachmentViewer = {}, root.pdfjsWebPDFJS);
- }(this, function (exports, pdfjsLib) {
- /**
- * @typedef {Object} PDFAttachmentViewerOptions
- * @property {HTMLDivElement} container - The viewer element.
- * @property {EventBus} eventBus - The application event bus.
- * @property {DownloadManager} downloadManager - The download manager.
- */
- /**
- * @typedef {Object} PDFAttachmentViewerRenderParameters
- * @property {Array|null} attachments - An array of attachment objects.
- */
- /**
- * @class
- */
- var PDFAttachmentViewer = function PDFAttachmentViewerClosure() {
- /**
- * @constructs PDFAttachmentViewer
- * @param {PDFAttachmentViewerOptions} options
- */
- function PDFAttachmentViewer(options) {
- this.attachments = null;
- this.container = options.container;
- this.eventBus = options.eventBus;
- this.downloadManager = options.downloadManager;
- }
- PDFAttachmentViewer.prototype = {
- reset: function PDFAttachmentViewer_reset() {
- this.attachments = null;
- var container = this.container;
- while (container.firstChild) {
- container.removeChild(container.firstChild);
- }
- },
- /**
- * @private
- */
- _dispatchEvent: function PDFAttachmentViewer_dispatchEvent(attachmentsCount) {
- this.eventBus.dispatch('attachmentsloaded', {
- source: this,
- attachmentsCount: attachmentsCount
- });
- },
- /**
- * @private
- */
- _bindLink: function PDFAttachmentViewer_bindLink(button, content, filename) {
- button.onclick = function downloadFile(e) {
- this.downloadManager.downloadData(content, filename, '');
- return false;
- }.bind(this);
- },
- /**
- * @param {PDFAttachmentViewerRenderParameters} params
- */
- render: function PDFAttachmentViewer_render(params) {
- var attachments = params && params.attachments || null;
- var attachmentsCount = 0;
- if (this.attachments) {
- this.reset();
- }
- this.attachments = attachments;
- if (!attachments) {
- this._dispatchEvent(attachmentsCount);
- return;
- }
- var names = Object.keys(attachments).sort(function (a, b) {
- return a.toLowerCase().localeCompare(b.toLowerCase());
- });
- attachmentsCount = names.length;
- for (var i = 0; i < attachmentsCount; i++) {
- var item = attachments[names[i]];
- var filename = pdfjsLib.getFilenameFromUrl(item.filename);
- var div = document.createElement('div');
- div.className = 'attachmentsItem';
- var button = document.createElement('button');
- this._bindLink(button, item.content, filename);
- button.textContent = pdfjsLib.removeNullCharacters(filename);
- div.appendChild(button);
- this.container.appendChild(div);
- }
- this._dispatchEvent(attachmentsCount);
- }
- };
- return PDFAttachmentViewer;
- }();
- exports.PDFAttachmentViewer = PDFAttachmentViewer;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFOutlineViewer = {}, root.pdfjsWebPDFJS);
- }(this, function (exports, pdfjsLib) {
- var PDFJS = pdfjsLib.PDFJS;
- var DEFAULT_TITLE = '\u2013';
- /**
- * @typedef {Object} PDFOutlineViewerOptions
- * @property {HTMLDivElement} container - The viewer element.
- * @property {IPDFLinkService} linkService - The navigation/linking service.
- * @property {EventBus} eventBus - The application event bus.
- */
- /**
- * @typedef {Object} PDFOutlineViewerRenderParameters
- * @property {Array|null} outline - An array of outline objects.
- */
- /**
- * @class
- */
- var PDFOutlineViewer = function PDFOutlineViewerClosure() {
- /**
- * @constructs PDFOutlineViewer
- * @param {PDFOutlineViewerOptions} options
- */
- function PDFOutlineViewer(options) {
- this.outline = null;
- this.lastToggleIsShow = true;
- this.container = options.container;
- this.linkService = options.linkService;
- this.eventBus = options.eventBus;
- }
- PDFOutlineViewer.prototype = {
- reset: function PDFOutlineViewer_reset() {
- this.outline = null;
- this.lastToggleIsShow = true;
- var container = this.container;
- while (container.firstChild) {
- container.removeChild(container.firstChild);
- }
- },
- /**
- * @private
- */
- _dispatchEvent: function PDFOutlineViewer_dispatchEvent(outlineCount) {
- this.eventBus.dispatch('outlineloaded', {
- source: this,
- outlineCount: outlineCount
- });
- },
- /**
- * @private
- */
- _bindLink: function PDFOutlineViewer_bindLink(element, item) {
- if (item.url) {
- pdfjsLib.addLinkAttributes(element, {
- url: item.url,
- target: item.newWindow ? PDFJS.LinkTarget.BLANK : undefined
- });
- return;
- }
- var self = this, destination = item.dest;
- element.href = self.linkService.getDestinationHash(destination);
- element.onclick = function () {
- if (destination) {
- self.linkService.navigateTo(destination);
- }
- return false;
- };
- },
- /**
- * @private
- */
- _setStyles: function PDFOutlineViewer_setStyles(element, item) {
- var styleStr = '';
- if (item.bold) {
- styleStr += 'font-weight: bold;';
- }
- if (item.italic) {
- styleStr += 'font-style: italic;';
- }
- if (styleStr) {
- element.setAttribute('style', styleStr);
- }
- },
- /**
- * Prepend a button before an outline item which allows the user to toggle
- * the visibility of all outline items at that level.
- *
- * @private
- */
- _addToggleButton: function PDFOutlineViewer_addToggleButton(div) {
- var toggler = document.createElement('div');
- toggler.className = 'outlineItemToggler';
- toggler.onclick = function (event) {
- event.stopPropagation();
- toggler.classList.toggle('outlineItemsHidden');
- if (event.shiftKey) {
- var shouldShowAll = !toggler.classList.contains('outlineItemsHidden');
- this._toggleOutlineItem(div, shouldShowAll);
- }
- }.bind(this);
- div.insertBefore(toggler, div.firstChild);
- },
- /**
- * Toggle the visibility of the subtree of an outline item.
- *
- * @param {Element} root - the root of the outline (sub)tree.
- * @param {boolean} show - whether to show the outline (sub)tree. If false,
- * the outline subtree rooted at |root| will be collapsed.
- *
- * @private
- */
- _toggleOutlineItem: function PDFOutlineViewer_toggleOutlineItem(root, show) {
- this.lastToggleIsShow = show;
- var togglers = root.querySelectorAll('.outlineItemToggler');
- for (var i = 0, ii = togglers.length; i < ii; ++i) {
- togglers[i].classList[show ? 'remove' : 'add']('outlineItemsHidden');
- }
- },
- /**
- * Collapse or expand all subtrees of the outline.
- */
- toggleOutlineTree: function PDFOutlineViewer_toggleOutlineTree() {
- if (!this.outline) {
- return;
- }
- this._toggleOutlineItem(this.container, !this.lastToggleIsShow);
- },
- /**
- * @param {PDFOutlineViewerRenderParameters} params
- */
- render: function PDFOutlineViewer_render(params) {
- var outline = params && params.outline || null;
- var outlineCount = 0;
- if (this.outline) {
- this.reset();
- }
- this.outline = outline;
- if (!outline) {
- this._dispatchEvent(outlineCount);
- return;
- }
- var fragment = document.createDocumentFragment();
- var queue = [{
- parent: fragment,
- items: this.outline
- }];
- var hasAnyNesting = false;
- while (queue.length > 0) {
- var levelData = queue.shift();
- for (var i = 0, len = levelData.items.length; i < len; i++) {
- var item = levelData.items[i];
- var div = document.createElement('div');
- div.className = 'outlineItem';
- var element = document.createElement('a');
- this._bindLink(element, item);
- this._setStyles(element, item);
- element.textContent = pdfjsLib.removeNullCharacters(item.title) || DEFAULT_TITLE;
- div.appendChild(element);
- if (item.items.length > 0) {
- hasAnyNesting = true;
- this._addToggleButton(div);
- var itemsDiv = document.createElement('div');
- itemsDiv.className = 'outlineItems';
- div.appendChild(itemsDiv);
- queue.push({
- parent: itemsDiv,
- items: item.items
- });
- }
- levelData.parent.appendChild(div);
- outlineCount++;
- }
- }
- if (hasAnyNesting) {
- this.container.classList.add('outlineWithDeepNesting');
- }
- this.container.appendChild(fragment);
- this._dispatchEvent(outlineCount);
- }
- };
- return PDFOutlineViewer;
- }();
- exports.PDFOutlineViewer = PDFOutlineViewer;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFSidebar = {}, root.pdfjsWebPDFRenderingQueue);
- }(this, function (exports, pdfRenderingQueue) {
- var RenderingStates = pdfRenderingQueue.RenderingStates;
- var SidebarView = {
- NONE: 0,
- THUMBS: 1,
- OUTLINE: 2,
- ATTACHMENTS: 3
- };
- /**
- * @typedef {Object} PDFSidebarOptions
- * @property {PDFViewer} pdfViewer - The document viewer.
- * @property {PDFThumbnailViewer} pdfThumbnailViewer - The thumbnail viewer.
- * @property {PDFOutlineViewer} pdfOutlineViewer - The outline viewer.
- * @property {HTMLDivElement} mainContainer - The main container
- * (in which the viewer element is placed).
- * @property {HTMLDivElement} outerContainer - The outer container
- * (encasing both the viewer and sidebar elements).
- * @property {EventBus} eventBus - The application event bus.
- * @property {HTMLButtonElement} toggleButton - The button used for
- * opening/closing the sidebar.
- * @property {HTMLButtonElement} thumbnailButton - The button used to show
- * the thumbnail view.
- * @property {HTMLButtonElement} outlineButton - The button used to show
- * the outline view.
- * @property {HTMLButtonElement} attachmentsButton - The button used to show
- * the attachments view.
- * @property {HTMLDivElement} thumbnailView - The container in which
- * the thumbnails are placed.
- * @property {HTMLDivElement} outlineView - The container in which
- * the outline is placed.
- * @property {HTMLDivElement} attachmentsView - The container in which
- * the attachments are placed.
- */
- /**
- * @class
- */
- var PDFSidebar = function PDFSidebarClosure() {
- /**
- * @constructs PDFSidebar
- * @param {PDFSidebarOptions} options
- */
- function PDFSidebar(options) {
- this.isOpen = false;
- this.active = SidebarView.THUMBS;
- this.isInitialViewSet = false;
- /**
- * Callback used when the sidebar has been opened/closed, to ensure that
- * the viewers (PDFViewer/PDFThumbnailViewer) are updated correctly.
- */
- this.onToggled = null;
- this.pdfViewer = options.pdfViewer;
- this.pdfThumbnailViewer = options.pdfThumbnailViewer;
- this.pdfOutlineViewer = options.pdfOutlineViewer;
- this.mainContainer = options.mainContainer;
- this.outerContainer = options.outerContainer;
- this.eventBus = options.eventBus;
- this.toggleButton = options.toggleButton;
- this.thumbnailButton = options.thumbnailButton;
- this.outlineButton = options.outlineButton;
- this.attachmentsButton = options.attachmentsButton;
- this.thumbnailView = options.thumbnailView;
- this.outlineView = options.outlineView;
- this.attachmentsView = options.attachmentsView;
- this._addEventListeners();
- }
- PDFSidebar.prototype = {
- reset: function PDFSidebar_reset() {
- this.isInitialViewSet = false;
- this.close();
- this.switchView(SidebarView.THUMBS);
- this.outlineButton.disabled = false;
- this.attachmentsButton.disabled = false;
- },
- /**
- * @returns {number} One of the values in {SidebarView}.
- */
- get visibleView() {
- return this.isOpen ? this.active : SidebarView.NONE;
- },
- get isThumbnailViewVisible() {
- return this.isOpen && this.active === SidebarView.THUMBS;
- },
- get isOutlineViewVisible() {
- return this.isOpen && this.active === SidebarView.OUTLINE;
- },
- get isAttachmentsViewVisible() {
- return this.isOpen && this.active === SidebarView.ATTACHMENTS;
- },
- /**
- * @param {number} view - The sidebar view that should become visible,
- * must be one of the values in {SidebarView}.
- */
- setInitialView: function PDFSidebar_setInitialView(view) {
- if (this.isInitialViewSet) {
- return;
- }
- this.isInitialViewSet = true;
- if (this.isOpen && view === SidebarView.NONE) {
- this._dispatchEvent();
- // If the user has already manually opened the sidebar,
- // immediately closing it would be bad UX.
- return;
- }
- var isViewPreserved = view === this.visibleView;
- this.switchView(view, /* forceOpen */
- true);
- if (isViewPreserved) {
- // Prevent dispatching two back-to-back `sidebarviewchanged` events,
- // since `this.switchView` dispatched the event if the view changed.
- this._dispatchEvent();
- }
- },
- /**
- * @param {number} view - The sidebar view that should be switched to,
- * must be one of the values in {SidebarView}.
- * @param {boolean} forceOpen - (optional) Ensure that the sidebar is open.
- * The default value is false.
- */
- switchView: function PDFSidebar_switchView(view, forceOpen) {
- if (view === SidebarView.NONE) {
- this.close();
- return;
- }
- var isViewChanged = view !== this.active;
- var shouldForceRendering = false;
- switch (view) {
- case SidebarView.THUMBS:
- this.thumbnailButton.classList.add('toggled');
- this.outlineButton.classList.remove('toggled');
- this.attachmentsButton.classList.remove('toggled');
- this.thumbnailView.classList.remove('hidden');
- this.outlineView.classList.add('hidden');
- this.attachmentsView.classList.add('hidden');
- if (this.isOpen && isViewChanged) {
- this._updateThumbnailViewer();
- shouldForceRendering = true;
- }
- break;
- case SidebarView.OUTLINE:
- if (this.outlineButton.disabled) {
- return;
- }
- this.thumbnailButton.classList.remove('toggled');
- this.outlineButton.classList.add('toggled');
- this.attachmentsButton.classList.remove('toggled');
- this.thumbnailView.classList.add('hidden');
- this.outlineView.classList.remove('hidden');
- this.attachmentsView.classList.add('hidden');
- break;
- case SidebarView.ATTACHMENTS:
- if (this.attachmentsButton.disabled) {
- return;
- }
- this.thumbnailButton.classList.remove('toggled');
- this.outlineButton.classList.remove('toggled');
- this.attachmentsButton.classList.add('toggled');
- this.thumbnailView.classList.add('hidden');
- this.outlineView.classList.add('hidden');
- this.attachmentsView.classList.remove('hidden');
- break;
- default:
- console.error('PDFSidebar_switchView: "' + view + '" is an unsupported value.');
- return;
- }
- // Update the active view *after* it has been validated above,
- // in order to prevent setting it to an invalid state.
- this.active = view | 0;
- if (forceOpen && !this.isOpen) {
- this.open();
- // NOTE: `this.open` will trigger rendering, and dispatch the event.
- return;
- }
- if (shouldForceRendering) {
- this._forceRendering();
- }
- if (isViewChanged) {
- this._dispatchEvent();
- }
- },
- open: function PDFSidebar_open() {
- if (this.isOpen) {
- return;
- }
- this.isOpen = true;
- this.toggleButton.classList.add('toggled');
- this.outerContainer.classList.add('sidebarMoving');
- this.outerContainer.classList.add('sidebarOpen');
- if (this.active === SidebarView.THUMBS) {
- this._updateThumbnailViewer();
- }
- this._forceRendering();
- this._dispatchEvent();
- },
- close: function PDFSidebar_close() {
- if (!this.isOpen) {
- return;
- }
- this.isOpen = false;
- this.toggleButton.classList.remove('toggled');
- this.outerContainer.classList.add('sidebarMoving');
- this.outerContainer.classList.remove('sidebarOpen');
- this._forceRendering();
- this._dispatchEvent();
- },
- toggle: function PDFSidebar_toggle() {
- if (this.isOpen) {
- this.close();
- } else {
- this.open();
- }
- },
- /**
- * @private
- */
- _dispatchEvent: function PDFSidebar_dispatchEvent() {
- this.eventBus.dispatch('sidebarviewchanged', {
- source: this,
- view: this.visibleView
- });
- },
- /**
- * @private
- */
- _forceRendering: function PDFSidebar_forceRendering() {
- if (this.onToggled) {
- this.onToggled();
- } else {
- // Fallback
- this.pdfViewer.forceRendering();
- this.pdfThumbnailViewer.forceRendering();
- }
- },
- /**
- * @private
- */
- _updateThumbnailViewer: function PDFSidebar_updateThumbnailViewer() {
- var pdfViewer = this.pdfViewer;
- var thumbnailViewer = this.pdfThumbnailViewer;
- // Use the rendered pages to set the corresponding thumbnail images.
- var pagesCount = pdfViewer.pagesCount;
- for (var pageIndex = 0; pageIndex < pagesCount; pageIndex++) {
- var pageView = pdfViewer.getPageView(pageIndex);
- if (pageView && pageView.renderingState === RenderingStates.FINISHED) {
- var thumbnailView = thumbnailViewer.getThumbnail(pageIndex);
- thumbnailView.setImage(pageView);
- }
- }
- thumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber);
- },
- /**
- * @private
- */
- _addEventListeners: function PDFSidebar_addEventListeners() {
- var self = this;
- self.mainContainer.addEventListener('transitionend', function (evt) {
- if (evt.target === /* mainContainer */
- this) {
- self.outerContainer.classList.remove('sidebarMoving');
- }
- });
- // Buttons for switching views.
- self.thumbnailButton.addEventListener('click', function () {
- self.switchView(SidebarView.THUMBS);
- });
- self.outlineButton.addEventListener('click', function () {
- self.switchView(SidebarView.OUTLINE);
- });
- self.outlineButton.addEventListener('dblclick', function () {
- self.pdfOutlineViewer.toggleOutlineTree();
- });
- self.attachmentsButton.addEventListener('click', function () {
- self.switchView(SidebarView.ATTACHMENTS);
- });
- // Disable/enable views.
- self.eventBus.on('outlineloaded', function (e) {
- var outlineCount = e.outlineCount;
- self.outlineButton.disabled = !outlineCount;
- if (!outlineCount && self.active === SidebarView.OUTLINE) {
- self.switchView(SidebarView.THUMBS);
- }
- });
- self.eventBus.on('attachmentsloaded', function (e) {
- var attachmentsCount = e.attachmentsCount;
- self.attachmentsButton.disabled = !attachmentsCount;
- if (!attachmentsCount && self.active === SidebarView.ATTACHMENTS) {
- self.switchView(SidebarView.THUMBS);
- }
- });
- // Update the thumbnailViewer, if visible, when exiting presentation mode.
- self.eventBus.on('presentationmodechanged', function (e) {
- if (!e.active && !e.switchInProgress && self.isThumbnailViewVisible) {
- self._updateThumbnailViewer();
- }
- });
- }
- };
- return PDFSidebar;
- }();
- exports.SidebarView = SidebarView;
- exports.PDFSidebar = PDFSidebar;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebUIUtils = {}, root.pdfjsWebPDFJS);
- }(this, function (exports, pdfjsLib) {
- var CSS_UNITS = 96.0 / 72.0;
- var DEFAULT_SCALE_VALUE = 'auto';
- var DEFAULT_SCALE = 1.0;
- var UNKNOWN_SCALE = 0;
- var MAX_AUTO_SCALE = 1.25;
- var SCROLLBAR_PADDING = 40;
- var VERTICAL_PADDING = 5;
- var mozL10n = document.mozL10n || document.webL10n;
- var PDFJS = pdfjsLib.PDFJS;
- /**
- * Disables fullscreen support, and by extension Presentation Mode,
- * in browsers which support the fullscreen API.
- * @var {boolean}
- */
- PDFJS.disableFullscreen = PDFJS.disableFullscreen === undefined ? false : PDFJS.disableFullscreen;
- /**
- * Enables CSS only zooming.
- * @var {boolean}
- */
- PDFJS.useOnlyCssZoom = PDFJS.useOnlyCssZoom === undefined ? false : PDFJS.useOnlyCssZoom;
- /**
- * The maximum supported canvas size in total pixels e.g. width * height.
- * The default value is 4096 * 4096. Use -1 for no limit.
- * @var {number}
- */
- PDFJS.maxCanvasPixels = PDFJS.maxCanvasPixels === undefined ? 16777216 : PDFJS.maxCanvasPixels;
- /**
- * Disables saving of the last position of the viewed PDF.
- * @var {boolean}
- */
- PDFJS.disableHistory = PDFJS.disableHistory === undefined ? false : PDFJS.disableHistory;
- /**
- * Disables creation of the text layer that used for text selection and search.
- * @var {boolean}
- */
- PDFJS.disableTextLayer = PDFJS.disableTextLayer === undefined ? false : PDFJS.disableTextLayer;
- /**
- * Disables maintaining the current position in the document when zooming.
- */
- PDFJS.ignoreCurrentPositionOnZoom = PDFJS.ignoreCurrentPositionOnZoom === undefined ? false : PDFJS.ignoreCurrentPositionOnZoom;
- /**
- * Returns scale factor for the canvas. It makes sense for the HiDPI displays.
- * @return {Object} The object with horizontal (sx) and vertical (sy)
- scales. The scaled property is set to false if scaling is
- not required, true otherwise.
- */
- function getOutputScale(ctx) {
- var devicePixelRatio = window.devicePixelRatio || 1;
- var backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
- var pixelRatio = devicePixelRatio / backingStoreRatio;
- return {
- sx: pixelRatio,
- sy: pixelRatio,
- scaled: pixelRatio !== 1
- };
- }
- /**
- * Scrolls specified element into view of its parent.
- * @param {Object} element - The element to be visible.
- * @param {Object} spot - An object with optional top and left properties,
- * specifying the offset from the top left edge.
- * @param {boolean} skipOverflowHiddenElements - Ignore elements that have
- * the CSS rule `overflow: hidden;` set. The default is false.
- */
- function scrollIntoView(element, spot, skipOverflowHiddenElements) {
- // Assuming offsetParent is available (it's not available when viewer is in
- // hidden iframe or object). We have to scroll: if the offsetParent is not set
- // producing the error. See also animationStartedClosure.
- var parent = element.offsetParent;
- if (!parent) {
- console.error('offsetParent is not set -- cannot scroll');
- return;
- }
- var checkOverflow = skipOverflowHiddenElements || false;
- var offsetY = element.offsetTop + element.clientTop;
- var offsetX = element.offsetLeft + element.clientLeft;
- while (parent.clientHeight === parent.scrollHeight || checkOverflow && getComputedStyle(parent).overflow === 'hidden') {
- if (parent.dataset._scaleY) {
- offsetY /= parent.dataset._scaleY;
- offsetX /= parent.dataset._scaleX;
- }
- offsetY += parent.offsetTop;
- offsetX += parent.offsetLeft;
- parent = parent.offsetParent;
- if (!parent) {
- return;
- }
- }
- // no need to scroll
- if (spot) {
- if (spot.top !== undefined) {
- offsetY += spot.top;
- }
- if (spot.left !== undefined) {
- offsetX += spot.left;
- parent.scrollLeft = offsetX;
- }
- }
- parent.scrollTop = offsetY;
- }
- /**
- * Helper function to start monitoring the scroll event and converting them into
- * PDF.js friendly one: with scroll debounce and scroll direction.
- */
- function watchScroll(viewAreaElement, callback) {
- var debounceScroll = function debounceScroll(evt) {
- if (rAF) {
- return;
- }
- // schedule an invocation of scroll for next animation frame.
- rAF = window.requestAnimationFrame(function viewAreaElementScrolled() {
- rAF = null;
- var currentY = viewAreaElement.scrollTop;
- var lastY = state.lastY;
- if (currentY !== lastY) {
- state.down = currentY > lastY;
- }
- state.lastY = currentY;
- callback(state);
- });
- };
- var state = {
- down: true,
- lastY: viewAreaElement.scrollTop,
- _eventHandler: debounceScroll
- };
- var rAF = null;
- viewAreaElement.addEventListener('scroll', debounceScroll, true);
- return state;
- }
- /**
- * Helper function to parse query string (e.g. ?param1=value&parm2=...).
- */
- function parseQueryString(query) {
- var parts = query.split('&');
- var params = {};
- for (var i = 0, ii = parts.length; i < ii; ++i) {
- var param = parts[i].split('=');
- var key = param[0].toLowerCase();
- var value = param.length > 1 ? param[1] : null;
- params[decodeURIComponent(key)] = decodeURIComponent(value);
- }
- return params;
- }
- /**
- * Use binary search to find the index of the first item in a given array which
- * passes a given condition. The items are expected to be sorted in the sense
- * that if the condition is true for one item in the array, then it is also true
- * for all following items.
- *
- * @returns {Number} Index of the first array element to pass the test,
- * or |items.length| if no such element exists.
- */
- function binarySearchFirstItem(items, condition) {
- var minIndex = 0;
- var maxIndex = items.length - 1;
- if (items.length === 0 || !condition(items[maxIndex])) {
- return items.length;
- }
- if (condition(items[minIndex])) {
- return minIndex;
- }
- while (minIndex < maxIndex) {
- var currentIndex = minIndex + maxIndex >> 1;
- var currentItem = items[currentIndex];
- if (condition(currentItem)) {
- maxIndex = currentIndex;
- } else {
- minIndex = currentIndex + 1;
- }
- }
- return minIndex;
- }
- /* === maxIndex */
- /**
- * Approximates float number as a fraction using Farey sequence (max order
- * of 8).
- * @param {number} x - Positive float number.
- * @returns {Array} Estimated fraction: the first array item is a numerator,
- * the second one is a denominator.
- */
- function approximateFraction(x) {
- // Fast paths for int numbers or their inversions.
- if (Math.floor(x) === x) {
- return [
- x,
- 1
- ];
- }
- var xinv = 1 / x;
- var limit = 8;
- if (xinv > limit) {
- return [
- 1,
- limit
- ];
- } else if (Math.floor(xinv) === xinv) {
- return [
- 1,
- xinv
- ];
- }
- var x_ = x > 1 ? xinv : x;
- // a/b and c/d are neighbours in Farey sequence.
- var a = 0, b = 1, c = 1, d = 1;
- // Limiting search to order 8.
- while (true) {
- // Generating next term in sequence (order of q).
- var p = a + c, q = b + d;
- if (q > limit) {
- break;
- }
- if (x_ <= p / q) {
- c = p;
- d = q;
- } else {
- a = p;
- b = q;
- }
- }
- // Select closest of the neighbours to x.
- if (x_ - a / b < c / d - x_) {
- return x_ === x ? [
- a,
- b
- ] : [
- b,
- a
- ];
- } else {
- return x_ === x ? [
- c,
- d
- ] : [
- d,
- c
- ];
- }
- }
- function roundToDivide(x, div) {
- var r = x % div;
- return r === 0 ? x : Math.round(x - r + div);
- }
- /**
- * Generic helper to find out what elements are visible within a scroll pane.
- */
- function getVisibleElements(scrollEl, views, sortByVisibility) {
- var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight;
- var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth;
- function isElementBottomBelowViewTop(view) {
- var element = view.div;
- var elementBottom = element.offsetTop + element.clientTop + element.clientHeight;
- return elementBottom > top;
- }
- var visible = [], view, element;
- var currentHeight, viewHeight, hiddenHeight, percentHeight;
- var currentWidth, viewWidth;
- var firstVisibleElementInd = views.length === 0 ? 0 : binarySearchFirstItem(views, isElementBottomBelowViewTop);
- for (var i = firstVisibleElementInd, ii = views.length; i < ii; i++) {
- view = views[i];
- element = view.div;
- currentHeight = element.offsetTop + element.clientTop;
- viewHeight = element.clientHeight;
- if (currentHeight > bottom) {
- break;
- }
- currentWidth = element.offsetLeft + element.clientLeft;
- viewWidth = element.clientWidth;
- if (currentWidth + viewWidth < left || currentWidth > right) {
- continue;
- }
- hiddenHeight = Math.max(0, top - currentHeight) + Math.max(0, currentHeight + viewHeight - bottom);
- percentHeight = (viewHeight - hiddenHeight) * 100 / viewHeight | 0;
- visible.push({
- id: view.id,
- x: currentWidth,
- y: currentHeight,
- view: view,
- percent: percentHeight
- });
- }
- var first = visible[0];
- var last = visible[visible.length - 1];
- if (sortByVisibility) {
- visible.sort(function (a, b) {
- var pc = a.percent - b.percent;
- if (Math.abs(pc) > 0.001) {
- return -pc;
- }
- return a.id - b.id;
- });
- }
- // ensure stability
- return {
- first: first,
- last: last,
- views: visible
- };
- }
- /**
- * Event handler to suppress context menu.
- */
- function noContextMenuHandler(e) {
- e.preventDefault();
- }
- /**
- * Returns the filename or guessed filename from the url (see issue 3455).
- * url {String} The original PDF location.
- * @return {String} Guessed PDF file name.
- */
- function getPDFFileNameFromURL(url) {
- var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
- // SCHEME HOST 1.PATH 2.QUERY 3.REF
- // Pattern to get last matching NAME.pdf
- var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
- var splitURI = reURI.exec(url);
- var suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]);
- if (suggestedFilename) {
- suggestedFilename = suggestedFilename[0];
- if (suggestedFilename.indexOf('%') !== -1) {
- // URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
- try {
- suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0];
- } catch (e) {
- }
- }
- }
- return suggestedFilename || 'document.pdf';
- }
- function normalizeWheelEventDelta(evt) {
- var delta = Math.sqrt(evt.deltaX * evt.deltaX + evt.deltaY * evt.deltaY);
- var angle = Math.atan2(evt.deltaY, evt.deltaX);
- if (-0.25 * Math.PI < angle && angle < 0.75 * Math.PI) {
- // All that is left-up oriented has to change the sign.
- delta = -delta;
- }
- var MOUSE_DOM_DELTA_PIXEL_MODE = 0;
- var MOUSE_DOM_DELTA_LINE_MODE = 1;
- var MOUSE_PIXELS_PER_LINE = 30;
- var MOUSE_LINES_PER_PAGE = 30;
- // Converts delta to per-page units
- if (evt.deltaMode === MOUSE_DOM_DELTA_PIXEL_MODE) {
- delta /= MOUSE_PIXELS_PER_LINE * MOUSE_LINES_PER_PAGE;
- } else if (evt.deltaMode === MOUSE_DOM_DELTA_LINE_MODE) {
- delta /= MOUSE_LINES_PER_PAGE;
- }
- return delta;
- }
- /**
- * Simple event bus for an application. Listeners are attached using the
- * `on` and `off` methods. To raise an event, the `dispatch` method shall be
- * used.
- */
- var EventBus = function EventBusClosure() {
- function EventBus() {
- this._listeners = Object.create(null);
- }
- EventBus.prototype = {
- on: function EventBus_on(eventName, listener) {
- var eventListeners = this._listeners[eventName];
- if (!eventListeners) {
- eventListeners = [];
- this._listeners[eventName] = eventListeners;
- }
- eventListeners.push(listener);
- },
- off: function EventBus_on(eventName, listener) {
- var eventListeners = this._listeners[eventName];
- var i;
- if (!eventListeners || (i = eventListeners.indexOf(listener)) < 0) {
- return;
- }
- eventListeners.splice(i, 1);
- },
- dispatch: function EventBus_dispath(eventName) {
- var eventListeners = this._listeners[eventName];
- if (!eventListeners || eventListeners.length === 0) {
- return;
- }
- // Passing all arguments after the eventName to the listeners.
- var args = Array.prototype.slice.call(arguments, 1);
- // Making copy of the listeners array in case if it will be modified
- // during dispatch.
- eventListeners.slice(0).forEach(function (listener) {
- listener.apply(null, args);
- });
- }
- };
- return EventBus;
- }();
- var ProgressBar = function ProgressBarClosure() {
- function clamp(v, min, max) {
- return Math.min(Math.max(v, min), max);
- }
- function ProgressBar(id, opts) {
- this.visible = true;
- // Fetch the sub-elements for later.
- this.div = document.querySelector(id + ' .progress');
- // Get the loading bar element, so it can be resized to fit the viewer.
- this.bar = this.div.parentNode;
- // Get options, with sensible defaults.
- this.height = opts.height || 100;
- this.width = opts.width || 100;
- this.units = opts.units || '%';
- // Initialize heights.
- this.div.style.height = this.height + this.units;
- this.percent = 0;
- }
- ProgressBar.prototype = {
- updateBar: function ProgressBar_updateBar() {
- if (this._indeterminate) {
- this.div.classList.add('indeterminate');
- this.div.style.width = this.width + this.units;
- return;
- }
- this.div.classList.remove('indeterminate');
- var progressSize = this.width * this._percent / 100;
- this.div.style.width = progressSize + this.units;
- },
- get percent() {
- return this._percent;
- },
- set percent(val) {
- this._indeterminate = isNaN(val);
- this._percent = clamp(val, 0, 100);
- this.updateBar();
- },
- setWidth: function ProgressBar_setWidth(viewer) {
- if (viewer) {
- var container = viewer.parentNode;
- var scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
- if (scrollbarWidth > 0) {
- this.bar.setAttribute('style', 'width: calc(100% - ' + scrollbarWidth + 'px);');
- }
- }
- },
- hide: function ProgressBar_hide() {
- if (!this.visible) {
- return;
- }
- this.visible = false;
- this.bar.classList.add('hidden');
- document.body.classList.remove('loadingInProgress');
- },
- show: function ProgressBar_show() {
- if (this.visible) {
- return;
- }
- this.visible = true;
- document.body.classList.add('loadingInProgress');
- this.bar.classList.remove('hidden');
- }
- };
- return ProgressBar;
- }();
- exports.CSS_UNITS = CSS_UNITS;
- exports.DEFAULT_SCALE_VALUE = DEFAULT_SCALE_VALUE;
- exports.DEFAULT_SCALE = DEFAULT_SCALE;
- exports.UNKNOWN_SCALE = UNKNOWN_SCALE;
- exports.MAX_AUTO_SCALE = MAX_AUTO_SCALE;
- exports.SCROLLBAR_PADDING = SCROLLBAR_PADDING;
- exports.VERTICAL_PADDING = VERTICAL_PADDING;
- exports.mozL10n = mozL10n;
- exports.EventBus = EventBus;
- exports.ProgressBar = ProgressBar;
- exports.getPDFFileNameFromURL = getPDFFileNameFromURL;
- exports.noContextMenuHandler = noContextMenuHandler;
- exports.parseQueryString = parseQueryString;
- exports.getVisibleElements = getVisibleElements;
- exports.roundToDivide = roundToDivide;
- exports.approximateFraction = approximateFraction;
- exports.getOutputScale = getOutputScale;
- exports.scrollIntoView = scrollIntoView;
- exports.watchScroll = watchScroll;
- exports.binarySearchFirstItem = binarySearchFirstItem;
- exports.normalizeWheelEventDelta = normalizeWheelEventDelta;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebDOMEvents = {}, root.pdfjsWebUIUtils);
- }(this, function (exports, uiUtils) {
- var EventBus = uiUtils.EventBus;
- // Attaching to the application event bus to dispatch events to the DOM for
- // backwards viewer API compatibility.
- function attachDOMEventsToEventBus(eventBus) {
- eventBus.on('documentload', function () {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('documentload', true, true, {});
- window.dispatchEvent(event);
- });
- eventBus.on('pagerendered', function (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('pagerendered', true, true, {
- pageNumber: e.pageNumber,
- cssTransform: e.cssTransform
- });
- e.source.div.dispatchEvent(event);
- });
- eventBus.on('textlayerrendered', function (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('textlayerrendered', true, true, { pageNumber: e.pageNumber });
- e.source.textLayerDiv.dispatchEvent(event);
- });
- eventBus.on('pagechange', function (e) {
- var event = document.createEvent('UIEvents');
- event.initUIEvent('pagechange', true, true, window, 0);
- event.pageNumber = e.pageNumber;
- e.source.container.dispatchEvent(event);
- });
- eventBus.on('pagesinit', function (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('pagesinit', true, true, null);
- e.source.container.dispatchEvent(event);
- });
- eventBus.on('pagesloaded', function (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('pagesloaded', true, true, { pagesCount: e.pagesCount });
- e.source.container.dispatchEvent(event);
- });
- eventBus.on('scalechange', function (e) {
- var event = document.createEvent('UIEvents');
- event.initUIEvent('scalechange', true, true, window, 0);
- event.scale = e.scale;
- event.presetValue = e.presetValue;
- e.source.container.dispatchEvent(event);
- });
- eventBus.on('updateviewarea', function (e) {
- var event = document.createEvent('UIEvents');
- event.initUIEvent('updateviewarea', true, true, window, 0);
- event.location = e.location;
- e.source.container.dispatchEvent(event);
- });
- eventBus.on('find', function (e) {
- if (e.source === window) {
- return;
- }
- // event comes from FirefoxCom, no need to replicate
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('find' + e.type, true, true, {
- query: e.query,
- phraseSearch: e.phraseSearch,
- caseSensitive: e.caseSensitive,
- highlightAll: e.highlightAll,
- findPrevious: e.findPrevious
- });
- window.dispatchEvent(event);
- });
- eventBus.on('attachmentsloaded', function (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('attachmentsloaded', true, true, { attachmentsCount: e.attachmentsCount });
- e.source.container.dispatchEvent(event);
- });
- eventBus.on('sidebarviewchanged', function (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('sidebarviewchanged', true, true, { view: e.view });
- e.source.outerContainer.dispatchEvent(event);
- });
- eventBus.on('pagemode', function (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('pagemode', true, true, { mode: e.mode });
- e.source.pdfViewer.container.dispatchEvent(event);
- });
- eventBus.on('namedaction', function (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('namedaction', true, true, { action: e.action });
- e.source.pdfViewer.container.dispatchEvent(event);
- });
- eventBus.on('presentationmodechanged', function (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('presentationmodechanged', true, true, {
- active: e.active,
- switchInProgress: e.switchInProgress
- });
- window.dispatchEvent(event);
- });
- eventBus.on('outlineloaded', function (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('outlineloaded', true, true, { outlineCount: e.outlineCount });
- e.source.container.dispatchEvent(event);
- });
- }
- var globalEventBus = null;
- function getGlobalEventBus() {
- if (globalEventBus) {
- return globalEventBus;
- }
- globalEventBus = new EventBus();
- attachDOMEventsToEventBus(globalEventBus);
- return globalEventBus;
- }
- exports.attachDOMEventsToEventBus = attachDOMEventsToEventBus;
- exports.getGlobalEventBus = getGlobalEventBus;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPasswordPrompt = {}, root.pdfjsWebUIUtils, root.pdfjsWebOverlayManager, root.pdfjsWebPDFJS);
- }(this, function (exports, uiUtils, overlayManager, pdfjsLib) {
- var mozL10n = uiUtils.mozL10n;
- var OverlayManager = overlayManager.OverlayManager;
- /**
- * @typedef {Object} PasswordPromptOptions
- * @property {string} overlayName - Name of the overlay for the overlay manager.
- * @property {HTMLDivElement} container - Div container for the overlay.
- * @property {HTMLParagraphElement} label - Label containing instructions for
- * entering the password.
- * @property {HTMLInputElement} input - Input field for entering the password.
- * @property {HTMLButtonElement} submitButton - Button for submitting the
- * password.
- * @property {HTMLButtonElement} cancelButton - Button for cancelling password
- * entry.
- */
- /**
- * @class
- */
- var PasswordPrompt = function PasswordPromptClosure() {
- /**
- * @constructs PasswordPrompt
- * @param {PasswordPromptOptions} options
- */
- function PasswordPrompt(options) {
- this.overlayName = options.overlayName;
- this.container = options.container;
- this.label = options.label;
- this.input = options.input;
- this.submitButton = options.submitButton;
- this.cancelButton = options.cancelButton;
- this.updateCallback = null;
- this.reason = null;
- // Attach the event listeners.
- this.submitButton.addEventListener('click', this.verify.bind(this));
- this.cancelButton.addEventListener('click', this.close.bind(this));
- this.input.addEventListener('keydown', function (e) {
- if (e.keyCode === 13) {
- // Enter key
- this.verify();
- }
- }.bind(this));
- OverlayManager.register(this.overlayName, this.container, this.close.bind(this), true);
- }
- PasswordPrompt.prototype = {
- open: function PasswordPrompt_open() {
- OverlayManager.open(this.overlayName).then(function () {
- this.input.type = 'password';
- this.input.focus();
- var promptString = mozL10n.get('password_label', null, 'Enter the password to open this PDF file.');
- if (this.reason === pdfjsLib.PasswordResponses.INCORRECT_PASSWORD) {
- promptString = mozL10n.get('password_invalid', null, 'Invalid password. Please try again.');
- }
- this.label.textContent = promptString;
- }.bind(this));
- },
- close: function PasswordPrompt_close() {
- OverlayManager.close(this.overlayName).then(function () {
- this.input.value = '';
- this.input.type = '';
- }.bind(this));
- },
- verify: function PasswordPrompt_verify() {
- var password = this.input.value;
- if (password && password.length > 0) {
- this.close();
- return this.updateCallback(password);
- }
- },
- setUpdateCallback: function PasswordPrompt_setUpdateCallback(updateCallback, reason) {
- this.updateCallback = updateCallback;
- this.reason = reason;
- }
- };
- return PasswordPrompt;
- }();
- exports.PasswordPrompt = PasswordPrompt;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFDocumentProperties = {}, root.pdfjsWebUIUtils, root.pdfjsWebOverlayManager);
- }(this, function (exports, uiUtils, overlayManager) {
- var getPDFFileNameFromURL = uiUtils.getPDFFileNameFromURL;
- var mozL10n = uiUtils.mozL10n;
- var OverlayManager = overlayManager.OverlayManager;
- /**
- * @typedef {Object} PDFDocumentPropertiesOptions
- * @property {string} overlayName - Name/identifier for the overlay.
- * @property {Object} fields - Names and elements of the overlay's fields.
- * @property {HTMLButtonElement} closeButton - Button for closing the overlay.
- */
- /**
- * @class
- */
- var PDFDocumentProperties = function PDFDocumentPropertiesClosure() {
- /**
- * @constructs PDFDocumentProperties
- * @param {PDFDocumentPropertiesOptions} options
- */
- function PDFDocumentProperties(options) {
- this.fields = options.fields;
- this.overlayName = options.overlayName;
- this.container = options.container;
- this.rawFileSize = 0;
- this.url = null;
- this.pdfDocument = null;
- // Bind the event listener for the Close button.
- if (options.closeButton) {
- options.closeButton.addEventListener('click', this.close.bind(this));
- }
- this.dataAvailablePromise = new Promise(function (resolve) {
- this.resolveDataAvailable = resolve;
- }.bind(this));
- OverlayManager.register(this.overlayName, this.container, this.close.bind(this));
- }
- PDFDocumentProperties.prototype = {
- /**
- * Open the document properties overlay.
- */
- open: function PDFDocumentProperties_open() {
- Promise.all([
- OverlayManager.open(this.overlayName),
- this.dataAvailablePromise
- ]).then(function () {
- this._getProperties();
- }.bind(this));
- },
- /**
- * Close the document properties overlay.
- */
- close: function PDFDocumentProperties_close() {
- OverlayManager.close(this.overlayName);
- },
- /**
- * Set the file size of the PDF document. This method is used to
- * update the file size in the document properties overlay once it
- * is known so we do not have to wait until the entire file is loaded.
- *
- * @param {number} fileSize - The file size of the PDF document.
- */
- setFileSize: function PDFDocumentProperties_setFileSize(fileSize) {
- if (fileSize > 0) {
- this.rawFileSize = fileSize;
- }
- },
- /**
- * Set a reference to the PDF document and the URL in order
- * to populate the overlay fields with the document properties.
- * Note that the overlay will contain no information if this method
- * is not called.
- *
- * @param {Object} pdfDocument - A reference to the PDF document.
- * @param {string} url - The URL of the document.
- */
- setDocumentAndUrl: function PDFDocumentProperties_setDocumentAndUrl(pdfDocument, url) {
- this.pdfDocument = pdfDocument;
- this.url = url;
- this.resolveDataAvailable();
- },
- /**
- * @private
- */
- _getProperties: function PDFDocumentProperties_getProperties() {
- if (!OverlayManager.active) {
- // If the dialog was closed before dataAvailablePromise was resolved,
- // don't bother updating the properties.
- return;
- }
- // Get the file size (if it hasn't already been set).
- this.pdfDocument.getDownloadInfo().then(function (data) {
- if (data.length === this.rawFileSize) {
- return;
- }
- this.setFileSize(data.length);
- this._updateUI(this.fields['fileSize'], this._parseFileSize());
- }.bind(this));
- // Get the document properties.
- this.pdfDocument.getMetadata().then(function (data) {
- var content = {
- 'fileName': getPDFFileNameFromURL(this.url),
- 'fileSize': this._parseFileSize(),
- 'title': data.info.Title,
- 'author': data.info.Author,
- 'subject': data.info.Subject,
- 'keywords': data.info.Keywords,
- 'creationDate': this._parseDate(data.info.CreationDate),
- 'modificationDate': this._parseDate(data.info.ModDate),
- 'creator': data.info.Creator,
- 'producer': data.info.Producer,
- 'version': data.info.PDFFormatVersion,
- 'pageCount': this.pdfDocument.numPages
- };
- // Show the properties in the dialog.
- for (var identifier in content) {
- this._updateUI(this.fields[identifier], content[identifier]);
- }
- }.bind(this));
- },
- /**
- * @private
- */
- _updateUI: function PDFDocumentProperties_updateUI(field, content) {
- if (field && content !== undefined && content !== '') {
- field.textContent = content;
- }
- },
- /**
- * @private
- */
- _parseFileSize: function PDFDocumentProperties_parseFileSize() {
- var fileSize = this.rawFileSize, kb = fileSize / 1024;
- if (!kb) {
- return;
- } else if (kb < 1024) {
- return mozL10n.get('document_properties_kb', {
- size_kb: (+kb.toPrecision(3)).toLocaleString(),
- size_b: fileSize.toLocaleString()
- }, '{{size_kb}} KB ({{size_b}} bytes)');
- } else {
- return mozL10n.get('document_properties_mb', {
- size_mb: (+(kb / 1024).toPrecision(3)).toLocaleString(),
- size_b: fileSize.toLocaleString()
- }, '{{size_mb}} MB ({{size_b}} bytes)');
- }
- },
- /**
- * @private
- */
- _parseDate: function PDFDocumentProperties_parseDate(inputDate) {
- // This is implemented according to the PDF specification, but note that
- // Adobe Reader doesn't handle changing the date to universal time
- // and doesn't use the user's time zone (they're effectively ignoring
- // the HH' and mm' parts of the date string).
- var dateToParse = inputDate;
- if (dateToParse === undefined) {
- return '';
- }
- // Remove the D: prefix if it is available.
- if (dateToParse.substring(0, 2) === 'D:') {
- dateToParse = dateToParse.substring(2);
- }
- // Get all elements from the PDF date string.
- // JavaScript's Date object expects the month to be between
- // 0 and 11 instead of 1 and 12, so we're correcting for this.
- var year = parseInt(dateToParse.substring(0, 4), 10);
- var month = parseInt(dateToParse.substring(4, 6), 10) - 1;
- var day = parseInt(dateToParse.substring(6, 8), 10);
- var hours = parseInt(dateToParse.substring(8, 10), 10);
- var minutes = parseInt(dateToParse.substring(10, 12), 10);
- var seconds = parseInt(dateToParse.substring(12, 14), 10);
- var utRel = dateToParse.substring(14, 15);
- var offsetHours = parseInt(dateToParse.substring(15, 17), 10);
- var offsetMinutes = parseInt(dateToParse.substring(18, 20), 10);
- // As per spec, utRel = 'Z' means equal to universal time.
- // The other cases ('-' and '+') have to be handled here.
- if (utRel === '-') {
- hours += offsetHours;
- minutes += offsetMinutes;
- } else if (utRel === '+') {
- hours -= offsetHours;
- minutes -= offsetMinutes;
- }
- // Return the new date format from the user's locale.
- var date = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
- var dateString = date.toLocaleDateString();
- var timeString = date.toLocaleTimeString();
- return mozL10n.get('document_properties_date_string', {
- date: dateString,
- time: timeString
- }, '{{date}}, {{time}}');
- }
- };
- return PDFDocumentProperties;
- }();
- exports.PDFDocumentProperties = PDFDocumentProperties;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFFindController = {}, root.pdfjsWebUIUtils);
- }(this, function (exports, uiUtils) {
- var scrollIntoView = uiUtils.scrollIntoView;
- var FindStates = {
- FIND_FOUND: 0,
- FIND_NOTFOUND: 1,
- FIND_WRAPPED: 2,
- FIND_PENDING: 3
- };
- var FIND_SCROLL_OFFSET_TOP = -50;
- var FIND_SCROLL_OFFSET_LEFT = -400;
- var CHARACTERS_TO_NORMALIZE = {
- '\u2018': '\'',
- // Left single quotation mark
- '\u2019': '\'',
- // Right single quotation mark
- '\u201A': '\'',
- // Single low-9 quotation mark
- '\u201B': '\'',
- // Single high-reversed-9 quotation mark
- '\u201C': '"',
- // Left double quotation mark
- '\u201D': '"',
- // Right double quotation mark
- '\u201E': '"',
- // Double low-9 quotation mark
- '\u201F': '"',
- // Double high-reversed-9 quotation mark
- '\u00BC': '1/4',
- // Vulgar fraction one quarter
- '\u00BD': '1/2',
- // Vulgar fraction one half
- '\u00BE': '3/4'
- };
- // Vulgar fraction three quarters
- /**
- * Provides "search" or "find" functionality for the PDF.
- * This object actually performs the search for a given string.
- */
- var PDFFindController = function PDFFindControllerClosure() {
- function PDFFindController(options) {
- this.pdfViewer = options.pdfViewer || null;
- this.onUpdateResultsCount = null;
- this.onUpdateState = null;
- this.reset();
- // Compile the regular expression for text normalization once.
- var replace = Object.keys(CHARACTERS_TO_NORMALIZE).join('');
- this.normalizationRegex = new RegExp('[' + replace + ']', 'g');
- }
- PDFFindController.prototype = {
- reset: function PDFFindController_reset() {
- this.startedTextExtraction = false;
- this.extractTextPromises = [];
- this.pendingFindMatches = Object.create(null);
- this.active = false;
- // If active, find results will be highlighted.
- this.pageContents = [];
- // Stores the text for each page.
- this.pageMatches = [];
- this.pageMatchesLength = null;
- this.matchCount = 0;
- this.selected = {
- // Currently selected match.
- pageIdx: -1,
- matchIdx: -1
- };
- this.offset = {
- // Where the find algorithm currently is in the document.
- pageIdx: null,
- matchIdx: null
- };
- this.pagesToSearch = null;
- this.resumePageIdx = null;
- this.state = null;
- this.dirtyMatch = false;
- this.findTimeout = null;
- this.firstPagePromise = new Promise(function (resolve) {
- this.resolveFirstPage = resolve;
- }.bind(this));
- },
- normalize: function PDFFindController_normalize(text) {
- return text.replace(this.normalizationRegex, function (ch) {
- return CHARACTERS_TO_NORMALIZE[ch];
- });
- },
- // Helper for multiple search - fills matchesWithLength array
- // and takes into account cases when one search term
- // include another search term (for example, "tamed tame" or "this is").
- // Looking for intersecting terms in the 'matches' and
- // leave elements with a longer match-length.
- _prepareMatches: function PDFFindController_prepareMatches(matchesWithLength, matches, matchesLength) {
- function isSubTerm(matchesWithLength, currentIndex) {
- var currentElem, prevElem, nextElem;
- currentElem = matchesWithLength[currentIndex];
- nextElem = matchesWithLength[currentIndex + 1];
- // checking for cases like "TAMEd TAME"
- if (currentIndex < matchesWithLength.length - 1 && currentElem.match === nextElem.match) {
- currentElem.skipped = true;
- return true;
- }
- // checking for cases like "thIS IS"
- for (var i = currentIndex - 1; i >= 0; i--) {
- prevElem = matchesWithLength[i];
- if (prevElem.skipped) {
- continue;
- }
- if (prevElem.match + prevElem.matchLength < currentElem.match) {
- break;
- }
- if (prevElem.match + prevElem.matchLength >= currentElem.match + currentElem.matchLength) {
- currentElem.skipped = true;
- return true;
- }
- }
- return false;
- }
- var i, len;
- // Sorting array of objects { match: <match>, matchLength: <matchLength> }
- // in increasing index first and then the lengths.
- matchesWithLength.sort(function (a, b) {
- return a.match === b.match ? a.matchLength - b.matchLength : a.match - b.match;
- });
- for (i = 0, len = matchesWithLength.length; i < len; i++) {
- if (isSubTerm(matchesWithLength, i)) {
- continue;
- }
- matches.push(matchesWithLength[i].match);
- matchesLength.push(matchesWithLength[i].matchLength);
- }
- },
- calcFindPhraseMatch: function PDFFindController_calcFindPhraseMatch(query, pageIndex, pageContent) {
- var matches = [];
- var queryLen = query.length;
- var matchIdx = -queryLen;
- while (true) {
- matchIdx = pageContent.indexOf(query, matchIdx + queryLen);
- if (matchIdx === -1) {
- break;
- }
- matches.push(matchIdx);
- }
- this.pageMatches[pageIndex] = matches;
- },
- calcFindWordMatch: function PDFFindController_calcFindWordMatch(query, pageIndex, pageContent) {
- var matchesWithLength = [];
- // Divide the query into pieces and search for text on each piece.
- var queryArray = query.match(/\S+/g);
- var subquery, subqueryLen, matchIdx;
- for (var i = 0, len = queryArray.length; i < len; i++) {
- subquery = queryArray[i];
- subqueryLen = subquery.length;
- matchIdx = -subqueryLen;
- while (true) {
- matchIdx = pageContent.indexOf(subquery, matchIdx + subqueryLen);
- if (matchIdx === -1) {
- break;
- }
- // Other searches do not, so we store the length.
- matchesWithLength.push({
- match: matchIdx,
- matchLength: subqueryLen,
- skipped: false
- });
- }
- }
- // Prepare arrays for store the matches.
- if (!this.pageMatchesLength) {
- this.pageMatchesLength = [];
- }
- this.pageMatchesLength[pageIndex] = [];
- this.pageMatches[pageIndex] = [];
- // Sort matchesWithLength, clean up intersecting terms
- // and put the result into the two arrays.
- this._prepareMatches(matchesWithLength, this.pageMatches[pageIndex], this.pageMatchesLength[pageIndex]);
- },
- calcFindMatch: function PDFFindController_calcFindMatch(pageIndex) {
- var pageContent = this.normalize(this.pageContents[pageIndex]);
- var query = this.normalize(this.state.query);
- var caseSensitive = this.state.caseSensitive;
- var phraseSearch = this.state.phraseSearch;
- var queryLen = query.length;
- if (queryLen === 0) {
- // Do nothing: the matches should be wiped out already.
- return;
- }
- if (!caseSensitive) {
- pageContent = pageContent.toLowerCase();
- query = query.toLowerCase();
- }
- if (phraseSearch) {
- this.calcFindPhraseMatch(query, pageIndex, pageContent);
- } else {
- this.calcFindWordMatch(query, pageIndex, pageContent);
- }
- this.updatePage(pageIndex);
- if (this.resumePageIdx === pageIndex) {
- this.resumePageIdx = null;
- this.nextPageMatch();
- }
- // Update the matches count
- if (this.pageMatches[pageIndex].length > 0) {
- this.matchCount += this.pageMatches[pageIndex].length;
- this.updateUIResultsCount();
- }
- },
- extractText: function PDFFindController_extractText() {
- if (this.startedTextExtraction) {
- return;
- }
- this.startedTextExtraction = true;
- this.pageContents = [];
- var extractTextPromisesResolves = [];
- var numPages = this.pdfViewer.pagesCount;
- for (var i = 0; i < numPages; i++) {
- this.extractTextPromises.push(new Promise(function (resolve) {
- extractTextPromisesResolves.push(resolve);
- }));
- }
- var self = this;
- function extractPageText(pageIndex) {
- self.pdfViewer.getPageTextContent(pageIndex).then(function textContentResolved(textContent) {
- var textItems = textContent.items;
- var str = [];
- for (var i = 0, len = textItems.length; i < len; i++) {
- str.push(textItems[i].str);
- }
- // Store the pageContent as a string.
- self.pageContents.push(str.join(''));
- extractTextPromisesResolves[pageIndex](pageIndex);
- if (pageIndex + 1 < self.pdfViewer.pagesCount) {
- extractPageText(pageIndex + 1);
- }
- });
- }
- extractPageText(0);
- },
- executeCommand: function PDFFindController_executeCommand(cmd, state) {
- if (this.state === null || cmd !== 'findagain') {
- this.dirtyMatch = true;
- }
- this.state = state;
- this.updateUIState(FindStates.FIND_PENDING);
- this.firstPagePromise.then(function () {
- this.extractText();
- clearTimeout(this.findTimeout);
- if (cmd === 'find') {
- // Only trigger the find action after 250ms of silence.
- this.findTimeout = setTimeout(this.nextMatch.bind(this), 250);
- } else {
- this.nextMatch();
- }
- }.bind(this));
- },
- updatePage: function PDFFindController_updatePage(index) {
- if (this.selected.pageIdx === index) {
- // If the page is selected, scroll the page into view, which triggers
- // rendering the page, which adds the textLayer. Once the textLayer is
- // build, it will scroll onto the selected match.
- this.pdfViewer.currentPageNumber = index + 1;
- }
- var page = this.pdfViewer.getPageView(index);
- if (page.textLayer) {
- page.textLayer.updateMatches();
- }
- },
- nextMatch: function PDFFindController_nextMatch() {
- var previous = this.state.findPrevious;
- var currentPageIndex = this.pdfViewer.currentPageNumber - 1;
- var numPages = this.pdfViewer.pagesCount;
- this.active = true;
- if (this.dirtyMatch) {
- // Need to recalculate the matches, reset everything.
- this.dirtyMatch = false;
- this.selected.pageIdx = this.selected.matchIdx = -1;
- this.offset.pageIdx = currentPageIndex;
- this.offset.matchIdx = null;
- this.hadMatch = false;
- this.resumePageIdx = null;
- this.pageMatches = [];
- this.matchCount = 0;
- this.pageMatchesLength = null;
- var self = this;
- for (var i = 0; i < numPages; i++) {
- // Wipe out any previous highlighted matches.
- this.updatePage(i);
- // As soon as the text is extracted start finding the matches.
- if (!(i in this.pendingFindMatches)) {
- this.pendingFindMatches[i] = true;
- this.extractTextPromises[i].then(function (pageIdx) {
- delete self.pendingFindMatches[pageIdx];
- self.calcFindMatch(pageIdx);
- });
- }
- }
- }
- // If there's no query there's no point in searching.
- if (this.state.query === '') {
- this.updateUIState(FindStates.FIND_FOUND);
- return;
- }
- // If we're waiting on a page, we return since we can't do anything else.
- if (this.resumePageIdx) {
- return;
- }
- var offset = this.offset;
- // Keep track of how many pages we should maximally iterate through.
- this.pagesToSearch = numPages;
- // If there's already a matchIdx that means we are iterating through a
- // page's matches.
- if (offset.matchIdx !== null) {
- var numPageMatches = this.pageMatches[offset.pageIdx].length;
- if (!previous && offset.matchIdx + 1 < numPageMatches || previous && offset.matchIdx > 0) {
- // The simple case; we just have advance the matchIdx to select
- // the next match on the page.
- this.hadMatch = true;
- offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1;
- this.updateMatch(true);
- return;
- }
- // We went beyond the current page's matches, so we advance to
- // the next page.
- this.advanceOffsetPage(previous);
- }
- // Start searching through the page.
- this.nextPageMatch();
- },
- matchesReady: function PDFFindController_matchesReady(matches) {
- var offset = this.offset;
- var numMatches = matches.length;
- var previous = this.state.findPrevious;
- if (numMatches) {
- // There were matches for the page, so initialize the matchIdx.
- this.hadMatch = true;
- offset.matchIdx = previous ? numMatches - 1 : 0;
- this.updateMatch(true);
- return true;
- } else {
- // No matches, so attempt to search the next page.
- this.advanceOffsetPage(previous);
- if (offset.wrapped) {
- offset.matchIdx = null;
- if (this.pagesToSearch < 0) {
- // No point in wrapping again, there were no matches.
- this.updateMatch(false);
- // while matches were not found, searching for a page
- // with matches should nevertheless halt.
- return true;
- }
- }
- // Matches were not found (and searching is not done).
- return false;
- }
- },
- /**
- * The method is called back from the text layer when match presentation
- * is updated.
- * @param {number} pageIndex - page index.
- * @param {number} index - match index.
- * @param {Array} elements - text layer div elements array.
- * @param {number} beginIdx - start index of the div array for the match.
- */
- updateMatchPosition: function PDFFindController_updateMatchPosition(pageIndex, index, elements, beginIdx) {
- if (this.selected.matchIdx === index && this.selected.pageIdx === pageIndex) {
- var spot = {
- top: FIND_SCROLL_OFFSET_TOP,
- left: FIND_SCROLL_OFFSET_LEFT
- };
- scrollIntoView(elements[beginIdx], spot, /* skipOverflowHiddenElements = */
- true);
- }
- },
- nextPageMatch: function PDFFindController_nextPageMatch() {
- if (this.resumePageIdx !== null) {
- console.error('There can only be one pending page.');
- }
- do {
- var pageIdx = this.offset.pageIdx;
- var matches = this.pageMatches[pageIdx];
- if (!matches) {
- // The matches don't exist yet for processing by "matchesReady",
- // so set a resume point for when they do exist.
- this.resumePageIdx = pageIdx;
- break;
- }
- } while (!this.matchesReady(matches));
- },
- advanceOffsetPage: function PDFFindController_advanceOffsetPage(previous) {
- var offset = this.offset;
- var numPages = this.extractTextPromises.length;
- offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1;
- offset.matchIdx = null;
- this.pagesToSearch--;
- if (offset.pageIdx >= numPages || offset.pageIdx < 0) {
- offset.pageIdx = previous ? numPages - 1 : 0;
- offset.wrapped = true;
- }
- },
- updateMatch: function PDFFindController_updateMatch(found) {
- var state = FindStates.FIND_NOTFOUND;
- var wrapped = this.offset.wrapped;
- this.offset.wrapped = false;
- if (found) {
- var previousPage = this.selected.pageIdx;
- this.selected.pageIdx = this.offset.pageIdx;
- this.selected.matchIdx = this.offset.matchIdx;
- state = wrapped ? FindStates.FIND_WRAPPED : FindStates.FIND_FOUND;
- // Update the currently selected page to wipe out any selected matches.
- if (previousPage !== -1 && previousPage !== this.selected.pageIdx) {
- this.updatePage(previousPage);
- }
- }
- this.updateUIState(state, this.state.findPrevious);
- if (this.selected.pageIdx !== -1) {
- this.updatePage(this.selected.pageIdx);
- }
- },
- updateUIResultsCount: function PDFFindController_updateUIResultsCount() {
- if (this.onUpdateResultsCount) {
- this.onUpdateResultsCount(this.matchCount);
- }
- },
- updateUIState: function PDFFindController_updateUIState(state, previous) {
- if (this.onUpdateState) {
- this.onUpdateState(state, previous, this.matchCount);
- }
- }
- };
- return PDFFindController;
- }();
- exports.FindStates = FindStates;
- exports.PDFFindController = PDFFindController;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFPresentationMode = {}, root.pdfjsWebUIUtils);
- }(this, function (exports, uiUtils) {
- var normalizeWheelEventDelta = uiUtils.normalizeWheelEventDelta;
- var DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1500;
- // in ms
- var DELAY_BEFORE_HIDING_CONTROLS = 3000;
- // in ms
- var ACTIVE_SELECTOR = 'pdfPresentationMode';
- var CONTROLS_SELECTOR = 'pdfPresentationModeControls';
- /**
- * @typedef {Object} PDFPresentationModeOptions
- * @property {HTMLDivElement} container - The container for the viewer element.
- * @property {HTMLDivElement} viewer - (optional) The viewer element.
- * @property {PDFViewer} pdfViewer - The document viewer.
- * @property {EventBus} eventBus - The application event bus.
- * @property {Array} contextMenuItems - (optional) The menuitems that are added
- * to the context menu in Presentation Mode.
- */
- /**
- * @class
- */
- var PDFPresentationMode = function PDFPresentationModeClosure() {
- /**
- * @constructs PDFPresentationMode
- * @param {PDFPresentationModeOptions} options
- */
- function PDFPresentationMode(options) {
- this.container = options.container;
- this.viewer = options.viewer || options.container.firstElementChild;
- this.pdfViewer = options.pdfViewer;
- this.eventBus = options.eventBus;
- var contextMenuItems = options.contextMenuItems || null;
- this.active = false;
- this.args = null;
- this.contextMenuOpen = false;
- this.mouseScrollTimeStamp = 0;
- this.mouseScrollDelta = 0;
- this.touchSwipeState = null;
- if (contextMenuItems) {
- contextMenuItems.contextFirstPage.addEventListener('click', function PDFPresentationMode_contextFirstPageClick(e) {
- this.contextMenuOpen = false;
- this.eventBus.dispatch('firstpage');
- }.bind(this));
- contextMenuItems.contextLastPage.addEventListener('click', function PDFPresentationMode_contextLastPageClick(e) {
- this.contextMenuOpen = false;
- this.eventBus.dispatch('lastpage');
- }.bind(this));
- contextMenuItems.contextPageRotateCw.addEventListener('click', function PDFPresentationMode_contextPageRotateCwClick(e) {
- this.contextMenuOpen = false;
- this.eventBus.dispatch('rotatecw');
- }.bind(this));
- contextMenuItems.contextPageRotateCcw.addEventListener('click', function PDFPresentationMode_contextPageRotateCcwClick(e) {
- this.contextMenuOpen = false;
- this.eventBus.dispatch('rotateccw');
- }.bind(this));
- }
- }
- PDFPresentationMode.prototype = {
- /**
- * Request the browser to enter fullscreen mode.
- * @returns {boolean} Indicating if the request was successful.
- */
- request: function PDFPresentationMode_request() {
- if (this.switchInProgress || this.active || !this.viewer.hasChildNodes()) {
- return false;
- }
- this._addFullscreenChangeListeners();
- this._setSwitchInProgress();
- this._notifyStateChange();
- if (this.container.requestFullscreen) {
- this.container.requestFullscreen();
- } else if (this.container.mozRequestFullScreen) {
- this.container.mozRequestFullScreen();
- } else if (this.container.webkitRequestFullscreen) {
- this.container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
- } else if (this.container.msRequestFullscreen) {
- this.container.msRequestFullscreen();
- } else {
- return false;
- }
- this.args = {
- page: this.pdfViewer.currentPageNumber,
- previousScale: this.pdfViewer.currentScaleValue
- };
- return true;
- },
- /**
- * @private
- */
- _mouseWheel: function PDFPresentationMode_mouseWheel(evt) {
- if (!this.active) {
- return;
- }
- evt.preventDefault();
- var delta = normalizeWheelEventDelta(evt);
- var MOUSE_SCROLL_COOLDOWN_TIME = 50;
- var PAGE_SWITCH_THRESHOLD = 0.1;
- var currentTime = new Date().getTime();
- var storedTime = this.mouseScrollTimeStamp;
- // If we've already switched page, avoid accidentally switching again.
- if (currentTime > storedTime && currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) {
- return;
- }
- // If the scroll direction changed, reset the accumulated scroll delta.
- if (this.mouseScrollDelta > 0 && delta < 0 || this.mouseScrollDelta < 0 && delta > 0) {
- this._resetMouseScrollState();
- }
- this.mouseScrollDelta += delta;
- if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) {
- var totalDelta = this.mouseScrollDelta;
- this._resetMouseScrollState();
- var success = totalDelta > 0 ? this._goToPreviousPage() : this._goToNextPage();
- if (success) {
- this.mouseScrollTimeStamp = currentTime;
- }
- }
- },
- get isFullscreen() {
- return !!(document.fullscreenElement || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement);
- },
- /**
- * @private
- */
- _goToPreviousPage: function PDFPresentationMode_goToPreviousPage() {
- var page = this.pdfViewer.currentPageNumber;
- // If we're at the first page, we don't need to do anything.
- if (page <= 1) {
- return false;
- }
- this.pdfViewer.currentPageNumber = page - 1;
- return true;
- },
- /**
- * @private
- */
- _goToNextPage: function PDFPresentationMode_goToNextPage() {
- var page = this.pdfViewer.currentPageNumber;
- // If we're at the last page, we don't need to do anything.
- if (page >= this.pdfViewer.pagesCount) {
- return false;
- }
- this.pdfViewer.currentPageNumber = page + 1;
- return true;
- },
- /**
- * @private
- */
- _notifyStateChange: function PDFPresentationMode_notifyStateChange() {
- this.eventBus.dispatch('presentationmodechanged', {
- source: this,
- active: this.active,
- switchInProgress: !!this.switchInProgress
- });
- },
- /**
- * Used to initialize a timeout when requesting Presentation Mode,
- * i.e. when the browser is requested to enter fullscreen mode.
- * This timeout is used to prevent the current page from being scrolled
- * partially, or completely, out of view when entering Presentation Mode.
- * NOTE: This issue seems limited to certain zoom levels (e.g. page-width).
- * @private
- */
- _setSwitchInProgress: function PDFPresentationMode_setSwitchInProgress() {
- if (this.switchInProgress) {
- clearTimeout(this.switchInProgress);
- }
- this.switchInProgress = setTimeout(function switchInProgressTimeout() {
- this._removeFullscreenChangeListeners();
- delete this.switchInProgress;
- this._notifyStateChange();
- }.bind(this), DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS);
- },
- /**
- * @private
- */
- _resetSwitchInProgress: function PDFPresentationMode_resetSwitchInProgress() {
- if (this.switchInProgress) {
- clearTimeout(this.switchInProgress);
- delete this.switchInProgress;
- }
- },
- /**
- * @private
- */
- _enter: function PDFPresentationMode_enter() {
- this.active = true;
- this._resetSwitchInProgress();
- this._notifyStateChange();
- this.container.classList.add(ACTIVE_SELECTOR);
- // Ensure that the correct page is scrolled into view when entering
- // Presentation Mode, by waiting until fullscreen mode in enabled.
- setTimeout(function enterPresentationModeTimeout() {
- this.pdfViewer.currentPageNumber = this.args.page;
- this.pdfViewer.currentScaleValue = 'page-fit';
- }.bind(this), 0);
- this._addWindowListeners();
- this._showControls();
- this.contextMenuOpen = false;
- this.container.setAttribute('contextmenu', 'viewerContextMenu');
- // Text selection is disabled in Presentation Mode, thus it's not possible
- // for the user to deselect text that is selected (e.g. with "Select all")
- // when entering Presentation Mode, hence we remove any active selection.
- window.getSelection().removeAllRanges();
- },
- /**
- * @private
- */
- _exit: function PDFPresentationMode_exit() {
- var page = this.pdfViewer.currentPageNumber;
- this.container.classList.remove(ACTIVE_SELECTOR);
- // Ensure that the correct page is scrolled into view when exiting
- // Presentation Mode, by waiting until fullscreen mode is disabled.
- setTimeout(function exitPresentationModeTimeout() {
- this.active = false;
- this._removeFullscreenChangeListeners();
- this._notifyStateChange();
- this.pdfViewer.currentScaleValue = this.args.previousScale;
- this.pdfViewer.currentPageNumber = page;
- this.args = null;
- }.bind(this), 0);
- this._removeWindowListeners();
- this._hideControls();
- this._resetMouseScrollState();
- this.container.removeAttribute('contextmenu');
- this.contextMenuOpen = false;
- },
- /**
- * @private
- */
- _mouseDown: function PDFPresentationMode_mouseDown(evt) {
- if (this.contextMenuOpen) {
- this.contextMenuOpen = false;
- evt.preventDefault();
- return;
- }
- if (evt.button === 0) {
- // Enable clicking of links in presentation mode. Please note:
- // Only links pointing to destinations in the current PDF document work.
- var isInternalLink = evt.target.href && evt.target.classList.contains('internalLink');
- if (!isInternalLink) {
- // Unless an internal link was clicked, advance one page.
- evt.preventDefault();
- this.pdfViewer.currentPageNumber += evt.shiftKey ? -1 : 1;
- }
- }
- },
- /**
- * @private
- */
- _contextMenu: function PDFPresentationMode_contextMenu() {
- this.contextMenuOpen = true;
- },
- /**
- * @private
- */
- _showControls: function PDFPresentationMode_showControls() {
- if (this.controlsTimeout) {
- clearTimeout(this.controlsTimeout);
- } else {
- this.container.classList.add(CONTROLS_SELECTOR);
- }
- this.controlsTimeout = setTimeout(function showControlsTimeout() {
- this.container.classList.remove(CONTROLS_SELECTOR);
- delete this.controlsTimeout;
- }.bind(this), DELAY_BEFORE_HIDING_CONTROLS);
- },
- /**
- * @private
- */
- _hideControls: function PDFPresentationMode_hideControls() {
- if (!this.controlsTimeout) {
- return;
- }
- clearTimeout(this.controlsTimeout);
- this.container.classList.remove(CONTROLS_SELECTOR);
- delete this.controlsTimeout;
- },
- /**
- * Resets the properties used for tracking mouse scrolling events.
- * @private
- */
- _resetMouseScrollState: function PDFPresentationMode_resetMouseScrollState() {
- this.mouseScrollTimeStamp = 0;
- this.mouseScrollDelta = 0;
- },
- /**
- * @private
- */
- _touchSwipe: function PDFPresentationMode_touchSwipe(evt) {
- if (!this.active) {
- return;
- }
- // Must move at least these many CSS pixels for it to count as a swipe
- var SWIPE_MIN_DISTANCE_THRESHOLD = 50;
- // The swipe angle is allowed to deviate from the x or y axis by this much
- // before it is not considered a swipe in that direction any more.
- var SWIPE_ANGLE_THRESHOLD = Math.PI / 6;
- if (evt.touches.length > 1) {
- // Multiple touch points detected, cancel the swipe.
- this.touchSwipeState = null;
- return;
- }
- switch (evt.type) {
- case 'touchstart':
- this.touchSwipeState = {
- startX: evt.touches[0].pageX,
- startY: evt.touches[0].pageY,
- endX: evt.touches[0].pageX,
- endY: evt.touches[0].pageY
- };
- break;
- case 'touchmove':
- if (this.touchSwipeState === null) {
- return;
- }
- this.touchSwipeState.endX = evt.touches[0].pageX;
- this.touchSwipeState.endY = evt.touches[0].pageY;
- // Do a preventDefault to avoid the swipe from triggering browser
- // gestures (Chrome in particular has some sort of swipe gesture in
- // fullscreen mode).
- evt.preventDefault();
- break;
- case 'touchend':
- if (this.touchSwipeState === null) {
- return;
- }
- var delta = 0;
- var dx = this.touchSwipeState.endX - this.touchSwipeState.startX;
- var dy = this.touchSwipeState.endY - this.touchSwipeState.startY;
- var absAngle = Math.abs(Math.atan2(dy, dx));
- if (Math.abs(dx) > SWIPE_MIN_DISTANCE_THRESHOLD && (absAngle <= SWIPE_ANGLE_THRESHOLD || absAngle >= Math.PI - SWIPE_ANGLE_THRESHOLD)) {
- // horizontal swipe
- delta = dx;
- } else if (Math.abs(dy) > SWIPE_MIN_DISTANCE_THRESHOLD && Math.abs(absAngle - Math.PI / 2) <= SWIPE_ANGLE_THRESHOLD) {
- // vertical swipe
- delta = dy;
- }
- if (delta > 0) {
- this._goToPreviousPage();
- } else if (delta < 0) {
- this._goToNextPage();
- }
- break;
- }
- },
- /**
- * @private
- */
- _addWindowListeners: function PDFPresentationMode_addWindowListeners() {
- this.showControlsBind = this._showControls.bind(this);
- this.mouseDownBind = this._mouseDown.bind(this);
- this.mouseWheelBind = this._mouseWheel.bind(this);
- this.resetMouseScrollStateBind = this._resetMouseScrollState.bind(this);
- this.contextMenuBind = this._contextMenu.bind(this);
- this.touchSwipeBind = this._touchSwipe.bind(this);
- window.addEventListener('mousemove', this.showControlsBind);
- window.addEventListener('mousedown', this.mouseDownBind);
- window.addEventListener('wheel', this.mouseWheelBind);
- window.addEventListener('keydown', this.resetMouseScrollStateBind);
- window.addEventListener('contextmenu', this.contextMenuBind);
- window.addEventListener('touchstart', this.touchSwipeBind);
- window.addEventListener('touchmove', this.touchSwipeBind);
- window.addEventListener('touchend', this.touchSwipeBind);
- },
- /**
- * @private
- */
- _removeWindowListeners: function PDFPresentationMode_removeWindowListeners() {
- window.removeEventListener('mousemove', this.showControlsBind);
- window.removeEventListener('mousedown', this.mouseDownBind);
- window.removeEventListener('wheel', this.mouseWheelBind);
- window.removeEventListener('keydown', this.resetMouseScrollStateBind);
- window.removeEventListener('contextmenu', this.contextMenuBind);
- window.removeEventListener('touchstart', this.touchSwipeBind);
- window.removeEventListener('touchmove', this.touchSwipeBind);
- window.removeEventListener('touchend', this.touchSwipeBind);
- delete this.showControlsBind;
- delete this.mouseDownBind;
- delete this.mouseWheelBind;
- delete this.resetMouseScrollStateBind;
- delete this.contextMenuBind;
- delete this.touchSwipeBind;
- },
- /**
- * @private
- */
- _fullscreenChange: function PDFPresentationMode_fullscreenChange() {
- if (this.isFullscreen) {
- this._enter();
- } else {
- this._exit();
- }
- },
- /**
- * @private
- */
- _addFullscreenChangeListeners: function PDFPresentationMode_addFullscreenChangeListeners() {
- this.fullscreenChangeBind = this._fullscreenChange.bind(this);
- window.addEventListener('fullscreenchange', this.fullscreenChangeBind);
- window.addEventListener('mozfullscreenchange', this.fullscreenChangeBind);
- },
- /**
- * @private
- */
- _removeFullscreenChangeListeners: function PDFPresentationMode_removeFullscreenChangeListeners() {
- window.removeEventListener('fullscreenchange', this.fullscreenChangeBind);
- window.removeEventListener('mozfullscreenchange', this.fullscreenChangeBind);
- delete this.fullscreenChangeBind;
- }
- };
- return PDFPresentationMode;
- }();
- exports.PDFPresentationMode = PDFPresentationMode;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFThumbnailView = {}, root.pdfjsWebUIUtils, root.pdfjsWebPDFRenderingQueue);
- }(this, function (exports, uiUtils, pdfRenderingQueue) {
- var mozL10n = uiUtils.mozL10n;
- var getOutputScale = uiUtils.getOutputScale;
- var RenderingStates = pdfRenderingQueue.RenderingStates;
- var THUMBNAIL_WIDTH = 98;
- // px
- var THUMBNAIL_CANVAS_BORDER_WIDTH = 1;
- // px
- /**
- * @typedef {Object} PDFThumbnailViewOptions
- * @property {HTMLDivElement} container - The viewer element.
- * @property {number} id - The thumbnail's unique ID (normally its number).
- * @property {PageViewport} defaultViewport - The page viewport.
- * @property {IPDFLinkService} linkService - The navigation/linking service.
- * @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
- * @property {boolean} disableCanvasToImageConversion - (optional) Don't convert
- * the canvas thumbnails to images. This prevents `toDataURL` calls,
- * but increases the overall memory usage. The default value is false.
- */
- /**
- * @class
- * @implements {IRenderableView}
- */
- var PDFThumbnailView = function PDFThumbnailViewClosure() {
- function getTempCanvas(width, height) {
- var tempCanvas = PDFThumbnailView.tempImageCache;
- if (!tempCanvas) {
- tempCanvas = document.createElement('canvas');
- PDFThumbnailView.tempImageCache = tempCanvas;
- }
- tempCanvas.width = width;
- tempCanvas.height = height;
- tempCanvas.mozOpaque = true;
- var ctx = tempCanvas.getContext('2d', { alpha: false });
- ctx.save();
- ctx.fillStyle = 'rgb(255, 255, 255)';
- ctx.fillRect(0, 0, width, height);
- ctx.restore();
- return tempCanvas;
- }
- /**
- * @constructs PDFThumbnailView
- * @param {PDFThumbnailViewOptions} options
- */
- function PDFThumbnailView(options) {
- var container = options.container;
- var id = options.id;
- var defaultViewport = options.defaultViewport;
- var linkService = options.linkService;
- var renderingQueue = options.renderingQueue;
- var disableCanvasToImageConversion = options.disableCanvasToImageConversion || false;
- this.id = id;
- this.renderingId = 'thumbnail' + id;
- this.pageLabel = null;
- this.pdfPage = null;
- this.rotation = 0;
- this.viewport = defaultViewport;
- this.pdfPageRotate = defaultViewport.rotation;
- this.linkService = linkService;
- this.renderingQueue = renderingQueue;
- this.renderTask = null;
- this.renderingState = RenderingStates.INITIAL;
- this.resume = null;
- this.disableCanvasToImageConversion = disableCanvasToImageConversion;
- this.pageWidth = this.viewport.width;
- this.pageHeight = this.viewport.height;
- this.pageRatio = this.pageWidth / this.pageHeight;
- this.canvasWidth = THUMBNAIL_WIDTH;
- this.canvasHeight = this.canvasWidth / this.pageRatio | 0;
- this.scale = this.canvasWidth / this.pageWidth;
- var anchor = document.createElement('a');
- anchor.href = linkService.getAnchorUrl('#page=' + id);
- anchor.title = mozL10n.get('thumb_page_title', { page: id }, 'Page {{page}}');
- anchor.onclick = function stopNavigation() {
- linkService.page = id;
- return false;
- };
- this.anchor = anchor;
- var div = document.createElement('div');
- div.id = 'thumbnailContainer' + id;
- div.className = 'thumbnail';
- this.div = div;
- if (id === 1) {
- // Highlight the thumbnail of the first page when no page number is
- // specified (or exists in cache) when the document is loaded.
- div.classList.add('selected');
- }
- var ring = document.createElement('div');
- ring.className = 'thumbnailSelectionRing';
- var borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH;
- ring.style.width = this.canvasWidth + borderAdjustment + 'px';
- ring.style.height = this.canvasHeight + borderAdjustment + 'px';
- this.ring = ring;
- div.appendChild(ring);
- anchor.appendChild(div);
- container.appendChild(anchor);
- }
- PDFThumbnailView.prototype = {
- setPdfPage: function PDFThumbnailView_setPdfPage(pdfPage) {
- this.pdfPage = pdfPage;
- this.pdfPageRotate = pdfPage.rotate;
- var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
- this.viewport = pdfPage.getViewport(1, totalRotation);
- this.reset();
- },
- reset: function PDFThumbnailView_reset() {
- this.cancelRendering();
- this.pageWidth = this.viewport.width;
- this.pageHeight = this.viewport.height;
- this.pageRatio = this.pageWidth / this.pageHeight;
- this.canvasHeight = this.canvasWidth / this.pageRatio | 0;
- this.scale = this.canvasWidth / this.pageWidth;
- this.div.removeAttribute('data-loaded');
- var ring = this.ring;
- var childNodes = ring.childNodes;
- for (var i = childNodes.length - 1; i >= 0; i--) {
- ring.removeChild(childNodes[i]);
- }
- var borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH;
- ring.style.width = this.canvasWidth + borderAdjustment + 'px';
- ring.style.height = this.canvasHeight + borderAdjustment + 'px';
- if (this.canvas) {
- // Zeroing the width and height causes Firefox to release graphics
- // resources immediately, which can greatly reduce memory consumption.
- this.canvas.width = 0;
- this.canvas.height = 0;
- delete this.canvas;
- }
- if (this.image) {
- this.image.removeAttribute('src');
- delete this.image;
- }
- },
- update: function PDFThumbnailView_update(rotation) {
- if (typeof rotation !== 'undefined') {
- this.rotation = rotation;
- }
- var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
- this.viewport = this.viewport.clone({
- scale: 1,
- rotation: totalRotation
- });
- this.reset();
- },
- cancelRendering: function PDFThumbnailView_cancelRendering() {
- if (this.renderTask) {
- this.renderTask.cancel();
- this.renderTask = null;
- }
- this.renderingState = RenderingStates.INITIAL;
- this.resume = null;
- },
- /**
- * @private
- */
- _getPageDrawContext: function PDFThumbnailView_getPageDrawContext(noCtxScale) {
- var canvas = document.createElement('canvas');
- // Keep the no-thumbnail outline visible, i.e. `data-loaded === false`,
- // until rendering/image conversion is complete, to avoid display issues.
- this.canvas = canvas;
- canvas.mozOpaque = true;
- var ctx = canvas.getContext('2d', { alpha: false });
- var outputScale = getOutputScale(ctx);
- canvas.width = this.canvasWidth * outputScale.sx | 0;
- canvas.height = this.canvasHeight * outputScale.sy | 0;
- canvas.style.width = this.canvasWidth + 'px';
- canvas.style.height = this.canvasHeight + 'px';
- if (!noCtxScale && outputScale.scaled) {
- ctx.scale(outputScale.sx, outputScale.sy);
- }
- return ctx;
- },
- /**
- * @private
- */
- _convertCanvasToImage: function PDFThumbnailView_convertCanvasToImage() {
- if (!this.canvas) {
- return;
- }
- if (this.renderingState !== RenderingStates.FINISHED) {
- return;
- }
- var id = this.renderingId;
- var className = 'thumbnailImage';
- var ariaLabel = mozL10n.get('thumb_page_canvas', { page: this.pageId }, 'Thumbnail of Page {{page}}');
- if (this.disableCanvasToImageConversion) {
- this.canvas.id = id;
- this.canvas.className = className;
- this.canvas.setAttribute('aria-label', ariaLabel);
- this.div.setAttribute('data-loaded', true);
- this.ring.appendChild(this.canvas);
- return;
- }
- var image = document.createElement('img');
- image.id = id;
- image.className = className;
- image.setAttribute('aria-label', ariaLabel);
- image.style.width = this.canvasWidth + 'px';
- image.style.height = this.canvasHeight + 'px';
- image.src = this.canvas.toDataURL();
- this.image = image;
- this.div.setAttribute('data-loaded', true);
- this.ring.appendChild(image);
- // Zeroing the width and height causes Firefox to release graphics
- // resources immediately, which can greatly reduce memory consumption.
- this.canvas.width = 0;
- this.canvas.height = 0;
- delete this.canvas;
- },
- draw: function PDFThumbnailView_draw() {
- if (this.renderingState !== RenderingStates.INITIAL) {
- console.error('Must be in new state before drawing');
- return Promise.resolve(undefined);
- }
- this.renderingState = RenderingStates.RUNNING;
- var resolveRenderPromise, rejectRenderPromise;
- var promise = new Promise(function (resolve, reject) {
- resolveRenderPromise = resolve;
- rejectRenderPromise = reject;
- });
- var self = this;
- function thumbnailDrawCallback(error) {
- // The renderTask may have been replaced by a new one, so only remove
- // the reference to the renderTask if it matches the one that is
- // triggering this callback.
- if (renderTask === self.renderTask) {
- self.renderTask = null;
- }
- if (error === 'cancelled') {
- rejectRenderPromise(error);
- return;
- }
- self.renderingState = RenderingStates.FINISHED;
- self._convertCanvasToImage();
- if (!error) {
- resolveRenderPromise(undefined);
- } else {
- rejectRenderPromise(error);
- }
- }
- var ctx = this._getPageDrawContext();
- var drawViewport = this.viewport.clone({ scale: this.scale });
- var renderContinueCallback = function renderContinueCallback(cont) {
- if (!self.renderingQueue.isHighestPriority(self)) {
- self.renderingState = RenderingStates.PAUSED;
- self.resume = function resumeCallback() {
- self.renderingState = RenderingStates.RUNNING;
- cont();
- };
- return;
- }
- cont();
- };
- var renderContext = {
- canvasContext: ctx,
- viewport: drawViewport
- };
- var renderTask = this.renderTask = this.pdfPage.render(renderContext);
- renderTask.onContinue = renderContinueCallback;
- renderTask.promise.then(function pdfPageRenderCallback() {
- thumbnailDrawCallback(null);
- }, function pdfPageRenderError(error) {
- thumbnailDrawCallback(error);
- });
- return promise;
- },
- setImage: function PDFThumbnailView_setImage(pageView) {
- if (this.renderingState !== RenderingStates.INITIAL) {
- return;
- }
- var img = pageView.canvas;
- if (!img) {
- return;
- }
- if (!this.pdfPage) {
- this.setPdfPage(pageView.pdfPage);
- }
- this.renderingState = RenderingStates.FINISHED;
- var ctx = this._getPageDrawContext(true);
- var canvas = ctx.canvas;
- if (img.width <= 2 * canvas.width) {
- ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
- this._convertCanvasToImage();
- return;
- }
- // drawImage does an awful job of rescaling the image, doing it gradually.
- var MAX_NUM_SCALING_STEPS = 3;
- var reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS;
- var reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS;
- var reducedImage = getTempCanvas(reducedWidth, reducedHeight);
- var reducedImageCtx = reducedImage.getContext('2d');
- while (reducedWidth > img.width || reducedHeight > img.height) {
- reducedWidth >>= 1;
- reducedHeight >>= 1;
- }
- reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, reducedWidth, reducedHeight);
- while (reducedWidth > 2 * canvas.width) {
- reducedImageCtx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, reducedWidth >> 1, reducedHeight >> 1);
- reducedWidth >>= 1;
- reducedHeight >>= 1;
- }
- ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height);
- this._convertCanvasToImage();
- },
- get pageId() {
- return this.pageLabel !== null ? this.pageLabel : this.id;
- },
- /**
- * @param {string|null} label
- */
- setPageLabel: function PDFThumbnailView_setPageLabel(label) {
- this.pageLabel = typeof label === 'string' ? label : null;
- this.anchor.title = mozL10n.get('thumb_page_title', { page: this.pageId }, 'Page {{page}}');
- if (this.renderingState !== RenderingStates.FINISHED) {
- return;
- }
- var ariaLabel = mozL10n.get('thumb_page_canvas', { page: this.pageId }, 'Thumbnail of Page {{page}}');
- if (this.image) {
- this.image.setAttribute('aria-label', ariaLabel);
- } else if (this.disableCanvasToImageConversion && this.canvas) {
- this.canvas.setAttribute('aria-label', ariaLabel);
- }
- }
- };
- return PDFThumbnailView;
- }();
- PDFThumbnailView.tempImageCache = null;
- exports.PDFThumbnailView = PDFThumbnailView;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebSecondaryToolbar = {}, root.pdfjsWebUIUtils);
- }(this, function (exports, uiUtils) {
- var SCROLLBAR_PADDING = uiUtils.SCROLLBAR_PADDING;
- var mozL10n = uiUtils.mozL10n;
- /**
- * @typedef {Object} SecondaryToolbarOptions
- * @property {HTMLDivElement} toolbar - Container for the secondary toolbar.
- * @property {HTMLButtonElement} toggleButton - Button to toggle the visibility
- * of the secondary toolbar.
- * @property {HTMLDivElement} toolbarButtonContainer - Container where all the
- * toolbar buttons are placed. The maximum height of the toolbar is controlled
- * dynamically by adjusting the 'max-height' CSS property of this DOM element.
- * @property {HTMLButtonElement} presentationModeButton - Button for entering
- * presentation mode.
- * @property {HTMLButtonElement} openFileButton - Button to open a file.
- * @property {HTMLButtonElement} printButton - Button to print the document.
- * @property {HTMLButtonElement} downloadButton - Button to download the
- * document.
- * @property {HTMLLinkElement} viewBookmarkButton - Button to obtain a bookmark
- * link to the current location in the document.
- * @property {HTMLButtonElement} firstPageButton - Button to go to the first
- * page in the document.
- * @property {HTMLButtonElement} lastPageButton - Button to go to the last page
- * in the document.
- * @property {HTMLButtonElement} pageRotateCwButton - Button to rotate the pages
- * clockwise.
- * @property {HTMLButtonElement} pageRotateCcwButton - Button to rotate the
- * pages counterclockwise.
- * @property {HTMLButtonElement} toggleHandToolButton - Button to toggle the
- * hand tool.
- * @property {HTMLButtonElement} documentPropertiesButton - Button for opening
- * the document properties dialog.
- */
- /**
- * @class
- */
- var SecondaryToolbar = function SecondaryToolbarClosure() {
- /**
- * @constructs SecondaryToolbar
- * @param {SecondaryToolbarOptions} options
- * @param {HTMLDivElement} mainContainer
- * @param {EventBus} eventBus
- */
- function SecondaryToolbar(options, mainContainer, eventBus) {
- this.toolbar = options.toolbar;
- this.toggleButton = options.toggleButton;
- this.toolbarButtonContainer = options.toolbarButtonContainer;
- this.buttons = [
- {
- element: options.presentationModeButton,
- eventName: 'presentationmode',
- close: true
- },
- {
- element: options.openFileButton,
- eventName: 'openfile',
- close: true
- },
- {
- element: options.printButton,
- eventName: 'print',
- close: true
- },
- {
- element: options.downloadButton,
- eventName: 'download',
- close: true
- },
- {
- element: options.viewBookmarkButton,
- eventName: null,
- close: true
- },
- {
- element: options.firstPageButton,
- eventName: 'firstpage',
- close: true
- },
- {
- element: options.lastPageButton,
- eventName: 'lastpage',
- close: true
- },
- {
- element: options.pageRotateCwButton,
- eventName: 'rotatecw',
- close: false
- },
- {
- element: options.pageRotateCcwButton,
- eventName: 'rotateccw',
- close: false
- },
- {
- element: options.toggleHandToolButton,
- eventName: 'togglehandtool',
- close: true
- },
- {
- element: options.documentPropertiesButton,
- eventName: 'documentproperties',
- close: true
- }
- ];
- this.mainContainer = mainContainer;
- this.eventBus = eventBus;
- this.opened = false;
- this.containerHeight = null;
- this.previousContainerHeight = null;
- // Bind the event listeners for click and hand tool actions.
- this._bindClickListeners();
- this._bindHandToolListener(options.toggleHandToolButton);
- // Bind the event listener for adjusting the 'max-height' of the toolbar.
- this.eventBus.on('resize', this._setMaxHeight.bind(this));
- }
- SecondaryToolbar.prototype = {
- /**
- * @return {boolean}
- */
- get isOpen() {
- return this.opened;
- },
- _bindClickListeners: function SecondaryToolbar_bindClickListeners() {
- // Button to toggle the visibility of the secondary toolbar.
- this.toggleButton.addEventListener('click', this.toggle.bind(this));
- // All items within the secondary toolbar.
- for (var button in this.buttons) {
- var element = this.buttons[button].element;
- var eventName = this.buttons[button].eventName;
- var close = this.buttons[button].close;
- element.addEventListener('click', function (eventName, close) {
- if (eventName !== null) {
- this.eventBus.dispatch(eventName, { source: this });
- }
- if (close) {
- this.close();
- }
- }.bind(this, eventName, close));
- }
- },
- _bindHandToolListener: function SecondaryToolbar_bindHandToolListener(toggleHandToolButton) {
- var isHandToolActive = false;
- this.eventBus.on('handtoolchanged', function (e) {
- if (isHandToolActive === e.isActive) {
- return;
- }
- isHandToolActive = e.isActive;
- if (isHandToolActive) {
- toggleHandToolButton.title = mozL10n.get('hand_tool_disable.title', null, 'Disable hand tool');
- toggleHandToolButton.firstElementChild.textContent = mozL10n.get('hand_tool_disable_label', null, 'Disable hand tool');
- } else {
- toggleHandToolButton.title = mozL10n.get('hand_tool_enable.title', null, 'Enable hand tool');
- toggleHandToolButton.firstElementChild.textContent = mozL10n.get('hand_tool_enable_label', null, 'Enable hand tool');
- }
- }.bind(this));
- },
- open: function SecondaryToolbar_open() {
- if (this.opened) {
- return;
- }
- this.opened = true;
- this._setMaxHeight();
- this.toggleButton.classList.add('toggled');
- this.toolbar.classList.remove('hidden');
- },
- close: function SecondaryToolbar_close() {
- if (!this.opened) {
- return;
- }
- this.opened = false;
- this.toolbar.classList.add('hidden');
- this.toggleButton.classList.remove('toggled');
- },
- toggle: function SecondaryToolbar_toggle() {
- if (this.opened) {
- this.close();
- } else {
- this.open();
- }
- },
- /**
- * @private
- */
- _setMaxHeight: function SecondaryToolbar_setMaxHeight() {
- if (!this.opened) {
- return;
- }
- // Only adjust the 'max-height' if the toolbar is visible.
- this.containerHeight = this.mainContainer.clientHeight;
- if (this.containerHeight === this.previousContainerHeight) {
- return;
- }
- this.toolbarButtonContainer.setAttribute('style', 'max-height: ' + (this.containerHeight - SCROLLBAR_PADDING) + 'px;');
- this.previousContainerHeight = this.containerHeight;
- }
- };
- return SecondaryToolbar;
- }();
- exports.SecondaryToolbar = SecondaryToolbar;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFFindBar = {}, root.pdfjsWebUIUtils, root.pdfjsWebPDFFindController);
- }(this, function (exports, uiUtils, pdfFindController) {
- var mozL10n = uiUtils.mozL10n;
- var FindStates = pdfFindController.FindStates;
- /**
- * Creates a "search bar" given a set of DOM elements that act as controls
- * for searching or for setting search preferences in the UI. This object
- * also sets up the appropriate events for the controls. Actual searching
- * is done by PDFFindController.
- */
- var PDFFindBar = function PDFFindBarClosure() {
- function PDFFindBar(options) {
- this.opened = false;
- this.bar = options.bar || null;
- this.toggleButton = options.toggleButton || null;
- this.findField = options.findField || null;
- this.highlightAll = options.highlightAllCheckbox || null;
- this.caseSensitive = options.caseSensitiveCheckbox || null;
- this.findMsg = options.findMsg || null;
- this.findResultsCount = options.findResultsCount || null;
- this.findStatusIcon = options.findStatusIcon || null;
- this.findPreviousButton = options.findPreviousButton || null;
- this.findNextButton = options.findNextButton || null;
- this.findController = options.findController || null;
- this.eventBus = options.eventBus;
- if (this.findController === null) {
- throw new Error('PDFFindBar cannot be used without a ' + 'PDFFindController instance.');
- }
- // Add event listeners to the DOM elements.
- var self = this;
- this.toggleButton.addEventListener('click', function () {
- self.toggle();
- });
- this.findField.addEventListener('input', function () {
- self.dispatchEvent('');
- });
- this.bar.addEventListener('keydown', function (evt) {
- switch (evt.keyCode) {
- case 13:
- // Enter
- if (evt.target === self.findField) {
- self.dispatchEvent('again', evt.shiftKey);
- }
- break;
- case 27:
- // Escape
- self.close();
- break;
- }
- });
- this.findPreviousButton.addEventListener('click', function () {
- self.dispatchEvent('again', true);
- });
- this.findNextButton.addEventListener('click', function () {
- self.dispatchEvent('again', false);
- });
- this.highlightAll.addEventListener('click', function () {
- self.dispatchEvent('highlightallchange');
- });
- this.caseSensitive.addEventListener('click', function () {
- self.dispatchEvent('casesensitivitychange');
- });
- }
- PDFFindBar.prototype = {
- reset: function PDFFindBar_reset() {
- this.updateUIState();
- },
- dispatchEvent: function PDFFindBar_dispatchEvent(type, findPrev) {
- this.eventBus.dispatch('find', {
- source: this,
- type: type,
- query: this.findField.value,
- caseSensitive: this.caseSensitive.checked,
- phraseSearch: true,
- highlightAll: this.highlightAll.checked,
- findPrevious: findPrev
- });
- },
- updateUIState: function PDFFindBar_updateUIState(state, previous, matchCount) {
- var notFound = false;
- var findMsg = '';
- var status = '';
- switch (state) {
- case FindStates.FIND_FOUND:
- break;
- case FindStates.FIND_PENDING:
- status = 'pending';
- break;
- case FindStates.FIND_NOTFOUND:
- findMsg = mozL10n.get('find_not_found', null, 'Phrase not found');
- notFound = true;
- break;
- case FindStates.FIND_WRAPPED:
- if (previous) {
- findMsg = mozL10n.get('find_reached_top', null, 'Reached top of document, continued from bottom');
- } else {
- findMsg = mozL10n.get('find_reached_bottom', null, 'Reached end of document, continued from top');
- }
- break;
- }
- if (notFound) {
- this.findField.classList.add('notFound');
- } else {
- this.findField.classList.remove('notFound');
- }
- this.findField.setAttribute('data-status', status);
- this.findMsg.textContent = findMsg;
- this.updateResultsCount(matchCount);
- },
- updateResultsCount: function (matchCount) {
- if (!this.findResultsCount) {
- return;
- }
- // no UI control is provided
- // If there are no matches, hide the counter
- if (!matchCount) {
- this.findResultsCount.classList.add('hidden');
- return;
- }
- // Create the match counter
- this.findResultsCount.textContent = matchCount.toLocaleString();
- // Show the counter
- this.findResultsCount.classList.remove('hidden');
- },
- open: function PDFFindBar_open() {
- if (!this.opened) {
- this.opened = true;
- this.toggleButton.classList.add('toggled');
- this.bar.classList.remove('hidden');
- }
- this.findField.select();
- this.findField.focus();
- },
- close: function PDFFindBar_close() {
- if (!this.opened) {
- return;
- }
- this.opened = false;
- this.toggleButton.classList.remove('toggled');
- this.bar.classList.add('hidden');
- this.findController.active = false;
- },
- toggle: function PDFFindBar_toggle() {
- if (this.opened) {
- this.close();
- } else {
- this.open();
- }
- }
- };
- return PDFFindBar;
- }();
- exports.PDFFindBar = PDFFindBar;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFHistory = {}, root.pdfjsWebDOMEvents);
- }(this, function (exports, domEvents) {
- function PDFHistory(options) {
- this.linkService = options.linkService;
- this.eventBus = options.eventBus || domEvents.getGlobalEventBus();
- this.initialized = false;
- this.initialDestination = null;
- this.initialBookmark = null;
- }
- PDFHistory.prototype = {
- /**
- * @param {string} fingerprint
- */
- initialize: function pdfHistoryInitialize(fingerprint) {
- this.initialized = true;
- this.reInitialized = false;
- this.allowHashChange = true;
- this.historyUnlocked = true;
- this.isViewerInPresentationMode = false;
- this.previousHash = window.location.hash.substring(1);
- this.currentBookmark = '';
- this.currentPage = 0;
- this.updatePreviousBookmark = false;
- this.previousBookmark = '';
- this.previousPage = 0;
- this.nextHashParam = '';
- this.fingerprint = fingerprint;
- this.currentUid = this.uid = 0;
- this.current = {};
- var state = window.history.state;
- if (this._isStateObjectDefined(state)) {
- // This corresponds to navigating back to the document
- // from another page in the browser history.
- if (state.target.dest) {
- this.initialDestination = state.target.dest;
- } else {
- this.initialBookmark = state.target.hash;
- }
- this.currentUid = state.uid;
- this.uid = state.uid + 1;
- this.current = state.target;
- } else {
- // This corresponds to the loading of a new document.
- if (state && state.fingerprint && this.fingerprint !== state.fingerprint) {
- // Reinitialize the browsing history when a new document
- // is opened in the web viewer.
- this.reInitialized = true;
- }
- this._pushOrReplaceState({ fingerprint: this.fingerprint }, true);
- }
- var self = this;
- window.addEventListener('popstate', function pdfHistoryPopstate(evt) {
- if (!self.historyUnlocked) {
- return;
- }
- if (evt.state) {
- // Move back/forward in the history.
- self._goTo(evt.state);
- return;
- }
- // If the state is not set, then the user tried to navigate to a
- // different hash by manually editing the URL and pressing Enter, or by
- // clicking on an in-page link (e.g. the "current view" link).
- // Save the current view state to the browser history.
- // Note: In Firefox, history.null could also be null after an in-page
- // navigation to the same URL, and without dispatching the popstate
- // event: https://bugzilla.mozilla.org/show_bug.cgi?id=1183881
- if (self.uid === 0) {
- // Replace the previous state if it was not explicitly set.
- var previousParams = self.previousHash && self.currentBookmark && self.previousHash !== self.currentBookmark ? {
- hash: self.currentBookmark,
- page: self.currentPage
- } : { page: 1 };
- replacePreviousHistoryState(previousParams, function () {
- updateHistoryWithCurrentHash();
- });
- } else {
- updateHistoryWithCurrentHash();
- }
- }, false);
- function updateHistoryWithCurrentHash() {
- self.previousHash = window.location.hash.slice(1);
- self._pushToHistory({ hash: self.previousHash }, false, true);
- self._updatePreviousBookmark();
- }
- function replacePreviousHistoryState(params, callback) {
- // To modify the previous history entry, the following happens:
- // 1. history.back()
- // 2. _pushToHistory, which calls history.replaceState( ... )
- // 3. history.forward()
- // Because a navigation via the history API does not immediately update
- // the history state, the popstate event is used for synchronization.
- self.historyUnlocked = false;
- // Suppress the hashchange event to avoid side effects caused by
- // navigating back and forward.
- self.allowHashChange = false;
- window.addEventListener('popstate', rewriteHistoryAfterBack);
- history.back();
- function rewriteHistoryAfterBack() {
- window.removeEventListener('popstate', rewriteHistoryAfterBack);
- window.addEventListener('popstate', rewriteHistoryAfterForward);
- self._pushToHistory(params, false, true);
- history.forward();
- }
- function rewriteHistoryAfterForward() {
- window.removeEventListener('popstate', rewriteHistoryAfterForward);
- self.allowHashChange = true;
- self.historyUnlocked = true;
- callback();
- }
- }
- function pdfHistoryBeforeUnload() {
- var previousParams = self._getPreviousParams(null, true);
- if (previousParams) {
- var replacePrevious = !self.current.dest && self.current.hash !== self.previousHash;
- self._pushToHistory(previousParams, false, replacePrevious);
- self._updatePreviousBookmark();
- }
- // Remove the event listener when navigating away from the document,
- // since 'beforeunload' prevents Firefox from caching the document.
- window.removeEventListener('beforeunload', pdfHistoryBeforeUnload, false);
- }
- window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false);
- window.addEventListener('pageshow', function pdfHistoryPageShow(evt) {
- // If the entire viewer (including the PDF file) is cached in
- // the browser, we need to reattach the 'beforeunload' event listener
- // since the 'DOMContentLoaded' event is not fired on 'pageshow'.
- window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false);
- }, false);
- self.eventBus.on('presentationmodechanged', function (e) {
- self.isViewerInPresentationMode = e.active;
- });
- },
- clearHistoryState: function pdfHistory_clearHistoryState() {
- this._pushOrReplaceState(null, true);
- },
- _isStateObjectDefined: function pdfHistory_isStateObjectDefined(state) {
- return state && state.uid >= 0 && state.fingerprint && this.fingerprint === state.fingerprint && state.target && state.target.hash ? true : false;
- },
- _pushOrReplaceState: function pdfHistory_pushOrReplaceState(stateObj, replace) {
- if (replace) {
- window.history.replaceState(stateObj, '');
- } else {
- window.history.pushState(stateObj, '');
- }
- },
- get isHashChangeUnlocked() {
- if (!this.initialized) {
- return true;
- }
- return this.allowHashChange;
- },
- _updatePreviousBookmark: function pdfHistory_updatePreviousBookmark() {
- if (this.updatePreviousBookmark && this.currentBookmark && this.currentPage) {
- this.previousBookmark = this.currentBookmark;
- this.previousPage = this.currentPage;
- this.updatePreviousBookmark = false;
- }
- },
- updateCurrentBookmark: function pdfHistoryUpdateCurrentBookmark(bookmark, pageNum) {
- if (this.initialized) {
- this.currentBookmark = bookmark.substring(1);
- this.currentPage = pageNum | 0;
- this._updatePreviousBookmark();
- }
- },
- updateNextHashParam: function pdfHistoryUpdateNextHashParam(param) {
- if (this.initialized) {
- this.nextHashParam = param;
- }
- },
- push: function pdfHistoryPush(params, isInitialBookmark) {
- if (!(this.initialized && this.historyUnlocked)) {
- return;
- }
- if (params.dest && !params.hash) {
- params.hash = this.current.hash && this.current.dest && this.current.dest === params.dest ? this.current.hash : this.linkService.getDestinationHash(params.dest).split('#')[1];
- }
- if (params.page) {
- params.page |= 0;
- }
- if (isInitialBookmark) {
- var target = window.history.state.target;
- if (!target) {
- // Invoked when the user specifies an initial bookmark,
- // thus setting initialBookmark, when the document is loaded.
- this._pushToHistory(params, false);
- this.previousHash = window.location.hash.substring(1);
- }
- this.updatePreviousBookmark = this.nextHashParam ? false : true;
- if (target) {
- // If the current document is reloaded,
- // avoid creating duplicate entries in the history.
- this._updatePreviousBookmark();
- }
- return;
- }
- if (this.nextHashParam) {
- if (this.nextHashParam === params.hash) {
- this.nextHashParam = null;
- this.updatePreviousBookmark = true;
- return;
- } else {
- this.nextHashParam = null;
- }
- }
- if (params.hash) {
- if (this.current.hash) {
- if (this.current.hash !== params.hash) {
- this._pushToHistory(params, true);
- } else {
- if (!this.current.page && params.page) {
- this._pushToHistory(params, false, true);
- }
- this.updatePreviousBookmark = true;
- }
- } else {
- this._pushToHistory(params, true);
- }
- } else if (this.current.page && params.page && this.current.page !== params.page) {
- this._pushToHistory(params, true);
- }
- },
- _getPreviousParams: function pdfHistory_getPreviousParams(onlyCheckPage, beforeUnload) {
- if (!(this.currentBookmark && this.currentPage)) {
- return null;
- } else if (this.updatePreviousBookmark) {
- this.updatePreviousBookmark = false;
- }
- if (this.uid > 0 && !(this.previousBookmark && this.previousPage)) {
- // Prevent the history from getting stuck in the current state,
- // effectively preventing the user from going back/forward in
- // the history.
- //
- // This happens if the current position in the document didn't change
- // when the history was previously updated. The reasons for this are
- // either:
- // 1. The current zoom value is such that the document does not need to,
- // or cannot, be scrolled to display the destination.
- // 2. The previous destination is broken, and doesn't actally point to a
- // position within the document.
- // (This is either due to a bad PDF generator, or the user making a
- // mistake when entering a destination in the hash parameters.)
- return null;
- }
- if (!this.current.dest && !onlyCheckPage || beforeUnload) {
- if (this.previousBookmark === this.currentBookmark) {
- return null;
- }
- } else if (this.current.page || onlyCheckPage) {
- if (this.previousPage === this.currentPage) {
- return null;
- }
- } else {
- return null;
- }
- var params = {
- hash: this.currentBookmark,
- page: this.currentPage
- };
- if (this.isViewerInPresentationMode) {
- params.hash = null;
- }
- return params;
- },
- _stateObj: function pdfHistory_stateObj(params) {
- return {
- fingerprint: this.fingerprint,
- uid: this.uid,
- target: params
- };
- },
- _pushToHistory: function pdfHistory_pushToHistory(params, addPrevious, overwrite) {
- if (!this.initialized) {
- return;
- }
- if (!params.hash && params.page) {
- params.hash = 'page=' + params.page;
- }
- if (addPrevious && !overwrite) {
- var previousParams = this._getPreviousParams();
- if (previousParams) {
- var replacePrevious = !this.current.dest && this.current.hash !== this.previousHash;
- this._pushToHistory(previousParams, false, replacePrevious);
- }
- }
- this._pushOrReplaceState(this._stateObj(params), overwrite || this.uid === 0);
- this.currentUid = this.uid++;
- this.current = params;
- this.updatePreviousBookmark = true;
- },
- _goTo: function pdfHistory_goTo(state) {
- if (!(this.initialized && this.historyUnlocked && this._isStateObjectDefined(state))) {
- return;
- }
- if (!this.reInitialized && state.uid < this.currentUid) {
- var previousParams = this._getPreviousParams(true);
- if (previousParams) {
- this._pushToHistory(this.current, false);
- this._pushToHistory(previousParams, false);
- this.currentUid = state.uid;
- window.history.back();
- return;
- }
- }
- this.historyUnlocked = false;
- if (state.target.dest) {
- this.linkService.navigateTo(state.target.dest);
- } else {
- this.linkService.setHash(state.target.hash);
- }
- this.currentUid = state.uid;
- if (state.uid > this.uid) {
- this.uid = state.uid;
- }
- this.current = state.target;
- this.updatePreviousBookmark = true;
- var currentHash = window.location.hash.substring(1);
- if (this.previousHash !== currentHash) {
- this.allowHashChange = false;
- }
- this.previousHash = currentHash;
- this.historyUnlocked = true;
- },
- back: function pdfHistoryBack() {
- this.go(-1);
- },
- forward: function pdfHistoryForward() {
- this.go(1);
- },
- go: function pdfHistoryGo(direction) {
- if (this.initialized && this.historyUnlocked) {
- var state = window.history.state;
- if (direction === -1 && state && state.uid > 0) {
- window.history.back();
- } else if (direction === 1 && state && state.uid < this.uid - 1) {
- window.history.forward();
- }
- }
- }
- };
- exports.PDFHistory = PDFHistory;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFLinkService = {}, root.pdfjsWebUIUtils, root.pdfjsWebDOMEvents);
- }(this, function (exports, uiUtils, domEvents) {
- var parseQueryString = uiUtils.parseQueryString;
- var PageNumberRegExp = /^\d+$/;
- function isPageNumber(str) {
- return PageNumberRegExp.test(str);
- }
- /**
- * @typedef {Object} PDFLinkServiceOptions
- * @property {EventBus} eventBus - The application event bus.
- */
- /**
- * Performs navigation functions inside PDF, such as opening specified page,
- * or destination.
- * @class
- * @implements {IPDFLinkService}
- */
- var PDFLinkService = function PDFLinkServiceClosure() {
- /**
- * @constructs PDFLinkService
- * @param {PDFLinkServiceOptions} options
- */
- function PDFLinkService(options) {
- options = options || {};
- this.eventBus = options.eventBus || domEvents.getGlobalEventBus();
- this.baseUrl = null;
- this.pdfDocument = null;
- this.pdfViewer = null;
- this.pdfHistory = null;
- this._pagesRefCache = null;
- }
- PDFLinkService.prototype = {
- setDocument: function PDFLinkService_setDocument(pdfDocument, baseUrl) {
- this.baseUrl = baseUrl;
- this.pdfDocument = pdfDocument;
- this._pagesRefCache = Object.create(null);
- },
- setViewer: function PDFLinkService_setViewer(pdfViewer) {
- this.pdfViewer = pdfViewer;
- },
- setHistory: function PDFLinkService_setHistory(pdfHistory) {
- this.pdfHistory = pdfHistory;
- },
- /**
- * @returns {number}
- */
- get pagesCount() {
- return this.pdfDocument ? this.pdfDocument.numPages : 0;
- },
- /**
- * @returns {number}
- */
- get page() {
- return this.pdfViewer.currentPageNumber;
- },
- /**
- * @param {number} value
- */
- set page(value) {
- this.pdfViewer.currentPageNumber = value;
- },
- /**
- * @param dest - The PDF destination object.
- */
- navigateTo: function PDFLinkService_navigateTo(dest) {
- var destString = '';
- var self = this;
- var goToDestination = function (destRef) {
- // dest array looks like that: <page-ref> </XYZ|/FitXXX> <args..>
- var pageNumber;
- if (destRef instanceof Object) {
- pageNumber = self._cachedPageNumber(destRef);
- } else if ((destRef | 0) === destRef) {
- // Integer
- pageNumber = destRef + 1;
- } else {
- console.error('PDFLinkService_navigateTo: "' + destRef + '" is not a valid destination reference.');
- return;
- }
- if (pageNumber) {
- if (pageNumber < 1 || pageNumber > self.pagesCount) {
- console.error('PDFLinkService_navigateTo: "' + pageNumber + '" is a non-existent page number.');
- return;
- }
- self.pdfViewer.scrollPageIntoView({
- pageNumber: pageNumber,
- destArray: dest
- });
- if (self.pdfHistory) {
- // Update the browsing history.
- self.pdfHistory.push({
- dest: dest,
- hash: destString,
- page: pageNumber
- });
- }
- } else {
- self.pdfDocument.getPageIndex(destRef).then(function (pageIndex) {
- self.cachePageRef(pageIndex + 1, destRef);
- goToDestination(destRef);
- }).catch(function () {
- console.error('PDFLinkService_navigateTo: "' + destRef + '" is not a valid page reference.');
- return;
- });
- }
- };
- var destinationPromise;
- if (typeof dest === 'string') {
- destString = dest;
- destinationPromise = this.pdfDocument.getDestination(dest);
- } else {
- destinationPromise = Promise.resolve(dest);
- }
- destinationPromise.then(function (destination) {
- dest = destination;
- if (!(destination instanceof Array)) {
- console.error('PDFLinkService_navigateTo: "' + destination + '" is not a valid destination array.');
- return;
- }
- goToDestination(destination[0]);
- });
- },
- /**
- * @param dest - The PDF destination object.
- * @returns {string} The hyperlink to the PDF object.
- */
- getDestinationHash: function PDFLinkService_getDestinationHash(dest) {
- if (typeof dest === 'string') {
- // In practice, a named destination may contain only a number.
- // If that happens, use the '#nameddest=' form to avoid the link
- // redirecting to a page, instead of the correct destination.
- return this.getAnchorUrl('#' + (isPageNumber(dest) ? 'nameddest=' : '') + escape(dest));
- }
- if (dest instanceof Array) {
- var str = JSON.stringify(dest);
- return this.getAnchorUrl('#' + escape(str));
- }
- return this.getAnchorUrl('');
- },
- /**
- * Prefix the full url on anchor links to make sure that links are resolved
- * relative to the current URL instead of the one defined in <base href>.
- * @param {String} anchor The anchor hash, including the #.
- * @returns {string} The hyperlink to the PDF object.
- */
- getAnchorUrl: function PDFLinkService_getAnchorUrl(anchor) {
- return (this.baseUrl || '') + anchor;
- },
- /**
- * @param {string} hash
- */
- setHash: function PDFLinkService_setHash(hash) {
- var pageNumber, dest;
- if (hash.indexOf('=') >= 0) {
- var params = parseQueryString(hash);
- if ('search' in params) {
- this.eventBus.dispatch('findfromurlhash', {
- source: this,
- query: params['search'].replace(/"/g, ''),
- phraseSearch: params['phrase'] === 'true'
- });
- }
- // borrowing syntax from "Parameters for Opening PDF Files"
- if ('nameddest' in params) {
- if (this.pdfHistory) {
- this.pdfHistory.updateNextHashParam(params.nameddest);
- }
- this.navigateTo(params.nameddest);
- return;
- }
- if ('page' in params) {
- pageNumber = params.page | 0 || 1;
- }
- if ('zoom' in params) {
- // Build the destination array.
- var zoomArgs = params.zoom.split(',');
- // scale,left,top
- var zoomArg = zoomArgs[0];
- var zoomArgNumber = parseFloat(zoomArg);
- if (zoomArg.indexOf('Fit') === -1) {
- // If the zoomArg is a number, it has to get divided by 100. If it's
- // a string, it should stay as it is.
- dest = [
- null,
- { name: 'XYZ' },
- zoomArgs.length > 1 ? zoomArgs[1] | 0 : null,
- zoomArgs.length > 2 ? zoomArgs[2] | 0 : null,
- zoomArgNumber ? zoomArgNumber / 100 : zoomArg
- ];
- } else {
- if (zoomArg === 'Fit' || zoomArg === 'FitB') {
- dest = [
- null,
- { name: zoomArg }
- ];
- } else if (zoomArg === 'FitH' || zoomArg === 'FitBH' || (zoomArg === 'FitV' || zoomArg === 'FitBV')) {
- dest = [
- null,
- { name: zoomArg },
- zoomArgs.length > 1 ? zoomArgs[1] | 0 : null
- ];
- } else if (zoomArg === 'FitR') {
- if (zoomArgs.length !== 5) {
- console.error('PDFLinkService_setHash: ' + 'Not enough parameters for \'FitR\'.');
- } else {
- dest = [
- null,
- { name: zoomArg },
- zoomArgs[1] | 0,
- zoomArgs[2] | 0,
- zoomArgs[3] | 0,
- zoomArgs[4] | 0
- ];
- }
- } else {
- console.error('PDFLinkService_setHash: \'' + zoomArg + '\' is not a valid zoom value.');
- }
- }
- }
- if (dest) {
- this.pdfViewer.scrollPageIntoView({
- pageNumber: pageNumber || this.page,
- destArray: dest,
- allowNegativeOffset: true
- });
- } else if (pageNumber) {
- this.page = pageNumber;
- }
- // simple page
- if ('pagemode' in params) {
- this.eventBus.dispatch('pagemode', {
- source: this,
- mode: params.pagemode
- });
- }
- } else {
- dest = unescape(hash);
- try {
- dest = JSON.parse(dest);
- if (!(dest instanceof Array)) {
- // Avoid incorrectly rejecting a valid named destination, such as
- // e.g. "4.3" or "true", because `JSON.parse` converted its type.
- dest = dest.toString();
- }
- } catch (ex) {
- }
- if (typeof dest === 'string' || isValidExplicitDestination(dest)) {
- if (this.pdfHistory) {
- this.pdfHistory.updateNextHashParam(dest);
- }
- this.navigateTo(dest);
- return;
- }
- console.error('PDFLinkService_setHash: \'' + unescape(hash) + '\' is not a valid destination.');
- }
- },
- /**
- * @param {string} action
- */
- executeNamedAction: function PDFLinkService_executeNamedAction(action) {
- // See PDF reference, table 8.45 - Named action
- switch (action) {
- case 'GoBack':
- if (this.pdfHistory) {
- this.pdfHistory.back();
- }
- break;
- case 'GoForward':
- if (this.pdfHistory) {
- this.pdfHistory.forward();
- }
- break;
- case 'NextPage':
- if (this.page < this.pagesCount) {
- this.page++;
- }
- break;
- case 'PrevPage':
- if (this.page > 1) {
- this.page--;
- }
- break;
- case 'LastPage':
- this.page = this.pagesCount;
- break;
- case 'FirstPage':
- this.page = 1;
- break;
- default:
- break;
- }
- // No action according to spec
- this.eventBus.dispatch('namedaction', {
- source: this,
- action: action
- });
- },
- /**
- * @param {number} pageNum - page number.
- * @param {Object} pageRef - reference to the page.
- */
- cachePageRef: function PDFLinkService_cachePageRef(pageNum, pageRef) {
- var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
- this._pagesRefCache[refStr] = pageNum;
- },
- _cachedPageNumber: function PDFLinkService_cachedPageNumber(pageRef) {
- var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
- return this._pagesRefCache && this._pagesRefCache[refStr] || null;
- }
- };
- function isValidExplicitDestination(dest) {
- if (!(dest instanceof Array)) {
- return false;
- }
- var destLength = dest.length, allowNull = true;
- if (destLength < 2) {
- return false;
- }
- var page = dest[0];
- if (!(typeof page === 'object' && typeof page.num === 'number' && (page.num | 0) === page.num && typeof page.gen === 'number' && (page.gen | 0) === page.gen) && !(typeof page === 'number' && (page | 0) === page && page >= 0)) {
- return false;
- }
- var zoom = dest[1];
- if (!(typeof zoom === 'object' && typeof zoom.name === 'string')) {
- return false;
- }
- switch (zoom.name) {
- case 'XYZ':
- if (destLength !== 5) {
- return false;
- }
- break;
- case 'Fit':
- case 'FitB':
- return destLength === 2;
- case 'FitH':
- case 'FitBH':
- case 'FitV':
- case 'FitBV':
- if (destLength !== 3) {
- return false;
- }
- break;
- case 'FitR':
- if (destLength !== 6) {
- return false;
- }
- allowNull = false;
- break;
- default:
- return false;
- }
- for (var i = 2; i < destLength; i++) {
- var param = dest[i];
- if (!(typeof param === 'number' || allowNull && param === null)) {
- return false;
- }
- }
- return true;
- }
- return PDFLinkService;
- }();
- var SimpleLinkService = function SimpleLinkServiceClosure() {
- function SimpleLinkService() {
- }
- SimpleLinkService.prototype = {
- /**
- * @returns {number}
- */
- get page() {
- return 0;
- },
- /**
- * @param {number} value
- */
- set page(value) {
- },
- /**
- * @param dest - The PDF destination object.
- */
- navigateTo: function (dest) {
- },
- /**
- * @param dest - The PDF destination object.
- * @returns {string} The hyperlink to the PDF object.
- */
- getDestinationHash: function (dest) {
- return '#';
- },
- /**
- * @param hash - The PDF parameters/hash.
- * @returns {string} The hyperlink to the PDF object.
- */
- getAnchorUrl: function (hash) {
- return '#';
- },
- /**
- * @param {string} hash
- */
- setHash: function (hash) {
- },
- /**
- * @param {string} action
- */
- executeNamedAction: function (action) {
- },
- /**
- * @param {number} pageNum - page number.
- * @param {Object} pageRef - reference to the page.
- */
- cachePageRef: function (pageNum, pageRef) {
- }
- };
- return SimpleLinkService;
- }();
- exports.PDFLinkService = PDFLinkService;
- exports.SimpleLinkService = SimpleLinkService;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFPageView = {}, root.pdfjsWebUIUtils, root.pdfjsWebPDFRenderingQueue, root.pdfjsWebDOMEvents, root.pdfjsWebPDFJS);
- }(this, function (exports, uiUtils, pdfRenderingQueue, domEvents, pdfjsLib) {
- var CSS_UNITS = uiUtils.CSS_UNITS;
- var DEFAULT_SCALE = uiUtils.DEFAULT_SCALE;
- var getOutputScale = uiUtils.getOutputScale;
- var approximateFraction = uiUtils.approximateFraction;
- var roundToDivide = uiUtils.roundToDivide;
- var RenderingStates = pdfRenderingQueue.RenderingStates;
- var TEXT_LAYER_RENDER_DELAY = 200;
- // ms
- /**
- * @typedef {Object} PDFPageViewOptions
- * @property {HTMLDivElement} container - The viewer element.
- * @property {EventBus} eventBus - The application event bus.
- * @property {number} id - The page unique ID (normally its number).
- * @property {number} scale - The page scale display.
- * @property {PageViewport} defaultViewport - The page viewport.
- * @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
- * @property {IPDFTextLayerFactory} textLayerFactory
- * @property {IPDFAnnotationLayerFactory} annotationLayerFactory
- * @property {boolean} enhanceTextSelection - Turns on the text selection
- * enhancement. The default is `false`.
- * @property {boolean} renderInteractiveForms - Turns on rendering of
- * interactive form elements. The default is `false`.
- */
- /**
- * @class
- * @implements {IRenderableView}
- */
- var PDFPageView = function PDFPageViewClosure() {
- /**
- * @constructs PDFPageView
- * @param {PDFPageViewOptions} options
- */
- function PDFPageView(options) {
- var container = options.container;
- var id = options.id;
- var scale = options.scale;
- var defaultViewport = options.defaultViewport;
- var renderingQueue = options.renderingQueue;
- var textLayerFactory = options.textLayerFactory;
- var annotationLayerFactory = options.annotationLayerFactory;
- var enhanceTextSelection = options.enhanceTextSelection || false;
- var renderInteractiveForms = options.renderInteractiveForms || false;
- this.id = id;
- this.renderingId = 'page' + id;
- this.pageLabel = null;
- this.rotation = 0;
- this.scale = scale || DEFAULT_SCALE;
- this.viewport = defaultViewport;
- this.pdfPageRotate = defaultViewport.rotation;
- this.hasRestrictedScaling = false;
- this.enhanceTextSelection = enhanceTextSelection;
- this.renderInteractiveForms = renderInteractiveForms;
- this.eventBus = options.eventBus || domEvents.getGlobalEventBus();
- this.renderingQueue = renderingQueue;
- this.textLayerFactory = textLayerFactory;
- this.annotationLayerFactory = annotationLayerFactory;
- this.renderTask = null;
- this.renderingState = RenderingStates.INITIAL;
- this.resume = null;
- this.onBeforeDraw = null;
- this.onAfterDraw = null;
- this.textLayer = null;
- this.zoomLayer = null;
- this.annotationLayer = null;
- var div = document.createElement('div');
- div.id = 'pageContainer' + this.id;
- div.className = 'page';
- div.style.width = Math.floor(this.viewport.width) + 'px';
- div.style.height = Math.floor(this.viewport.height) + 'px';
- div.setAttribute('data-page-number', this.id);
- this.div = div;
- container.appendChild(div);
- }
- PDFPageView.prototype = {
- setPdfPage: function PDFPageView_setPdfPage(pdfPage) {
- this.pdfPage = pdfPage;
- this.pdfPageRotate = pdfPage.rotate;
- var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
- this.viewport = pdfPage.getViewport(this.scale * CSS_UNITS, totalRotation);
- this.stats = pdfPage.stats;
- this.reset();
- },
- destroy: function PDFPageView_destroy() {
- this.zoomLayer = null;
- this.reset();
- if (this.pdfPage) {
- this.pdfPage.cleanup();
- }
- },
- reset: function PDFPageView_reset(keepZoomLayer, keepAnnotations) {
- this.cancelRendering();
- var div = this.div;
- div.style.width = Math.floor(this.viewport.width) + 'px';
- div.style.height = Math.floor(this.viewport.height) + 'px';
- var childNodes = div.childNodes;
- var currentZoomLayerNode = keepZoomLayer && this.zoomLayer || null;
- var currentAnnotationNode = keepAnnotations && this.annotationLayer && this.annotationLayer.div || null;
- for (var i = childNodes.length - 1; i >= 0; i--) {
- var node = childNodes[i];
- if (currentZoomLayerNode === node || currentAnnotationNode === node) {
- continue;
- }
- div.removeChild(node);
- }
- div.removeAttribute('data-loaded');
- if (currentAnnotationNode) {
- // Hide annotationLayer until all elements are resized
- // so they are not displayed on the already-resized page
- this.annotationLayer.hide();
- } else {
- this.annotationLayer = null;
- }
- if (this.canvas && !currentZoomLayerNode) {
- // Zeroing the width and height causes Firefox to release graphics
- // resources immediately, which can greatly reduce memory consumption.
- this.canvas.width = 0;
- this.canvas.height = 0;
- delete this.canvas;
- }
- this.loadingIconDiv = document.createElement('div');
- this.loadingIconDiv.className = 'loadingIcon';
- div.appendChild(this.loadingIconDiv);
- },
- update: function PDFPageView_update(scale, rotation) {
- this.scale = scale || this.scale;
- if (typeof rotation !== 'undefined') {
- this.rotation = rotation;
- }
- var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
- this.viewport = this.viewport.clone({
- scale: this.scale * CSS_UNITS,
- rotation: totalRotation
- });
- var isScalingRestricted = false;
- if (this.canvas && pdfjsLib.PDFJS.maxCanvasPixels > 0) {
- var outputScale = this.outputScale;
- if ((Math.floor(this.viewport.width) * outputScale.sx | 0) * (Math.floor(this.viewport.height) * outputScale.sy | 0) > pdfjsLib.PDFJS.maxCanvasPixels) {
- isScalingRestricted = true;
- }
- }
- if (this.canvas) {
- if (pdfjsLib.PDFJS.useOnlyCssZoom || this.hasRestrictedScaling && isScalingRestricted) {
- this.cssTransform(this.canvas, true);
- this.eventBus.dispatch('pagerendered', {
- source: this,
- pageNumber: this.id,
- cssTransform: true
- });
- return;
- }
- if (!this.zoomLayer) {
- this.zoomLayer = this.canvas.parentNode;
- this.zoomLayer.style.position = 'absolute';
- }
- }
- if (this.zoomLayer) {
- this.cssTransform(this.zoomLayer.firstChild);
- }
- this.reset(/* keepZoomLayer = */
- true, /* keepAnnotations = */
- true);
- },
- cancelRendering: function PDFPageView_cancelRendering() {
- if (this.renderTask) {
- this.renderTask.cancel();
- this.renderTask = null;
- }
- this.renderingState = RenderingStates.INITIAL;
- this.resume = null;
- if (this.textLayer) {
- this.textLayer.cancel();
- this.textLayer = null;
- }
- },
- /**
- * Called when moved in the parent's container.
- */
- updatePosition: function PDFPageView_updatePosition() {
- if (this.textLayer) {
- this.textLayer.render(TEXT_LAYER_RENDER_DELAY);
- }
- },
- cssTransform: function PDFPageView_transform(canvas, redrawAnnotations) {
- var CustomStyle = pdfjsLib.CustomStyle;
- // Scale canvas, canvas wrapper, and page container.
- var width = this.viewport.width;
- var height = this.viewport.height;
- var div = this.div;
- canvas.style.width = canvas.parentNode.style.width = div.style.width = Math.floor(width) + 'px';
- canvas.style.height = canvas.parentNode.style.height = div.style.height = Math.floor(height) + 'px';
- // The canvas may have been originally rotated, rotate relative to that.
- var relativeRotation = this.viewport.rotation - canvas._viewport.rotation;
- var absRotation = Math.abs(relativeRotation);
- var scaleX = 1, scaleY = 1;
- if (absRotation === 90 || absRotation === 270) {
- // Scale x and y because of the rotation.
- scaleX = height / width;
- scaleY = width / height;
- }
- var cssTransform = 'rotate(' + relativeRotation + 'deg) ' + 'scale(' + scaleX + ',' + scaleY + ')';
- CustomStyle.setProp('transform', canvas, cssTransform);
- if (this.textLayer) {
- // Rotating the text layer is more complicated since the divs inside the
- // the text layer are rotated.
- // TODO: This could probably be simplified by drawing the text layer in
- // one orientation then rotating overall.
- var textLayerViewport = this.textLayer.viewport;
- var textRelativeRotation = this.viewport.rotation - textLayerViewport.rotation;
- var textAbsRotation = Math.abs(textRelativeRotation);
- var scale = width / textLayerViewport.width;
- if (textAbsRotation === 90 || textAbsRotation === 270) {
- scale = width / textLayerViewport.height;
- }
- var textLayerDiv = this.textLayer.textLayerDiv;
- var transX, transY;
- switch (textAbsRotation) {
- case 0:
- transX = transY = 0;
- break;
- case 90:
- transX = 0;
- transY = '-' + textLayerDiv.style.height;
- break;
- case 180:
- transX = '-' + textLayerDiv.style.width;
- transY = '-' + textLayerDiv.style.height;
- break;
- case 270:
- transX = '-' + textLayerDiv.style.width;
- transY = 0;
- break;
- default:
- console.error('Bad rotation value.');
- break;
- }
- CustomStyle.setProp('transform', textLayerDiv, 'rotate(' + textAbsRotation + 'deg) ' + 'scale(' + scale + ', ' + scale + ') ' + 'translate(' + transX + ', ' + transY + ')');
- CustomStyle.setProp('transformOrigin', textLayerDiv, '0% 0%');
- }
- if (redrawAnnotations && this.annotationLayer) {
- this.annotationLayer.render(this.viewport, 'display');
- }
- },
- get width() {
- return this.viewport.width;
- },
- get height() {
- return this.viewport.height;
- },
- getPagePoint: function PDFPageView_getPagePoint(x, y) {
- return this.viewport.convertToPdfPoint(x, y);
- },
- draw: function PDFPageView_draw() {
- if (this.renderingState !== RenderingStates.INITIAL) {
- console.error('Must be in new state before drawing');
- this.reset();
- }
- // Ensure that we reset all state to prevent issues.
- this.renderingState = RenderingStates.RUNNING;
- var pdfPage = this.pdfPage;
- var viewport = this.viewport;
- var div = this.div;
- // Wrap the canvas so if it has a css transform for highdpi the overflow
- // will be hidden in FF.
- var canvasWrapper = document.createElement('div');
- canvasWrapper.style.width = div.style.width;
- canvasWrapper.style.height = div.style.height;
- canvasWrapper.classList.add('canvasWrapper');
- var canvas = document.createElement('canvas');
- canvas.id = 'page' + this.id;
- // Keep the canvas hidden until the first draw callback, or until drawing
- // is complete when `!this.renderingQueue`, to prevent black flickering.
- canvas.setAttribute('hidden', 'hidden');
- var isCanvasHidden = true;
- canvasWrapper.appendChild(canvas);
- if (this.annotationLayer && this.annotationLayer.div) {
- // annotationLayer needs to stay on top
- div.insertBefore(canvasWrapper, this.annotationLayer.div);
- } else {
- div.appendChild(canvasWrapper);
- }
- this.canvas = canvas;
- canvas.mozOpaque = true;
- var ctx = canvas.getContext('2d', { alpha: false });
- var outputScale = getOutputScale(ctx);
- this.outputScale = outputScale;
- if (pdfjsLib.PDFJS.useOnlyCssZoom) {
- var actualSizeViewport = viewport.clone({ scale: CSS_UNITS });
- // Use a scale that will make the canvas be the original intended size
- // of the page.
- outputScale.sx *= actualSizeViewport.width / viewport.width;
- outputScale.sy *= actualSizeViewport.height / viewport.height;
- outputScale.scaled = true;
- }
- if (pdfjsLib.PDFJS.maxCanvasPixels > 0) {
- var pixelsInViewport = viewport.width * viewport.height;
- var maxScale = Math.sqrt(pdfjsLib.PDFJS.maxCanvasPixels / pixelsInViewport);
- if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
- outputScale.sx = maxScale;
- outputScale.sy = maxScale;
- outputScale.scaled = true;
- this.hasRestrictedScaling = true;
- } else {
- this.hasRestrictedScaling = false;
- }
- }
- var sfx = approximateFraction(outputScale.sx);
- var sfy = approximateFraction(outputScale.sy);
- canvas.width = roundToDivide(viewport.width * outputScale.sx, sfx[0]);
- canvas.height = roundToDivide(viewport.height * outputScale.sy, sfy[0]);
- canvas.style.width = roundToDivide(viewport.width, sfx[1]) + 'px';
- canvas.style.height = roundToDivide(viewport.height, sfy[1]) + 'px';
- // Add the viewport so it's known what it was originally drawn with.
- canvas._viewport = viewport;
- var textLayerDiv = null;
- var textLayer = null;
- if (this.textLayerFactory) {
- textLayerDiv = document.createElement('div');
- textLayerDiv.className = 'textLayer';
- textLayerDiv.style.width = canvasWrapper.style.width;
- textLayerDiv.style.height = canvasWrapper.style.height;
- if (this.annotationLayer && this.annotationLayer.div) {
- // annotationLayer needs to stay on top
- div.insertBefore(textLayerDiv, this.annotationLayer.div);
- } else {
- div.appendChild(textLayerDiv);
- }
- textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.enhanceTextSelection);
- }
- this.textLayer = textLayer;
- var resolveRenderPromise, rejectRenderPromise;
- var promise = new Promise(function (resolve, reject) {
- resolveRenderPromise = resolve;
- rejectRenderPromise = reject;
- });
- // Rendering area
- var self = this;
- function pageViewDrawCallback(error) {
- // The renderTask may have been replaced by a new one, so only remove
- // the reference to the renderTask if it matches the one that is
- // triggering this callback.
- if (renderTask === self.renderTask) {
- self.renderTask = null;
- }
- if (error === 'cancelled') {
- rejectRenderPromise(error);
- return;
- }
- self.renderingState = RenderingStates.FINISHED;
- if (isCanvasHidden) {
- self.canvas.removeAttribute('hidden');
- isCanvasHidden = false;
- }
- if (self.loadingIconDiv) {
- div.removeChild(self.loadingIconDiv);
- delete self.loadingIconDiv;
- }
- if (self.zoomLayer) {
- // Zeroing the width and height causes Firefox to release graphics
- // resources immediately, which can greatly reduce memory consumption.
- var zoomLayerCanvas = self.zoomLayer.firstChild;
- zoomLayerCanvas.width = 0;
- zoomLayerCanvas.height = 0;
- if (div.contains(self.zoomLayer)) {
- // Prevent "Node was not found" errors if the `zoomLayer` was
- // already removed. This may occur intermittently if the scale
- // changes many times in very quick succession.
- div.removeChild(self.zoomLayer);
- }
- self.zoomLayer = null;
- }
- self.error = error;
- self.stats = pdfPage.stats;
- if (self.onAfterDraw) {
- self.onAfterDraw();
- }
- self.eventBus.dispatch('pagerendered', {
- source: self,
- pageNumber: self.id,
- cssTransform: false
- });
- if (!error) {
- resolveRenderPromise(undefined);
- } else {
- rejectRenderPromise(error);
- }
- }
- var renderContinueCallback = null;
- if (this.renderingQueue) {
- renderContinueCallback = function renderContinueCallback(cont) {
- if (!self.renderingQueue.isHighestPriority(self)) {
- self.renderingState = RenderingStates.PAUSED;
- self.resume = function resumeCallback() {
- self.renderingState = RenderingStates.RUNNING;
- cont();
- };
- return;
- }
- if (isCanvasHidden) {
- self.canvas.removeAttribute('hidden');
- isCanvasHidden = false;
- }
- cont();
- };
- }
- var transform = !outputScale.scaled ? null : [
- outputScale.sx,
- 0,
- 0,
- outputScale.sy,
- 0,
- 0
- ];
- var renderContext = {
- canvasContext: ctx,
- transform: transform,
- viewport: this.viewport,
- renderInteractiveForms: this.renderInteractiveForms
- };
- // intent: 'default', // === 'display'
- var renderTask = this.renderTask = this.pdfPage.render(renderContext);
- renderTask.onContinue = renderContinueCallback;
- this.renderTask.promise.then(function pdfPageRenderCallback() {
- pageViewDrawCallback(null);
- if (textLayer) {
- self.pdfPage.getTextContent({ normalizeWhitespace: true }).then(function textContentResolved(textContent) {
- textLayer.setTextContent(textContent);
- textLayer.render(TEXT_LAYER_RENDER_DELAY);
- });
- }
- }, function pdfPageRenderError(error) {
- pageViewDrawCallback(error);
- });
- if (this.annotationLayerFactory) {
- if (!this.annotationLayer) {
- this.annotationLayer = this.annotationLayerFactory.createAnnotationLayerBuilder(div, this.pdfPage, this.renderInteractiveForms);
- }
- this.annotationLayer.render(this.viewport, 'display');
- }
- div.setAttribute('data-loaded', true);
- if (self.onBeforeDraw) {
- self.onBeforeDraw();
- }
- return promise;
- },
- /**
- * @param {string|null} label
- */
- setPageLabel: function PDFView_setPageLabel(label) {
- this.pageLabel = typeof label === 'string' ? label : null;
- if (this.pageLabel !== null) {
- this.div.setAttribute('data-page-label', this.pageLabel);
- } else {
- this.div.removeAttribute('data-page-label');
- }
- }
- };
- return PDFPageView;
- }();
- exports.PDFPageView = PDFPageView;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFThumbnailViewer = {}, root.pdfjsWebUIUtils, root.pdfjsWebPDFThumbnailView);
- }(this, function (exports, uiUtils, pdfThumbnailView) {
- var watchScroll = uiUtils.watchScroll;
- var getVisibleElements = uiUtils.getVisibleElements;
- var scrollIntoView = uiUtils.scrollIntoView;
- var PDFThumbnailView = pdfThumbnailView.PDFThumbnailView;
- var THUMBNAIL_SCROLL_MARGIN = -19;
- /**
- * @typedef {Object} PDFThumbnailViewerOptions
- * @property {HTMLDivElement} container - The container for the thumbnail
- * elements.
- * @property {IPDFLinkService} linkService - The navigation/linking service.
- * @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
- */
- /**
- * Simple viewer control to display thumbnails for pages.
- * @class
- * @implements {IRenderableView}
- */
- var PDFThumbnailViewer = function PDFThumbnailViewerClosure() {
- /**
- * @constructs PDFThumbnailViewer
- * @param {PDFThumbnailViewerOptions} options
- */
- function PDFThumbnailViewer(options) {
- this.container = options.container;
- this.renderingQueue = options.renderingQueue;
- this.linkService = options.linkService;
- this.scroll = watchScroll(this.container, this._scrollUpdated.bind(this));
- this._resetView();
- }
- PDFThumbnailViewer.prototype = {
- /**
- * @private
- */
- _scrollUpdated: function PDFThumbnailViewer_scrollUpdated() {
- this.renderingQueue.renderHighestPriority();
- },
- getThumbnail: function PDFThumbnailViewer_getThumbnail(index) {
- return this.thumbnails[index];
- },
- /**
- * @private
- */
- _getVisibleThumbs: function PDFThumbnailViewer_getVisibleThumbs() {
- return getVisibleElements(this.container, this.thumbnails);
- },
- scrollThumbnailIntoView: function PDFThumbnailViewer_scrollThumbnailIntoView(page) {
- var selected = document.querySelector('.thumbnail.selected');
- if (selected) {
- selected.classList.remove('selected');
- }
- var thumbnail = document.getElementById('thumbnailContainer' + page);
- if (thumbnail) {
- thumbnail.classList.add('selected');
- }
- var visibleThumbs = this._getVisibleThumbs();
- var numVisibleThumbs = visibleThumbs.views.length;
- // If the thumbnail isn't currently visible, scroll it into view.
- if (numVisibleThumbs > 0) {
- var first = visibleThumbs.first.id;
- // Account for only one thumbnail being visible.
- var last = numVisibleThumbs > 1 ? visibleThumbs.last.id : first;
- if (page <= first || page >= last) {
- scrollIntoView(thumbnail, { top: THUMBNAIL_SCROLL_MARGIN });
- }
- }
- },
- get pagesRotation() {
- return this._pagesRotation;
- },
- set pagesRotation(rotation) {
- this._pagesRotation = rotation;
- for (var i = 0, l = this.thumbnails.length; i < l; i++) {
- var thumb = this.thumbnails[i];
- thumb.update(rotation);
- }
- },
- cleanup: function PDFThumbnailViewer_cleanup() {
- var tempCanvas = PDFThumbnailView.tempImageCache;
- if (tempCanvas) {
- // Zeroing the width and height causes Firefox to release graphics
- // resources immediately, which can greatly reduce memory consumption.
- tempCanvas.width = 0;
- tempCanvas.height = 0;
- }
- PDFThumbnailView.tempImageCache = null;
- },
- /**
- * @private
- */
- _resetView: function PDFThumbnailViewer_resetView() {
- this.thumbnails = [];
- this._pageLabels = null;
- this._pagesRotation = 0;
- this._pagesRequests = [];
- // Remove the thumbnails from the DOM.
- this.container.textContent = '';
- },
- setDocument: function PDFThumbnailViewer_setDocument(pdfDocument) {
- if (this.pdfDocument) {
- this._cancelRendering();
- this._resetView();
- }
- this.pdfDocument = pdfDocument;
- if (!pdfDocument) {
- return Promise.resolve();
- }
- return pdfDocument.getPage(1).then(function (firstPage) {
- var pagesCount = pdfDocument.numPages;
- var viewport = firstPage.getViewport(1.0);
- for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
- var thumbnail = new PDFThumbnailView({
- container: this.container,
- id: pageNum,
- defaultViewport: viewport.clone(),
- linkService: this.linkService,
- renderingQueue: this.renderingQueue,
- disableCanvasToImageConversion: false
- });
- this.thumbnails.push(thumbnail);
- }
- }.bind(this));
- },
- /**
- * @private
- */
- _cancelRendering: function PDFThumbnailViewer_cancelRendering() {
- for (var i = 0, ii = this.thumbnails.length; i < ii; i++) {
- if (this.thumbnails[i]) {
- this.thumbnails[i].cancelRendering();
- }
- }
- },
- /**
- * @param {Array|null} labels
- */
- setPageLabels: function PDFThumbnailViewer_setPageLabels(labels) {
- if (!this.pdfDocument) {
- return;
- }
- if (!labels) {
- this._pageLabels = null;
- } else if (!(labels instanceof Array && this.pdfDocument.numPages === labels.length)) {
- this._pageLabels = null;
- console.error('PDFThumbnailViewer_setPageLabels: Invalid page labels.');
- } else {
- this._pageLabels = labels;
- }
- // Update all the `PDFThumbnailView` instances.
- for (var i = 0, ii = this.thumbnails.length; i < ii; i++) {
- var thumbnailView = this.thumbnails[i];
- var label = this._pageLabels && this._pageLabels[i];
- thumbnailView.setPageLabel(label);
- }
- },
- /**
- * @param {PDFThumbnailView} thumbView
- * @returns {PDFPage}
- * @private
- */
- _ensurePdfPageLoaded: function PDFThumbnailViewer_ensurePdfPageLoaded(thumbView) {
- if (thumbView.pdfPage) {
- return Promise.resolve(thumbView.pdfPage);
- }
- var pageNumber = thumbView.id;
- if (this._pagesRequests[pageNumber]) {
- return this._pagesRequests[pageNumber];
- }
- var promise = this.pdfDocument.getPage(pageNumber).then(function (pdfPage) {
- thumbView.setPdfPage(pdfPage);
- this._pagesRequests[pageNumber] = null;
- return pdfPage;
- }.bind(this));
- this._pagesRequests[pageNumber] = promise;
- return promise;
- },
- forceRendering: function () {
- var visibleThumbs = this._getVisibleThumbs();
- var thumbView = this.renderingQueue.getHighestPriority(visibleThumbs, this.thumbnails, this.scroll.down);
- if (thumbView) {
- this._ensurePdfPageLoaded(thumbView).then(function () {
- this.renderingQueue.renderView(thumbView);
- }.bind(this));
- return true;
- }
- return false;
- }
- };
- return PDFThumbnailViewer;
- }();
- exports.PDFThumbnailViewer = PDFThumbnailViewer;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebTextLayerBuilder = {}, root.pdfjsWebDOMEvents, root.pdfjsWebPDFJS);
- }(this, function (exports, domEvents, pdfjsLib) {
- var EXPAND_DIVS_TIMEOUT = 300;
- // ms
- /**
- * @typedef {Object} TextLayerBuilderOptions
- * @property {HTMLDivElement} textLayerDiv - The text layer container.
- * @property {EventBus} eventBus - The application event bus.
- * @property {number} pageIndex - The page index.
- * @property {PageViewport} viewport - The viewport of the text layer.
- * @property {PDFFindController} findController
- * @property {boolean} enhanceTextSelection - Option to turn on improved
- * text selection.
- */
- /**
- * TextLayerBuilder provides text-selection functionality for the PDF.
- * It does this by creating overlay divs over the PDF text. These divs
- * contain text that matches the PDF text they are overlaying. This object
- * also provides a way to highlight text that is being searched for.
- * @class
- */
- var TextLayerBuilder = function TextLayerBuilderClosure() {
- function TextLayerBuilder(options) {
- this.textLayerDiv = options.textLayerDiv;
- this.eventBus = options.eventBus || domEvents.getGlobalEventBus();
- this.textContent = null;
- this.renderingDone = false;
- this.pageIdx = options.pageIndex;
- this.pageNumber = this.pageIdx + 1;
- this.matches = [];
- this.viewport = options.viewport;
- this.textDivs = [];
- this.findController = options.findController || null;
- this.textLayerRenderTask = null;
- this.enhanceTextSelection = options.enhanceTextSelection;
- this._bindMouse();
- }
- TextLayerBuilder.prototype = {
- /**
- * @private
- */
- _finishRendering: function TextLayerBuilder_finishRendering() {
- this.renderingDone = true;
- if (!this.enhanceTextSelection) {
- var endOfContent = document.createElement('div');
- endOfContent.className = 'endOfContent';
- this.textLayerDiv.appendChild(endOfContent);
- }
- this.eventBus.dispatch('textlayerrendered', {
- source: this,
- pageNumber: this.pageNumber,
- numTextDivs: this.textDivs.length
- });
- },
- /**
- * Renders the text layer.
- * @param {number} timeout (optional) if specified, the rendering waits
- * for specified amount of ms.
- */
- render: function TextLayerBuilder_render(timeout) {
- if (!this.textContent || this.renderingDone) {
- return;
- }
- this.cancel();
- this.textDivs = [];
- var textLayerFrag = document.createDocumentFragment();
- this.textLayerRenderTask = pdfjsLib.renderTextLayer({
- textContent: this.textContent,
- container: textLayerFrag,
- viewport: this.viewport,
- textDivs: this.textDivs,
- timeout: timeout,
- enhanceTextSelection: this.enhanceTextSelection
- });
- this.textLayerRenderTask.promise.then(function () {
- this.textLayerDiv.appendChild(textLayerFrag);
- this._finishRendering();
- this.updateMatches();
- }.bind(this), function (reason) {
- });
- },
- /**
- * Cancels rendering of the text layer.
- */
- cancel: function TextLayerBuilder_cancel() {
- if (this.textLayerRenderTask) {
- this.textLayerRenderTask.cancel();
- this.textLayerRenderTask = null;
- }
- },
- setTextContent: function TextLayerBuilder_setTextContent(textContent) {
- this.cancel();
- this.textContent = textContent;
- },
- convertMatches: function TextLayerBuilder_convertMatches(matches, matchesLength) {
- var i = 0;
- var iIndex = 0;
- var bidiTexts = this.textContent.items;
- var end = bidiTexts.length - 1;
- var queryLen = this.findController === null ? 0 : this.findController.state.query.length;
- var ret = [];
- if (!matches) {
- return ret;
- }
- for (var m = 0, len = matches.length; m < len; m++) {
- // Calculate the start position.
- var matchIdx = matches[m];
- // Loop over the divIdxs.
- while (i !== end && matchIdx >= iIndex + bidiTexts[i].str.length) {
- iIndex += bidiTexts[i].str.length;
- i++;
- }
- if (i === bidiTexts.length) {
- console.error('Could not find a matching mapping');
- }
- var match = {
- begin: {
- divIdx: i,
- offset: matchIdx - iIndex
- }
- };
- // Calculate the end position.
- if (matchesLength) {
- // multiterm search
- matchIdx += matchesLength[m];
- } else {
- // phrase search
- matchIdx += queryLen;
- }
- // Somewhat the same array as above, but use > instead of >= to get
- // the end position right.
- while (i !== end && matchIdx > iIndex + bidiTexts[i].str.length) {
- iIndex += bidiTexts[i].str.length;
- i++;
- }
- match.end = {
- divIdx: i,
- offset: matchIdx - iIndex
- };
- ret.push(match);
- }
- return ret;
- },
- renderMatches: function TextLayerBuilder_renderMatches(matches) {
- // Early exit if there is nothing to render.
- if (matches.length === 0) {
- return;
- }
- var bidiTexts = this.textContent.items;
- var textDivs = this.textDivs;
- var prevEnd = null;
- var pageIdx = this.pageIdx;
- var isSelectedPage = this.findController === null ? false : pageIdx === this.findController.selected.pageIdx;
- var selectedMatchIdx = this.findController === null ? -1 : this.findController.selected.matchIdx;
- var highlightAll = this.findController === null ? false : this.findController.state.highlightAll;
- var infinity = {
- divIdx: -1,
- offset: undefined
- };
- function beginText(begin, className) {
- var divIdx = begin.divIdx;
- textDivs[divIdx].textContent = '';
- appendTextToDiv(divIdx, 0, begin.offset, className);
- }
- function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
- var div = textDivs[divIdx];
- var content = bidiTexts[divIdx].str.substring(fromOffset, toOffset);
- var node = document.createTextNode(content);
- if (className) {
- var span = document.createElement('span');
- span.className = className;
- span.appendChild(node);
- div.appendChild(span);
- return;
- }
- div.appendChild(node);
- }
- var i0 = selectedMatchIdx, i1 = i0 + 1;
- if (highlightAll) {
- i0 = 0;
- i1 = matches.length;
- } else if (!isSelectedPage) {
- // Not highlighting all and this isn't the selected page, so do nothing.
- return;
- }
- for (var i = i0; i < i1; i++) {
- var match = matches[i];
- var begin = match.begin;
- var end = match.end;
- var isSelected = isSelectedPage && i === selectedMatchIdx;
- var highlightSuffix = isSelected ? ' selected' : '';
- if (this.findController) {
- this.findController.updateMatchPosition(pageIdx, i, textDivs, begin.divIdx);
- }
- // Match inside new div.
- if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
- // If there was a previous div, then add the text at the end.
- if (prevEnd !== null) {
- appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
- }
- // Clear the divs and set the content until the starting point.
- beginText(begin);
- } else {
- appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);
- }
- if (begin.divIdx === end.divIdx) {
- appendTextToDiv(begin.divIdx, begin.offset, end.offset, 'highlight' + highlightSuffix);
- } else {
- appendTextToDiv(begin.divIdx, begin.offset, infinity.offset, 'highlight begin' + highlightSuffix);
- for (var n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {
- textDivs[n0].className = 'highlight middle' + highlightSuffix;
- }
- beginText(end, 'highlight end' + highlightSuffix);
- }
- prevEnd = end;
- }
- if (prevEnd) {
- appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
- }
- },
- updateMatches: function TextLayerBuilder_updateMatches() {
- // Only show matches when all rendering is done.
- if (!this.renderingDone) {
- return;
- }
- // Clear all matches.
- var matches = this.matches;
- var textDivs = this.textDivs;
- var bidiTexts = this.textContent.items;
- var clearedUntilDivIdx = -1;
- // Clear all current matches.
- for (var i = 0, len = matches.length; i < len; i++) {
- var match = matches[i];
- var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
- for (var n = begin, end = match.end.divIdx; n <= end; n++) {
- var div = textDivs[n];
- div.textContent = bidiTexts[n].str;
- div.className = '';
- }
- clearedUntilDivIdx = match.end.divIdx + 1;
- }
- if (this.findController === null || !this.findController.active) {
- return;
- }
- // Convert the matches on the page controller into the match format
- // used for the textLayer.
- var pageMatches, pageMatchesLength;
- if (this.findController !== null) {
- pageMatches = this.findController.pageMatches[this.pageIdx] || null;
- pageMatchesLength = this.findController.pageMatchesLength ? this.findController.pageMatchesLength[this.pageIdx] || null : null;
- }
- this.matches = this.convertMatches(pageMatches, pageMatchesLength);
- this.renderMatches(this.matches);
- },
- /**
- * Fixes text selection: adds additional div where mouse was clicked.
- * This reduces flickering of the content if mouse slowly dragged down/up.
- * @private
- */
- _bindMouse: function TextLayerBuilder_bindMouse() {
- var div = this.textLayerDiv;
- var self = this;
- var expandDivsTimer = null;
- div.addEventListener('mousedown', function (e) {
- if (self.enhanceTextSelection && self.textLayerRenderTask) {
- self.textLayerRenderTask.expandTextDivs(true);
- return;
- }
- var end = div.querySelector('.endOfContent');
- if (!end) {
- return;
- }
- end.classList.add('active');
- });
- div.addEventListener('mouseup', function (e) {
- if (self.enhanceTextSelection && self.textLayerRenderTask) {
- self.textLayerRenderTask.expandTextDivs(false);
- return;
- }
- var end = div.querySelector('.endOfContent');
- if (!end) {
- return;
- }
- end.classList.remove('active');
- });
- }
- };
- return TextLayerBuilder;
- }();
- /**
- * @constructor
- * @implements IPDFTextLayerFactory
- */
- function DefaultTextLayerFactory() {
- }
- DefaultTextLayerFactory.prototype = {
- /**
- * @param {HTMLDivElement} textLayerDiv
- * @param {number} pageIndex
- * @param {PageViewport} viewport
- * @param {boolean} enhanceTextSelection
- * @returns {TextLayerBuilder}
- */
- createTextLayerBuilder: function (textLayerDiv, pageIndex, viewport, enhanceTextSelection) {
- return new TextLayerBuilder({
- textLayerDiv: textLayerDiv,
- pageIndex: pageIndex,
- viewport: viewport,
- enhanceTextSelection: enhanceTextSelection
- });
- }
- };
- exports.TextLayerBuilder = TextLayerBuilder;
- exports.DefaultTextLayerFactory = DefaultTextLayerFactory;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebAnnotationLayerBuilder = {}, root.pdfjsWebUIUtils, root.pdfjsWebPDFLinkService, root.pdfjsWebPDFJS);
- }(this, function (exports, uiUtils, pdfLinkService, pdfjsLib) {
- var mozL10n = uiUtils.mozL10n;
- var SimpleLinkService = pdfLinkService.SimpleLinkService;
- /**
- * @typedef {Object} AnnotationLayerBuilderOptions
- * @property {HTMLDivElement} pageDiv
- * @property {PDFPage} pdfPage
- * @property {boolean} renderInteractiveForms
- * @property {IPDFLinkService} linkService
- * @property {DownloadManager} downloadManager
- */
- /**
- * @class
- */
- var AnnotationLayerBuilder = function AnnotationLayerBuilderClosure() {
- /**
- * @param {AnnotationLayerBuilderOptions} options
- * @constructs AnnotationLayerBuilder
- */
- function AnnotationLayerBuilder(options) {
- this.pageDiv = options.pageDiv;
- this.pdfPage = options.pdfPage;
- this.renderInteractiveForms = options.renderInteractiveForms;
- this.linkService = options.linkService;
- this.downloadManager = options.downloadManager;
- this.div = null;
- }
- AnnotationLayerBuilder.prototype = /** @lends AnnotationLayerBuilder.prototype */
- {
- /**
- * @param {PageViewport} viewport
- * @param {string} intent (default value is 'display')
- */
- render: function AnnotationLayerBuilder_render(viewport, intent) {
- var self = this;
- var parameters = { intent: intent === undefined ? 'display' : intent };
- this.pdfPage.getAnnotations(parameters).then(function (annotations) {
- viewport = viewport.clone({ dontFlip: true });
- parameters = {
- viewport: viewport,
- div: self.div,
- annotations: annotations,
- page: self.pdfPage,
- renderInteractiveForms: self.renderInteractiveForms,
- linkService: self.linkService,
- downloadManager: self.downloadManager
- };
- if (self.div) {
- // If an annotationLayer already exists, refresh its children's
- // transformation matrices.
- pdfjsLib.AnnotationLayer.update(parameters);
- } else {
- // Create an annotation layer div and render the annotations
- // if there is at least one annotation.
- if (annotations.length === 0) {
- return;
- }
- self.div = document.createElement('div');
- self.div.className = 'annotationLayer';
- self.pageDiv.appendChild(self.div);
- parameters.div = self.div;
- pdfjsLib.AnnotationLayer.render(parameters);
- if (typeof mozL10n !== 'undefined') {
- mozL10n.translate(self.div);
- }
- }
- });
- },
- hide: function AnnotationLayerBuilder_hide() {
- if (!this.div) {
- return;
- }
- this.div.setAttribute('hidden', 'true');
- }
- };
- return AnnotationLayerBuilder;
- }();
- /**
- * @constructor
- * @implements IPDFAnnotationLayerFactory
- */
- function DefaultAnnotationLayerFactory() {
- }
- DefaultAnnotationLayerFactory.prototype = {
- /**
- * @param {HTMLDivElement} pageDiv
- * @param {PDFPage} pdfPage
- * @param {boolean} renderInteractiveForms
- * @returns {AnnotationLayerBuilder}
- */
- createAnnotationLayerBuilder: function (pageDiv, pdfPage, renderInteractiveForms) {
- return new AnnotationLayerBuilder({
- pageDiv: pageDiv,
- pdfPage: pdfPage,
- renderInteractiveForms: renderInteractiveForms,
- linkService: new SimpleLinkService()
- });
- }
- };
- exports.AnnotationLayerBuilder = AnnotationLayerBuilder;
- exports.DefaultAnnotationLayerFactory = DefaultAnnotationLayerFactory;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebPDFViewer = {}, root.pdfjsWebUIUtils, root.pdfjsWebPDFPageView, root.pdfjsWebPDFRenderingQueue, root.pdfjsWebTextLayerBuilder, root.pdfjsWebAnnotationLayerBuilder, root.pdfjsWebPDFLinkService, root.pdfjsWebDOMEvents, root.pdfjsWebPDFJS);
- }(this, function (exports, uiUtils, pdfPageView, pdfRenderingQueue, textLayerBuilder, annotationLayerBuilder, pdfLinkService, domEvents, pdfjsLib) {
- var UNKNOWN_SCALE = uiUtils.UNKNOWN_SCALE;
- var SCROLLBAR_PADDING = uiUtils.SCROLLBAR_PADDING;
- var VERTICAL_PADDING = uiUtils.VERTICAL_PADDING;
- var MAX_AUTO_SCALE = uiUtils.MAX_AUTO_SCALE;
- var CSS_UNITS = uiUtils.CSS_UNITS;
- var DEFAULT_SCALE = uiUtils.DEFAULT_SCALE;
- var DEFAULT_SCALE_VALUE = uiUtils.DEFAULT_SCALE_VALUE;
- var scrollIntoView = uiUtils.scrollIntoView;
- var watchScroll = uiUtils.watchScroll;
- var getVisibleElements = uiUtils.getVisibleElements;
- var PDFPageView = pdfPageView.PDFPageView;
- var RenderingStates = pdfRenderingQueue.RenderingStates;
- var PDFRenderingQueue = pdfRenderingQueue.PDFRenderingQueue;
- var TextLayerBuilder = textLayerBuilder.TextLayerBuilder;
- var AnnotationLayerBuilder = annotationLayerBuilder.AnnotationLayerBuilder;
- var SimpleLinkService = pdfLinkService.SimpleLinkService;
- var PresentationModeState = {
- UNKNOWN: 0,
- NORMAL: 1,
- CHANGING: 2,
- FULLSCREEN: 3
- };
- var DEFAULT_CACHE_SIZE = 10;
- /**
- * @typedef {Object} PDFViewerOptions
- * @property {HTMLDivElement} container - The container for the viewer element.
- * @property {HTMLDivElement} viewer - (optional) The viewer element.
- * @property {EventBus} eventBus - The application event bus.
- * @property {IPDFLinkService} linkService - The navigation/linking service.
- * @property {DownloadManager} downloadManager - (optional) The download
- * manager component.
- * @property {PDFRenderingQueue} renderingQueue - (optional) The rendering
- * queue object.
- * @property {boolean} removePageBorders - (optional) Removes the border shadow
- * around the pages. The default is false.
- * @property {boolean} enhanceTextSelection - (optional) Enables the improved
- * text selection behaviour. The default is `false`.
- * @property {boolean} renderInteractiveForms - (optional) Enables rendering of
- * interactive form elements. The default is `false`.
- */
- /**
- * Simple viewer control to display PDF content/pages.
- * @class
- * @implements {IRenderableView}
- */
- var PDFViewer = function pdfViewer() {
- function PDFPageViewBuffer(size) {
- var data = [];
- this.push = function cachePush(view) {
- var i = data.indexOf(view);
- if (i >= 0) {
- data.splice(i, 1);
- }
- data.push(view);
- if (data.length > size) {
- data.shift().destroy();
- }
- };
- this.resize = function (newSize) {
- size = newSize;
- while (data.length > size) {
- data.shift().destroy();
- }
- };
- }
- function isSameScale(oldScale, newScale) {
- if (newScale === oldScale) {
- return true;
- }
- if (Math.abs(newScale - oldScale) < 1e-15) {
- // Prevent unnecessary re-rendering of all pages when the scale
- // changes only because of limited numerical precision.
- return true;
- }
- return false;
- }
- /**
- * @constructs PDFViewer
- * @param {PDFViewerOptions} options
- */
- function PDFViewer(options) {
- this.container = options.container;
- this.viewer = options.viewer || options.container.firstElementChild;
- this.eventBus = options.eventBus || domEvents.getGlobalEventBus();
- this.linkService = options.linkService || new SimpleLinkService();
- this.downloadManager = options.downloadManager || null;
- this.removePageBorders = options.removePageBorders || false;
- this.enhanceTextSelection = options.enhanceTextSelection || false;
- this.renderInteractiveForms = options.renderInteractiveForms || false;
- this.defaultRenderingQueue = !options.renderingQueue;
- if (this.defaultRenderingQueue) {
- // Custom rendering queue is not specified, using default one
- this.renderingQueue = new PDFRenderingQueue();
- this.renderingQueue.setViewer(this);
- } else {
- this.renderingQueue = options.renderingQueue;
- }
- this.scroll = watchScroll(this.container, this._scrollUpdate.bind(this));
- this.presentationModeState = PresentationModeState.UNKNOWN;
- this._resetView();
- if (this.removePageBorders) {
- this.viewer.classList.add('removePageBorders');
- }
- }
- PDFViewer.prototype = /** @lends PDFViewer.prototype */
- {
- get pagesCount() {
- return this._pages.length;
- },
- getPageView: function (index) {
- return this._pages[index];
- },
- /**
- * @returns {boolean} true if all {PDFPageView} objects are initialized.
- */
- get pageViewsReady() {
- return this._pageViewsReady;
- },
- /**
- * @returns {number}
- */
- get currentPageNumber() {
- return this._currentPageNumber;
- },
- /**
- * @param {number} val - The page number.
- */
- set currentPageNumber(val) {
- if ((val | 0) !== val) {
- // Ensure that `val` is an integer.
- throw new Error('Invalid page number.');
- }
- if (!this.pdfDocument) {
- this._currentPageNumber = val;
- return;
- }
- // The intent can be to just reset a scroll position and/or scale.
- this._setCurrentPageNumber(val, /* resetCurrentPageView = */
- true);
- },
- /**
- * @private
- */
- _setCurrentPageNumber: function PDFViewer_setCurrentPageNumber(val, resetCurrentPageView) {
- if (this._currentPageNumber === val) {
- if (resetCurrentPageView) {
- this._resetCurrentPageView();
- }
- return;
- }
- if (!(0 < val && val <= this.pagesCount)) {
- console.error('PDFViewer_setCurrentPageNumber: "' + val + '" is out of bounds.');
- return;
- }
- var arg = {
- source: this,
- pageNumber: val,
- pageLabel: this._pageLabels && this._pageLabels[val - 1]
- };
- this._currentPageNumber = val;
- this.eventBus.dispatch('pagechanging', arg);
- this.eventBus.dispatch('pagechange', arg);
- if (resetCurrentPageView) {
- this._resetCurrentPageView();
- }
- },
- /**
- * @returns {string|null} Returns the current page label,
- * or `null` if no page labels exist.
- */
- get currentPageLabel() {
- return this._pageLabels && this._pageLabels[this._currentPageNumber - 1];
- },
- /**
- * @param {string} val - The page label.
- */
- set currentPageLabel(val) {
- var pageNumber = val | 0;
- // Fallback page number.
- if (this._pageLabels) {
- var i = this._pageLabels.indexOf(val);
- if (i >= 0) {
- pageNumber = i + 1;
- }
- }
- this.currentPageNumber = pageNumber;
- },
- /**
- * @returns {number}
- */
- get currentScale() {
- return this._currentScale !== UNKNOWN_SCALE ? this._currentScale : DEFAULT_SCALE;
- },
- /**
- * @param {number} val - Scale of the pages in percents.
- */
- set currentScale(val) {
- if (isNaN(val)) {
- throw new Error('Invalid numeric scale');
- }
- if (!this.pdfDocument) {
- this._currentScale = val;
- this._currentScaleValue = val !== UNKNOWN_SCALE ? val.toString() : null;
- return;
- }
- this._setScale(val, false);
- },
- /**
- * @returns {string}
- */
- get currentScaleValue() {
- return this._currentScaleValue;
- },
- /**
- * @param val - The scale of the pages (in percent or predefined value).
- */
- set currentScaleValue(val) {
- if (!this.pdfDocument) {
- this._currentScale = isNaN(val) ? UNKNOWN_SCALE : val;
- this._currentScaleValue = val.toString();
- return;
- }
- this._setScale(val, false);
- },
- /**
- * @returns {number}
- */
- get pagesRotation() {
- return this._pagesRotation;
- },
- /**
- * @param {number} rotation - The rotation of the pages (0, 90, 180, 270).
- */
- set pagesRotation(rotation) {
- if (!(typeof rotation === 'number' && rotation % 90 === 0)) {
- throw new Error('Invalid pages rotation angle.');
- }
- this._pagesRotation = rotation;
- if (!this.pdfDocument) {
- return;
- }
- for (var i = 0, l = this._pages.length; i < l; i++) {
- var pageView = this._pages[i];
- pageView.update(pageView.scale, rotation);
- }
- this._setScale(this._currentScaleValue, true);
- if (this.defaultRenderingQueue) {
- this.update();
- }
- },
- /**
- * @param pdfDocument {PDFDocument}
- */
- setDocument: function (pdfDocument) {
- if (this.pdfDocument) {
- this._cancelRendering();
- this._resetView();
- }
- this.pdfDocument = pdfDocument;
- if (!pdfDocument) {
- return;
- }
- var pagesCount = pdfDocument.numPages;
- var self = this;
- var resolvePagesPromise;
- var pagesPromise = new Promise(function (resolve) {
- resolvePagesPromise = resolve;
- });
- this.pagesPromise = pagesPromise;
- pagesPromise.then(function () {
- self._pageViewsReady = true;
- self.eventBus.dispatch('pagesloaded', {
- source: self,
- pagesCount: pagesCount
- });
- });
- var isOnePageRenderedResolved = false;
- var resolveOnePageRendered = null;
- var onePageRendered = new Promise(function (resolve) {
- resolveOnePageRendered = resolve;
- });
- this.onePageRendered = onePageRendered;
- var bindOnAfterAndBeforeDraw = function (pageView) {
- pageView.onBeforeDraw = function pdfViewLoadOnBeforeDraw() {
- // Add the page to the buffer at the start of drawing. That way it can
- // be evicted from the buffer and destroyed even if we pause its
- // rendering.
- self._buffer.push(this);
- };
- pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() {
- if (!isOnePageRenderedResolved) {
- isOnePageRenderedResolved = true;
- resolveOnePageRendered();
- }
- };
- };
- var firstPagePromise = pdfDocument.getPage(1);
- this.firstPagePromise = firstPagePromise;
- // Fetch a single page so we can get a viewport that will be the default
- // viewport for all pages
- return firstPagePromise.then(function (pdfPage) {
- var scale = this.currentScale;
- var viewport = pdfPage.getViewport(scale * CSS_UNITS);
- for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
- var textLayerFactory = null;
- if (!pdfjsLib.PDFJS.disableTextLayer) {
- textLayerFactory = this;
- }
- var pageView = new PDFPageView({
- container: this.viewer,
- eventBus: this.eventBus,
- id: pageNum,
- scale: scale,
- defaultViewport: viewport.clone(),
- renderingQueue: this.renderingQueue,
- textLayerFactory: textLayerFactory,
- annotationLayerFactory: this,
- enhanceTextSelection: this.enhanceTextSelection,
- renderInteractiveForms: this.renderInteractiveForms
- });
- bindOnAfterAndBeforeDraw(pageView);
- this._pages.push(pageView);
- }
- var linkService = this.linkService;
- // Fetch all the pages since the viewport is needed before printing
- // starts to create the correct size canvas. Wait until one page is
- // rendered so we don't tie up too many resources early on.
- onePageRendered.then(function () {
- if (!pdfjsLib.PDFJS.disableAutoFetch) {
- var getPagesLeft = pagesCount;
- for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
- pdfDocument.getPage(pageNum).then(function (pageNum, pdfPage) {
- var pageView = self._pages[pageNum - 1];
- if (!pageView.pdfPage) {
- pageView.setPdfPage(pdfPage);
- }
- linkService.cachePageRef(pageNum, pdfPage.ref);
- getPagesLeft--;
- if (!getPagesLeft) {
- resolvePagesPromise();
- }
- }.bind(null, pageNum));
- }
- } else {
- // XXX: Printing is semi-broken with auto fetch disabled.
- resolvePagesPromise();
- }
- });
- self.eventBus.dispatch('pagesinit', { source: self });
- if (this.defaultRenderingQueue) {
- this.update();
- }
- if (this.findController) {
- this.findController.resolveFirstPage();
- }
- }.bind(this));
- },
- /**
- * @param {Array|null} labels
- */
- setPageLabels: function PDFViewer_setPageLabels(labels) {
- if (!this.pdfDocument) {
- return;
- }
- if (!labels) {
- this._pageLabels = null;
- } else if (!(labels instanceof Array && this.pdfDocument.numPages === labels.length)) {
- this._pageLabels = null;
- console.error('PDFViewer_setPageLabels: Invalid page labels.');
- } else {
- this._pageLabels = labels;
- }
- // Update all the `PDFPageView` instances.
- for (var i = 0, ii = this._pages.length; i < ii; i++) {
- var pageView = this._pages[i];
- var label = this._pageLabels && this._pageLabels[i];
- pageView.setPageLabel(label);
- }
- },
- _resetView: function () {
- this._pages = [];
- this._currentPageNumber = 1;
- this._currentScale = UNKNOWN_SCALE;
- this._currentScaleValue = null;
- this._pageLabels = null;
- this._buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE);
- this._location = null;
- this._pagesRotation = 0;
- this._pagesRequests = [];
- this._pageViewsReady = false;
- // Remove the pages from the DOM.
- this.viewer.textContent = '';
- },
- _scrollUpdate: function PDFViewer_scrollUpdate() {
- if (this.pagesCount === 0) {
- return;
- }
- this.update();
- for (var i = 0, ii = this._pages.length; i < ii; i++) {
- this._pages[i].updatePosition();
- }
- },
- _setScaleDispatchEvent: function pdfViewer_setScaleDispatchEvent(newScale, newValue, preset) {
- var arg = {
- source: this,
- scale: newScale,
- presetValue: preset ? newValue : undefined
- };
- this.eventBus.dispatch('scalechanging', arg);
- this.eventBus.dispatch('scalechange', arg);
- },
- _setScaleUpdatePages: function pdfViewer_setScaleUpdatePages(newScale, newValue, noScroll, preset) {
- this._currentScaleValue = newValue.toString();
- if (isSameScale(this._currentScale, newScale)) {
- if (preset) {
- this._setScaleDispatchEvent(newScale, newValue, true);
- }
- return;
- }
- for (var i = 0, ii = this._pages.length; i < ii; i++) {
- this._pages[i].update(newScale);
- }
- this._currentScale = newScale;
- if (!noScroll) {
- var page = this._currentPageNumber, dest;
- if (this._location && !pdfjsLib.PDFJS.ignoreCurrentPositionOnZoom && !(this.isInPresentationMode || this.isChangingPresentationMode)) {
- page = this._location.pageNumber;
- dest = [
- null,
- { name: 'XYZ' },
- this._location.left,
- this._location.top,
- null
- ];
- }
- this.scrollPageIntoView({
- pageNumber: page,
- destArray: dest,
- allowNegativeOffset: true
- });
- }
- this._setScaleDispatchEvent(newScale, newValue, preset);
- if (this.defaultRenderingQueue) {
- this.update();
- }
- },
- _setScale: function PDFViewer_setScale(value, noScroll) {
- var scale = parseFloat(value);
- if (scale > 0) {
- this._setScaleUpdatePages(scale, value, noScroll, false);
- } else {
- var currentPage = this._pages[this._currentPageNumber - 1];
- if (!currentPage) {
- return;
- }
- var hPadding = this.isInPresentationMode || this.removePageBorders ? 0 : SCROLLBAR_PADDING;
- var vPadding = this.isInPresentationMode || this.removePageBorders ? 0 : VERTICAL_PADDING;
- var pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale;
- var pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale;
- switch (value) {
- case 'page-actual':
- scale = 1;
- break;
- case 'page-width':
- scale = pageWidthScale;
- break;
- case 'page-height':
- scale = pageHeightScale;
- break;
- case 'page-fit':
- scale = Math.min(pageWidthScale, pageHeightScale);
- break;
- case 'auto':
- var isLandscape = currentPage.width > currentPage.height;
- // For pages in landscape mode, fit the page height to the viewer
- // *unless* the page would thus become too wide to fit horizontally.
- var horizontalScale = isLandscape ? Math.min(pageHeightScale, pageWidthScale) : pageWidthScale;
- scale = Math.min(MAX_AUTO_SCALE, horizontalScale);
- break;
- default:
- console.error('PDFViewer_setScale: "' + value + '" is an unknown zoom value.');
- return;
- }
- this._setScaleUpdatePages(scale, value, noScroll, true);
- }
- },
- /**
- * Refreshes page view: scrolls to the current page and updates the scale.
- * @private
- */
- _resetCurrentPageView: function () {
- if (this.isInPresentationMode) {
- // Fixes the case when PDF has different page sizes.
- this._setScale(this._currentScaleValue, true);
- }
- var pageView = this._pages[this._currentPageNumber - 1];
- scrollIntoView(pageView.div);
- },
- /**
- * @typedef ScrollPageIntoViewParameters
- * @property {number} pageNumber - The page number.
- * @property {Array} destArray - (optional) The original PDF destination
- * array, in the format: <page-ref> </XYZ|/FitXXX> <args..>
- * @property {boolean} allowNegativeOffset - (optional) Allow negative page
- * offsets. The default value is `false`.
- */
- /**
- * Scrolls page into view.
- * @param {ScrollPageIntoViewParameters} params
- */
- scrollPageIntoView: function PDFViewer_scrollPageIntoView(params) {
- if (!this.pdfDocument) {
- return;
- }
- var pageNumber = params.pageNumber || 0;
- var dest = params.destArray || null;
- var allowNegativeOffset = params.allowNegativeOffset || false;
- if (this.isInPresentationMode || !dest) {
- this._setCurrentPageNumber(pageNumber, /* resetCurrentPageView */
- true);
- return;
- }
- var pageView = this._pages[pageNumber - 1];
- if (!pageView) {
- console.error('PDFViewer_scrollPageIntoView: ' + 'Invalid "pageNumber" parameter.');
- return;
- }
- var x = 0, y = 0;
- var width = 0, height = 0, widthScale, heightScale;
- var changeOrientation = pageView.rotation % 180 === 0 ? false : true;
- var pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / CSS_UNITS;
- var pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / CSS_UNITS;
- var scale = 0;
- switch (dest[1].name) {
- case 'XYZ':
- x = dest[2];
- y = dest[3];
- scale = dest[4];
- // If x and/or y coordinates are not supplied, default to
- // _top_ left of the page (not the obvious bottom left,
- // since aligning the bottom of the intended page with the
- // top of the window is rarely helpful).
- x = x !== null ? x : 0;
- y = y !== null ? y : pageHeight;
- break;
- case 'Fit':
- case 'FitB':
- scale = 'page-fit';
- break;
- case 'FitH':
- case 'FitBH':
- y = dest[2];
- scale = 'page-width';
- // According to the PDF spec, section 12.3.2.2, a `null` value in the
- // parameter should maintain the position relative to the new page.
- if (y === null && this._location) {
- x = this._location.left;
- y = this._location.top;
- }
- break;
- case 'FitV':
- case 'FitBV':
- x = dest[2];
- width = pageWidth;
- height = pageHeight;
- scale = 'page-height';
- break;
- case 'FitR':
- x = dest[2];
- y = dest[3];
- width = dest[4] - x;
- height = dest[5] - y;
- var hPadding = this.removePageBorders ? 0 : SCROLLBAR_PADDING;
- var vPadding = this.removePageBorders ? 0 : VERTICAL_PADDING;
- widthScale = (this.container.clientWidth - hPadding) / width / CSS_UNITS;
- heightScale = (this.container.clientHeight - vPadding) / height / CSS_UNITS;
- scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
- break;
- default:
- console.error('PDFViewer_scrollPageIntoView: \'' + dest[1].name + '\' is not a valid destination type.');
- return;
- }
- if (scale && scale !== this._currentScale) {
- this.currentScaleValue = scale;
- } else if (this._currentScale === UNKNOWN_SCALE) {
- this.currentScaleValue = DEFAULT_SCALE_VALUE;
- }
- if (scale === 'page-fit' && !dest[4]) {
- scrollIntoView(pageView.div);
- return;
- }
- var boundingRect = [
- pageView.viewport.convertToViewportPoint(x, y),
- pageView.viewport.convertToViewportPoint(x + width, y + height)
- ];
- var left = Math.min(boundingRect[0][0], boundingRect[1][0]);
- var top = Math.min(boundingRect[0][1], boundingRect[1][1]);
- if (!allowNegativeOffset) {
- // Some bad PDF generators will create destinations with e.g. top values
- // that exceeds the page height. Ensure that offsets are not negative,
- // to prevent a previous page from becoming visible (fixes bug 874482).
- left = Math.max(left, 0);
- top = Math.max(top, 0);
- }
- scrollIntoView(pageView.div, {
- left: left,
- top: top
- });
- },
- _updateLocation: function (firstPage) {
- var currentScale = this._currentScale;
- var currentScaleValue = this._currentScaleValue;
- var normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ? Math.round(currentScale * 10000) / 100 : currentScaleValue;
- var pageNumber = firstPage.id;
- var pdfOpenParams = '#page=' + pageNumber;
- pdfOpenParams += '&zoom=' + normalizedScaleValue;
- var currentPageView = this._pages[pageNumber - 1];
- var container = this.container;
- var topLeft = currentPageView.getPagePoint(container.scrollLeft - firstPage.x, container.scrollTop - firstPage.y);
- var intLeft = Math.round(topLeft[0]);
- var intTop = Math.round(topLeft[1]);
- pdfOpenParams += ',' + intLeft + ',' + intTop;
- this._location = {
- pageNumber: pageNumber,
- scale: normalizedScaleValue,
- top: intTop,
- left: intLeft,
- pdfOpenParams: pdfOpenParams
- };
- },
- update: function PDFViewer_update() {
- var visible = this._getVisiblePages();
- var visiblePages = visible.views;
- if (visiblePages.length === 0) {
- return;
- }
- var suggestedCacheSize = Math.max(DEFAULT_CACHE_SIZE, 2 * visiblePages.length + 1);
- this._buffer.resize(suggestedCacheSize);
- this.renderingQueue.renderHighestPriority(visible);
- var currentId = this._currentPageNumber;
- var firstPage = visible.first;
- for (var i = 0, ii = visiblePages.length, stillFullyVisible = false; i < ii; ++i) {
- var page = visiblePages[i];
- if (page.percent < 100) {
- break;
- }
- if (page.id === currentId) {
- stillFullyVisible = true;
- break;
- }
- }
- if (!stillFullyVisible) {
- currentId = visiblePages[0].id;
- }
- if (!this.isInPresentationMode) {
- this._setCurrentPageNumber(currentId);
- }
- this._updateLocation(firstPage);
- this.eventBus.dispatch('updateviewarea', {
- source: this,
- location: this._location
- });
- },
- containsElement: function (element) {
- return this.container.contains(element);
- },
- focus: function () {
- this.container.focus();
- },
- get isInPresentationMode() {
- return this.presentationModeState === PresentationModeState.FULLSCREEN;
- },
- get isChangingPresentationMode() {
- return this.presentationModeState === PresentationModeState.CHANGING;
- },
- get isHorizontalScrollbarEnabled() {
- return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth;
- },
- _getVisiblePages: function () {
- if (!this.isInPresentationMode) {
- return getVisibleElements(this.container, this._pages, true);
- } else {
- // The algorithm in getVisibleElements doesn't work in all browsers and
- // configurations when presentation mode is active.
- var visible = [];
- var currentPage = this._pages[this._currentPageNumber - 1];
- visible.push({
- id: currentPage.id,
- view: currentPage
- });
- return {
- first: currentPage,
- last: currentPage,
- views: visible
- };
- }
- },
- cleanup: function () {
- for (var i = 0, ii = this._pages.length; i < ii; i++) {
- if (this._pages[i] && this._pages[i].renderingState !== RenderingStates.FINISHED) {
- this._pages[i].reset();
- }
- }
- },
- /**
- * @private
- */
- _cancelRendering: function PDFViewer_cancelRendering() {
- for (var i = 0, ii = this._pages.length; i < ii; i++) {
- if (this._pages[i]) {
- this._pages[i].cancelRendering();
- }
- }
- },
- /**
- * @param {PDFPageView} pageView
- * @returns {PDFPage}
- * @private
- */
- _ensurePdfPageLoaded: function (pageView) {
- if (pageView.pdfPage) {
- return Promise.resolve(pageView.pdfPage);
- }
- var pageNumber = pageView.id;
- if (this._pagesRequests[pageNumber]) {
- return this._pagesRequests[pageNumber];
- }
- var promise = this.pdfDocument.getPage(pageNumber).then(function (pdfPage) {
- pageView.setPdfPage(pdfPage);
- this._pagesRequests[pageNumber] = null;
- return pdfPage;
- }.bind(this));
- this._pagesRequests[pageNumber] = promise;
- return promise;
- },
- forceRendering: function (currentlyVisiblePages) {
- var visiblePages = currentlyVisiblePages || this._getVisiblePages();
- var pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, this.scroll.down);
- if (pageView) {
- this._ensurePdfPageLoaded(pageView).then(function () {
- this.renderingQueue.renderView(pageView);
- }.bind(this));
- return true;
- }
- return false;
- },
- getPageTextContent: function (pageIndex) {
- return this.pdfDocument.getPage(pageIndex + 1).then(function (page) {
- return page.getTextContent({ normalizeWhitespace: true });
- });
- },
- /**
- * @param {HTMLDivElement} textLayerDiv
- * @param {number} pageIndex
- * @param {PageViewport} viewport
- * @returns {TextLayerBuilder}
- */
- createTextLayerBuilder: function (textLayerDiv, pageIndex, viewport, enhanceTextSelection) {
- return new TextLayerBuilder({
- textLayerDiv: textLayerDiv,
- eventBus: this.eventBus,
- pageIndex: pageIndex,
- viewport: viewport,
- findController: this.isInPresentationMode ? null : this.findController,
- enhanceTextSelection: this.isInPresentationMode ? false : enhanceTextSelection
- });
- },
- /**
- * @param {HTMLDivElement} pageDiv
- * @param {PDFPage} pdfPage
- * @param {boolean} renderInteractiveForms
- * @returns {AnnotationLayerBuilder}
- */
- createAnnotationLayerBuilder: function (pageDiv, pdfPage, renderInteractiveForms) {
- return new AnnotationLayerBuilder({
- pageDiv: pageDiv,
- pdfPage: pdfPage,
- renderInteractiveForms: renderInteractiveForms,
- linkService: this.linkService,
- downloadManager: this.downloadManager
- });
- },
- setFindController: function (findController) {
- this.findController = findController;
- },
- /**
- * Returns sizes of the pages.
- * @returns {Array} Array of objects with width/height fields.
- */
- getPagesOverview: function () {
- return this._pages.map(function (pageView) {
- var viewport = pageView.pdfPage.getViewport(1);
- return {
- width: viewport.width,
- height: viewport.height
- };
- });
- }
- };
- return PDFViewer;
- }();
- exports.PresentationModeState = PresentationModeState;
- exports.PDFViewer = PDFViewer;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebApp = {}, root.pdfjsWebUIUtils, root.pdfjsWebDownloadManager, root.pdfjsWebPDFHistory, root.pdfjsWebPreferences, root.pdfjsWebPDFSidebar, root.pdfjsWebViewHistory, root.pdfjsWebPDFThumbnailViewer, root.pdfjsWebSecondaryToolbar, root.pdfjsWebPasswordPrompt, root.pdfjsWebPDFPresentationMode, root.pdfjsWebPDFDocumentProperties, root.pdfjsWebHandTool, root.pdfjsWebPDFViewer, root.pdfjsWebPDFRenderingQueue, root.pdfjsWebPDFLinkService, root.pdfjsWebPDFOutlineViewer, root.pdfjsWebOverlayManager, root.pdfjsWebPDFAttachmentViewer, root.pdfjsWebPDFFindController, root.pdfjsWebPDFFindBar, root.pdfjsWebDOMEvents, root.pdfjsWebPDFJS);
- }(this, function (exports, uiUtilsLib, downloadManagerLib, pdfHistoryLib, preferencesLib, pdfSidebarLib, viewHistoryLib, pdfThumbnailViewerLib, secondaryToolbarLib, passwordPromptLib, pdfPresentationModeLib, pdfDocumentPropertiesLib, handToolLib, pdfViewerLib, pdfRenderingQueueLib, pdfLinkServiceLib, pdfOutlineViewerLib, overlayManagerLib, pdfAttachmentViewerLib, pdfFindControllerLib, pdfFindBarLib, domEventsLib, pdfjsLib) {
- var UNKNOWN_SCALE = uiUtilsLib.UNKNOWN_SCALE;
- var DEFAULT_SCALE_VALUE = uiUtilsLib.DEFAULT_SCALE_VALUE;
- var ProgressBar = uiUtilsLib.ProgressBar;
- var getPDFFileNameFromURL = uiUtilsLib.getPDFFileNameFromURL;
- var noContextMenuHandler = uiUtilsLib.noContextMenuHandler;
- var mozL10n = uiUtilsLib.mozL10n;
- var parseQueryString = uiUtilsLib.parseQueryString;
- var PDFHistory = pdfHistoryLib.PDFHistory;
- var Preferences = preferencesLib.Preferences;
- var SidebarView = pdfSidebarLib.SidebarView;
- var PDFSidebar = pdfSidebarLib.PDFSidebar;
- var ViewHistory = viewHistoryLib.ViewHistory;
- var PDFThumbnailViewer = pdfThumbnailViewerLib.PDFThumbnailViewer;
- var SecondaryToolbar = secondaryToolbarLib.SecondaryToolbar;
- var PasswordPrompt = passwordPromptLib.PasswordPrompt;
- var PDFPresentationMode = pdfPresentationModeLib.PDFPresentationMode;
- var PDFDocumentProperties = pdfDocumentPropertiesLib.PDFDocumentProperties;
- var HandTool = handToolLib.HandTool;
- var PresentationModeState = pdfViewerLib.PresentationModeState;
- var PDFViewer = pdfViewerLib.PDFViewer;
- var RenderingStates = pdfRenderingQueueLib.RenderingStates;
- var PDFRenderingQueue = pdfRenderingQueueLib.PDFRenderingQueue;
- var PDFLinkService = pdfLinkServiceLib.PDFLinkService;
- var PDFOutlineViewer = pdfOutlineViewerLib.PDFOutlineViewer;
- var OverlayManager = overlayManagerLib.OverlayManager;
- var PDFAttachmentViewer = pdfAttachmentViewerLib.PDFAttachmentViewer;
- var PDFFindController = pdfFindControllerLib.PDFFindController;
- var PDFFindBar = pdfFindBarLib.PDFFindBar;
- var getGlobalEventBus = domEventsLib.getGlobalEventBus;
- var normalizeWheelEventDelta = uiUtilsLib.normalizeWheelEventDelta;
- var DEFAULT_SCALE_DELTA = 1.1;
- var MIN_SCALE = 0.25;
- var MAX_SCALE = 10.0;
- var SCALE_SELECT_CONTAINER_PADDING = 8;
- var SCALE_SELECT_PADDING = 22;
- var PAGE_NUMBER_LOADING_INDICATOR = 'visiblePageIsLoading';
- var DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000;
- function configure(PDFJS) {
- PDFJS.imageResourcesPath = './images/';
- PDFJS.workerSrc = '../build/pdf.worker.js';
- PDFJS.cMapUrl = '../web/cmaps/';
- PDFJS.cMapPacked = true;
- }
- var DefaultExernalServices = {
- updateFindControlState: function (data) {
- },
- initPassiveLoading: function (callbacks) {
- },
- fallback: function (data, callback) {
- },
- reportTelemetry: function (data) {
- },
- createDownloadManager: function () {
- return new downloadManagerLib.DownloadManager();
- },
- supportsIntegratedFind: false,
- supportsDocumentFonts: true,
- supportsDocumentColors: true,
- supportedMouseWheelZoomModifierKeys: {
- ctrlKey: true,
- metaKey: true
- }
- };
- var PDFViewerApplication = {
- initialBookmark: document.location.hash.substring(1),
- initialDestination: null,
- initialized: false,
- fellback: false,
- appConfig: null,
- pdfDocument: null,
- pdfLoadingTask: null,
- printService: null,
- /** @type {PDFViewer} */
- pdfViewer: null,
- /** @type {PDFThumbnailViewer} */
- pdfThumbnailViewer: null,
- /** @type {PDFRenderingQueue} */
- pdfRenderingQueue: null,
- /** @type {PDFPresentationMode} */
- pdfPresentationMode: null,
- /** @type {PDFDocumentProperties} */
- pdfDocumentProperties: null,
- /** @type {PDFLinkService} */
- pdfLinkService: null,
- /** @type {PDFHistory} */
- pdfHistory: null,
- /** @type {PDFSidebar} */
- pdfSidebar: null,
- /** @type {PDFOutlineViewer} */
- pdfOutlineViewer: null,
- /** @type {PDFAttachmentViewer} */
- pdfAttachmentViewer: null,
- /** @type {ViewHistory} */
- store: null,
- /** @type {DownloadManager} */
- downloadManager: null,
- /** @type {EventBus} */
- eventBus: null,
- pageRotation: 0,
- isInitialViewSet: false,
- animationStartedPromise: null,
- preferenceSidebarViewOnLoad: SidebarView.NONE,
- preferencePdfBugEnabled: false,
- preferenceShowPreviousViewOnLoad: true,
- preferenceDefaultZoomValue: '',
- preferenceDisablePageLabels: false,
- isViewerEmbedded: window.parent !== window,
- url: '',
- baseUrl: '',
- externalServices: DefaultExernalServices,
- hasPageLabels: false,
- // called once when the document is loaded
- initialize: function pdfViewInitialize(appConfig) {
- configure(pdfjsLib.PDFJS);
- this.appConfig = appConfig;
- var eventBus = appConfig.eventBus || getGlobalEventBus();
- this.eventBus = eventBus;
- this.bindEvents();
- var pdfRenderingQueue = new PDFRenderingQueue();
- pdfRenderingQueue.onIdle = this.cleanup.bind(this);
- this.pdfRenderingQueue = pdfRenderingQueue;
- var pdfLinkService = new PDFLinkService({ eventBus: eventBus });
- this.pdfLinkService = pdfLinkService;
- var downloadManager = this.externalServices.createDownloadManager();
- this.downloadManager = downloadManager;
- var container = appConfig.mainContainer;
- var viewer = appConfig.viewerContainer;
- this.pdfViewer = new PDFViewer({
- container: container,
- viewer: viewer,
- eventBus: eventBus,
- renderingQueue: pdfRenderingQueue,
- linkService: pdfLinkService,
- downloadManager: downloadManager,
- enhanceTextSelection: false,
- renderInteractiveForms: false
- });
- pdfRenderingQueue.setViewer(this.pdfViewer);
- pdfLinkService.setViewer(this.pdfViewer);
- var thumbnailContainer = appConfig.sidebar.thumbnailView;
- this.pdfThumbnailViewer = new PDFThumbnailViewer({
- container: thumbnailContainer,
- renderingQueue: pdfRenderingQueue,
- linkService: pdfLinkService
- });
- pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
- Preferences.initialize();
- this.preferences = Preferences;
- this.pdfHistory = new PDFHistory({
- linkService: pdfLinkService,
- eventBus: this.eventBus
- });
- pdfLinkService.setHistory(this.pdfHistory);
- this.findController = new PDFFindController({ pdfViewer: this.pdfViewer });
- this.findController.onUpdateResultsCount = function (matchCount) {
- if (this.supportsIntegratedFind) {
- return;
- }
- this.findBar.updateResultsCount(matchCount);
- }.bind(this);
- this.findController.onUpdateState = function (state, previous, matchCount) {
- if (this.supportsIntegratedFind) {
- this.externalServices.updateFindControlState({
- result: state,
- findPrevious: previous
- });
- } else {
- this.findBar.updateUIState(state, previous, matchCount);
- }
- }.bind(this);
- this.pdfViewer.setFindController(this.findController);
- // FIXME better PDFFindBar constructor parameters
- var findBarConfig = Object.create(appConfig.findBar);
- findBarConfig.findController = this.findController;
- findBarConfig.eventBus = this.eventBus;
- this.findBar = new PDFFindBar(findBarConfig);
- this.overlayManager = OverlayManager;
- this.handTool = new HandTool({
- container: container,
- eventBus: this.eventBus
- });
- this.pdfDocumentProperties = new PDFDocumentProperties(appConfig.documentProperties);
- this.secondaryToolbar = new SecondaryToolbar(appConfig.secondaryToolbar, container, eventBus);
- if (this.supportsFullscreen) {
- this.pdfPresentationMode = new PDFPresentationMode({
- container: container,
- viewer: viewer,
- pdfViewer: this.pdfViewer,
- eventBus: this.eventBus,
- contextMenuItems: appConfig.fullscreen
- });
- }
- this.passwordPrompt = new PasswordPrompt(appConfig.passwordOverlay);
- this.pdfOutlineViewer = new PDFOutlineViewer({
- container: appConfig.sidebar.outlineView,
- eventBus: this.eventBus,
- linkService: pdfLinkService
- });
- this.pdfAttachmentViewer = new PDFAttachmentViewer({
- container: appConfig.sidebar.attachmentsView,
- eventBus: this.eventBus,
- downloadManager: downloadManager
- });
- // FIXME better PDFSidebar constructor parameters
- var sidebarConfig = Object.create(appConfig.sidebar);
- sidebarConfig.pdfViewer = this.pdfViewer;
- sidebarConfig.pdfThumbnailViewer = this.pdfThumbnailViewer;
- sidebarConfig.pdfOutlineViewer = this.pdfOutlineViewer;
- sidebarConfig.eventBus = this.eventBus;
- this.pdfSidebar = new PDFSidebar(sidebarConfig);
- this.pdfSidebar.onToggled = this.forceRendering.bind(this);
- var self = this;
- var PDFJS = pdfjsLib.PDFJS;
- var initializedPromise = Promise.all([
- Preferences.get('enableWebGL').then(function resolved(value) {
- PDFJS.disableWebGL = !value;
- }),
- Preferences.get('sidebarViewOnLoad').then(function resolved(value) {
- self.preferenceSidebarViewOnLoad = value;
- }),
- Preferences.get('pdfBugEnabled').then(function resolved(value) {
- self.preferencePdfBugEnabled = value;
- }),
- Preferences.get('showPreviousViewOnLoad').then(function resolved(value) {
- self.preferenceShowPreviousViewOnLoad = value;
- }),
- Preferences.get('defaultZoomValue').then(function resolved(value) {
- self.preferenceDefaultZoomValue = value;
- }),
- Preferences.get('enhanceTextSelection').then(function resolved(value) {
- // TODO: Move the initialization and fetching of `Preferences` to occur
- // before the various viewer components are initialized.
- //
- // This was attempted in: https://github.com/mozilla/pdf.js/pull/7586,
- // but it had to be backed out since it violated implicit assumptions
- // about some viewer components being synchronously available.
- //
- // NOTE: This hack works since the `enhanceTextSelection` option is not
- // needed until `PDFViewer.setDocument` has been called.
- self.pdfViewer.enhanceTextSelection = value;
- }),
- Preferences.get('disableTextLayer').then(function resolved(value) {
- if (PDFJS.disableTextLayer === true) {
- return;
- }
- PDFJS.disableTextLayer = value;
- }),
- Preferences.get('disableRange').then(function resolved(value) {
- if (PDFJS.disableRange === true) {
- return;
- }
- PDFJS.disableRange = value;
- }),
- Preferences.get('disableStream').then(function resolved(value) {
- if (PDFJS.disableStream === true) {
- return;
- }
- PDFJS.disableStream = value;
- }),
- Preferences.get('disableAutoFetch').then(function resolved(value) {
- PDFJS.disableAutoFetch = value;
- }),
- Preferences.get('disableFontFace').then(function resolved(value) {
- if (PDFJS.disableFontFace === true) {
- return;
- }
- PDFJS.disableFontFace = value;
- }),
- Preferences.get('useOnlyCssZoom').then(function resolved(value) {
- PDFJS.useOnlyCssZoom = value;
- }),
- Preferences.get('externalLinkTarget').then(function resolved(value) {
- if (PDFJS.isExternalLinkTargetSet()) {
- return;
- }
- PDFJS.externalLinkTarget = value;
- }),
- Preferences.get('renderInteractiveForms').then(function resolved(value) {
- // TODO: Like the `enhanceTextSelection` preference, move the
- // initialization and fetching of `Preferences` to occur
- // before the various viewer components are initialized.
- self.pdfViewer.renderInteractiveForms = value;
- }),
- Preferences.get('disablePageLabels').then(function resolved(value) {
- self.preferenceDisablePageLabels = value;
- })
- ]).catch(function (reason) {
- });
- return initializedPromise.then(function () {
- if (self.isViewerEmbedded && !PDFJS.isExternalLinkTargetSet()) {
- // Prevent external links from "replacing" the viewer,
- // when it's embedded in e.g. an iframe or an object.
- PDFJS.externalLinkTarget = PDFJS.LinkTarget.TOP;
- }
- self.initialized = true;
- });
- },
- run: function pdfViewRun(config) {
- this.initialize(config).then(webViewerInitialized);
- },
- zoomIn: function pdfViewZoomIn(ticks) {
- var newScale = this.pdfViewer.currentScale;
- do {
- newScale = (newScale * DEFAULT_SCALE_DELTA).toFixed(2);
- newScale = Math.ceil(newScale * 10) / 10;
- newScale = Math.min(MAX_SCALE, newScale);
- } while (--ticks > 0 && newScale < MAX_SCALE);
- this.pdfViewer.currentScaleValue = newScale;
- },
- zoomOut: function pdfViewZoomOut(ticks) {
- var newScale = this.pdfViewer.currentScale;
- do {
- newScale = (newScale / DEFAULT_SCALE_DELTA).toFixed(2);
- newScale = Math.floor(newScale * 10) / 10;
- newScale = Math.max(MIN_SCALE, newScale);
- } while (--ticks > 0 && newScale > MIN_SCALE);
- this.pdfViewer.currentScaleValue = newScale;
- },
- get pagesCount() {
- return this.pdfDocument ? this.pdfDocument.numPages : 0;
- },
- set page(val) {
- this.pdfViewer.currentPageNumber = val;
- },
- get page() {
- return this.pdfViewer.currentPageNumber;
- },
- get printing() {
- return !!this.printService;
- },
- get supportsPrinting() {
- return PDFPrintServiceFactory.instance.supportsPrinting;
- },
- get supportsFullscreen() {
- var support;
- support = document.fullscreenEnabled === true || document.mozFullScreenEnabled === true;
- if (support && pdfjsLib.PDFJS.disableFullscreen === true) {
- support = false;
- }
- return pdfjsLib.shadow(this, 'supportsFullscreen', support);
- },
- get supportsIntegratedFind() {
- return this.externalServices.supportsIntegratedFind;
- },
- get supportsDocumentFonts() {
- return this.externalServices.supportsDocumentFonts;
- },
- get supportsDocumentColors() {
- return this.externalServices.supportsDocumentColors;
- },
- get loadingBar() {
- var bar = new ProgressBar('#loadingBar', {});
- return pdfjsLib.shadow(this, 'loadingBar', bar);
- },
- get supportedMouseWheelZoomModifierKeys() {
- return this.externalServices.supportedMouseWheelZoomModifierKeys;
- },
- initPassiveLoading: function pdfViewInitPassiveLoading() {
- this.externalServices.initPassiveLoading({
- onOpenWithTransport: function (url, length, transport) {
- PDFViewerApplication.open(url, { range: transport });
- if (length) {
- PDFViewerApplication.pdfDocumentProperties.setFileSize(length);
- }
- },
- onOpenWithData: function (data) {
- PDFViewerApplication.open(data);
- },
- onOpenWithURL: function (url, length, originalURL) {
- var file = url, args = null;
- if (length !== undefined) {
- args = { length: length };
- }
- if (originalURL !== undefined) {
- file = {
- file: url,
- originalURL: originalURL
- };
- }
- PDFViewerApplication.open(file, args);
- },
- onError: function (e) {
- PDFViewerApplication.error(mozL10n.get('loading_error', null, 'An error occurred while loading the PDF.'), e);
- },
- onProgress: function (loaded, total) {
- PDFViewerApplication.progress(loaded / total);
- }
- });
- },
- setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
- this.url = url;
- this.baseUrl = url.split('#')[0];
- try {
- this.setTitle(decodeURIComponent(pdfjsLib.getFilenameFromUrl(url)) || url);
- } catch (e) {
- // decodeURIComponent may throw URIError,
- // fall back to using the unprocessed url in that case
- this.setTitle(url);
- }
- },
- setTitle: function pdfViewSetTitle(title) {
- if (this.isViewerEmbedded) {
- // Embedded PDF viewers should not be changing their parent page's title.
- return;
- }
- document.title = title;
- },
- /**
- * Closes opened PDF document.
- * @returns {Promise} - Returns the promise, which is resolved when all
- * destruction is completed.
- */
- close: function pdfViewClose() {
- var errorWrapper = this.appConfig.errorWrapper.container;
- errorWrapper.setAttribute('hidden', 'true');
- if (!this.pdfLoadingTask) {
- return Promise.resolve();
- }
- var promise = this.pdfLoadingTask.destroy();
- this.pdfLoadingTask = null;
- if (this.pdfDocument) {
- this.pdfDocument = null;
- this.pdfThumbnailViewer.setDocument(null);
- this.pdfViewer.setDocument(null);
- this.pdfLinkService.setDocument(null, null);
- }
- this.store = null;
- this.isInitialViewSet = false;
- this.hasPageLabels = false;
- this.pdfSidebar.reset();
- this.pdfOutlineViewer.reset();
- this.pdfAttachmentViewer.reset();
- this.findController.reset();
- this.findBar.reset();
- if (typeof PDFBug !== 'undefined') {
- PDFBug.cleanup();
- }
- return promise;
- },
- /**
- * Opens PDF document specified by URL or array with additional arguments.
- * @param {string|TypedArray|ArrayBuffer} file - PDF location or binary data.
- * @param {Object} args - (optional) Additional arguments for the getDocument
- * call, e.g. HTTP headers ('httpHeaders') or
- * alternative data transport ('range').
- * @returns {Promise} - Returns the promise, which is resolved when document
- * is opened.
- */
- open: function pdfViewOpen(file, args) {
- if (this.pdfLoadingTask) {
- // We need to destroy already opened document.
- return this.close().then(function () {
- // Reload the preferences if a document was previously opened.
- Preferences.reload();
- // ... and repeat the open() call.
- return this.open(file, args);
- }.bind(this));
- }
- var parameters = Object.create(null), scale;
- if (typeof file === 'string') {
- // URL
- this.setTitleUsingUrl(file);
- parameters.url = file;
- } else if (file && 'byteLength' in file) {
- // ArrayBuffer
- parameters.data = file;
- } else if (file.url && file.originalUrl) {
- this.setTitleUsingUrl(file.originalUrl);
- parameters.url = file.url;
- }
- parameters.docBaseUrl = this.baseUrl;
- if (args) {
- for (var prop in args) {
- parameters[prop] = args[prop];
- }
- if (args.scale) {
- scale = args.scale;
- }
- if (args.length) {
- this.pdfDocumentProperties.setFileSize(args.length);
- }
- }
- var self = this;
- self.downloadComplete = false;
- var loadingTask = pdfjsLib.getDocument(parameters);
- this.pdfLoadingTask = loadingTask;
- loadingTask.onPassword = function passwordNeeded(updateCallback, reason) {
- self.passwordPrompt.setUpdateCallback(updateCallback, reason);
- self.passwordPrompt.open();
- };
- loadingTask.onProgress = function getDocumentProgress(progressData) {
- self.progress(progressData.loaded / progressData.total);
- };
- // Listen for unsupported features to trigger the fallback UI.
- loadingTask.onUnsupportedFeature = this.fallback.bind(this);
- return loadingTask.promise.then(function getDocumentCallback(pdfDocument) {
- self.load(pdfDocument, scale);
- }, function getDocumentError(exception) {
- var message = exception && exception.message;
- var loadingErrorMessage = mozL10n.get('loading_error', null, 'An error occurred while loading the PDF.');
- if (exception instanceof pdfjsLib.InvalidPDFException) {
- // change error message also for other builds
- loadingErrorMessage = mozL10n.get('invalid_file_error', null, 'Invalid or corrupted PDF file.');
- } else if (exception instanceof pdfjsLib.MissingPDFException) {
- // special message for missing PDF's
- loadingErrorMessage = mozL10n.get('missing_file_error', null, 'Missing PDF file.');
- } else if (exception instanceof pdfjsLib.UnexpectedResponseException) {
- loadingErrorMessage = mozL10n.get('unexpected_response_error', null, 'Unexpected server response.');
- }
- var moreInfo = { message: message };
- self.error(loadingErrorMessage, moreInfo);
- throw new Error(loadingErrorMessage);
- });
- },
- download: function pdfViewDownload() {
- function downloadByUrl() {
- downloadManager.downloadUrl(url, filename);
- }
- var url = this.baseUrl;
- var filename = getPDFFileNameFromURL(url);
- var downloadManager = this.downloadManager;
- downloadManager.onerror = function (err) {
- // This error won't really be helpful because it's likely the
- // fallback won't work either (or is already open).
- PDFViewerApplication.error('PDF failed to download.');
- };
- if (!this.pdfDocument) {
- // the PDF is not ready yet
- downloadByUrl();
- return;
- }
- if (!this.downloadComplete) {
- // the PDF is still downloading
- downloadByUrl();
- return;
- }
- this.pdfDocument.getData().then(function getDataSuccess(data) {
- var blob = pdfjsLib.createBlob(data, 'application/pdf');
- downloadManager.download(blob, url, filename);
- }, downloadByUrl).then(null, downloadByUrl);
- },
- fallback: function pdfViewFallback(featureId) {
- // Only trigger the fallback once so we don't spam the user with messages
- // for one PDF.
- if (this.fellback) {
- return;
- }
- this.fellback = true;
- this.externalServices.fallback({
- featureId: featureId,
- url: this.baseUrl
- }, function response(download) {
- if (!download) {
- return;
- }
- PDFViewerApplication.download();
- });
- },
- /**
- * Show the error box.
- * @param {String} message A message that is human readable.
- * @param {Object} moreInfo (optional) Further information about the error
- * that is more technical. Should have a 'message'
- * and optionally a 'stack' property.
- */
- error: function pdfViewError(message, moreInfo) {
- var moreInfoText = mozL10n.get('error_version_info', {
- version: pdfjsLib.version || '?',
- build: pdfjsLib.build || '?'
- }, 'PDF.js v{{version}} (build: {{build}})') + '\n';
- if (moreInfo) {
- moreInfoText += mozL10n.get('error_message', { message: moreInfo.message }, 'Message: {{message}}');
- if (moreInfo.stack) {
- moreInfoText += '\n' + mozL10n.get('error_stack', { stack: moreInfo.stack }, 'Stack: {{stack}}');
- } else {
- if (moreInfo.filename) {
- moreInfoText += '\n' + mozL10n.get('error_file', { file: moreInfo.filename }, 'File: {{file}}');
- }
- if (moreInfo.lineNumber) {
- moreInfoText += '\n' + mozL10n.get('error_line', { line: moreInfo.lineNumber }, 'Line: {{line}}');
- }
- }
- }
- console.error(message + '\n' + moreInfoText);
- this.fallback();
- },
- progress: function pdfViewProgress(level) {
- var percent = Math.round(level * 100);
- // When we transition from full request to range requests, it's possible
- // that we discard some of the loaded data. This can cause the loading
- // bar to move backwards. So prevent this by only updating the bar if it
- // increases.
- if (percent > this.loadingBar.percent || isNaN(percent)) {
- this.loadingBar.percent = percent;
- // When disableAutoFetch is enabled, it's not uncommon for the entire file
- // to never be fetched (depends on e.g. the file structure). In this case
- // the loading bar will not be completely filled, nor will it be hidden.
- // To prevent displaying a partially filled loading bar permanently, we
- // hide it when no data has been loaded during a certain amount of time.
- if (pdfjsLib.PDFJS.disableAutoFetch && percent) {
- if (this.disableAutoFetchLoadingBarTimeout) {
- clearTimeout(this.disableAutoFetchLoadingBarTimeout);
- this.disableAutoFetchLoadingBarTimeout = null;
- }
- this.loadingBar.show();
- this.disableAutoFetchLoadingBarTimeout = setTimeout(function () {
- this.loadingBar.hide();
- this.disableAutoFetchLoadingBarTimeout = null;
- }.bind(this), DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT);
- }
- }
- },
- load: function pdfViewLoad(pdfDocument, scale) {
- var self = this;
- scale = scale || UNKNOWN_SCALE;
- this.pdfDocument = pdfDocument;
- this.pdfDocumentProperties.setDocumentAndUrl(pdfDocument, this.url);
- var downloadedPromise = pdfDocument.getDownloadInfo().then(function () {
- self.downloadComplete = true;
- self.loadingBar.hide();
- });
- this._updateUIToolbar({ resetNumPages: true });
- var id = this.documentFingerprint = pdfDocument.fingerprint;
- var store = this.store = new ViewHistory(id);
- var baseDocumentUrl;
- baseDocumentUrl = this.baseUrl;
- this.pdfLinkService.setDocument(pdfDocument, baseDocumentUrl);
- var pdfViewer = this.pdfViewer;
- pdfViewer.currentScale = scale;
- pdfViewer.setDocument(pdfDocument);
- var firstPagePromise = pdfViewer.firstPagePromise;
- var pagesPromise = pdfViewer.pagesPromise;
- var onePageRendered = pdfViewer.onePageRendered;
- this.pageRotation = 0;
- var pdfThumbnailViewer = this.pdfThumbnailViewer;
- pdfThumbnailViewer.setDocument(pdfDocument);
- firstPagePromise.then(function (pdfPage) {
- downloadedPromise.then(function () {
- self.eventBus.dispatch('documentload', { source: self });
- });
- self.loadingBar.setWidth(self.appConfig.viewerContainer);
- if (!pdfjsLib.PDFJS.disableHistory && !self.isViewerEmbedded) {
- // The browsing history is only enabled when the viewer is standalone,
- // i.e. not when it is embedded in a web page.
- if (!self.preferenceShowPreviousViewOnLoad) {
- self.pdfHistory.clearHistoryState();
- }
- self.pdfHistory.initialize(self.documentFingerprint);
- if (self.pdfHistory.initialDestination) {
- self.initialDestination = self.pdfHistory.initialDestination;
- } else if (self.pdfHistory.initialBookmark) {
- self.initialBookmark = self.pdfHistory.initialBookmark;
- }
- }
- var initialParams = {
- destination: self.initialDestination,
- bookmark: self.initialBookmark,
- hash: null
- };
- store.initializedPromise.then(function resolved() {
- var storedHash = null, sidebarView = null;
- if (self.preferenceShowPreviousViewOnLoad && store.get('exists', false)) {
- var pageNum = store.get('page', '1');
- var zoom = self.preferenceDefaultZoomValue || store.get('zoom', DEFAULT_SCALE_VALUE);
- var left = store.get('scrollLeft', '0');
- var top = store.get('scrollTop', '0');
- storedHash = 'page=' + pageNum + '&zoom=' + zoom + ',' + left + ',' + top;
- sidebarView = store.get('sidebarView', SidebarView.NONE);
- } else if (self.preferenceDefaultZoomValue) {
- storedHash = 'page=1&zoom=' + self.preferenceDefaultZoomValue;
- }
- self.setInitialView(storedHash, {
- scale: scale,
- sidebarView: sidebarView
- });
- initialParams.hash = storedHash;
- // Make all navigation keys work on document load,
- // unless the viewer is embedded in a web page.
- if (!self.isViewerEmbedded) {
- self.pdfViewer.focus();
- }
- }, function rejected(reason) {
- console.error(reason);
- self.setInitialView(null, { scale: scale });
- });
- // For documents with different page sizes,
- // ensure that the correct location becomes visible on load.
- pagesPromise.then(function resolved() {
- if (!initialParams.destination && !initialParams.bookmark && !initialParams.hash) {
- return;
- }
- if (self.hasEqualPageSizes) {
- return;
- }
- self.initialDestination = initialParams.destination;
- self.initialBookmark = initialParams.bookmark;
- self.pdfViewer.currentScaleValue = self.pdfViewer.currentScaleValue;
- self.setInitialView(initialParams.hash);
- });
- });
- pdfDocument.getPageLabels().then(function (labels) {
- if (!labels || self.preferenceDisablePageLabels) {
- return;
- }
- var i = 0, numLabels = labels.length;
- if (numLabels !== self.pagesCount) {
- console.error('The number of Page Labels does not match ' + 'the number of pages in the document.');
- return;
- }
- // Ignore page labels that correspond to standard page numbering.
- while (i < numLabels && labels[i] === (i + 1).toString()) {
- i++;
- }
- if (i === numLabels) {
- return;
- }
- pdfViewer.setPageLabels(labels);
- pdfThumbnailViewer.setPageLabels(labels);
- self.hasPageLabels = true;
- self._updateUIToolbar({ resetNumPages: true });
- });
- pagesPromise.then(function () {
- if (self.supportsPrinting) {
- pdfDocument.getJavaScript().then(function (javaScript) {
- if (javaScript.length) {
- console.warn('Warning: JavaScript is not supported');
- self.fallback(pdfjsLib.UNSUPPORTED_FEATURES.javaScript);
- }
- // Hack to support auto printing.
- var regex = /\bprint\s*\(/;
- for (var i = 0, ii = javaScript.length; i < ii; i++) {
- var js = javaScript[i];
- if (js && regex.test(js)) {
- setTimeout(function () {
- window.print();
- });
- return;
- }
- }
- });
- }
- });
- Promise.all([
- onePageRendered,
- this.animationStartedPromise
- ]).then(function () {
- pdfDocument.getOutline().then(function (outline) {
- self.pdfOutlineViewer.render({ outline: outline });
- });
- pdfDocument.getAttachments().then(function (attachments) {
- self.pdfAttachmentViewer.render({ attachments: attachments });
- });
- });
- pdfDocument.getMetadata().then(function (data) {
- var info = data.info, metadata = data.metadata;
- self.documentInfo = info;
- self.metadata = metadata;
- // Provides some basic debug information
- console.log('PDF ' + pdfDocument.fingerprint + ' [' + info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() + ' / ' + (info.Creator || '-').trim() + ']' + ' (PDF.js: ' + (pdfjsLib.version || '-') + (!pdfjsLib.PDFJS.disableWebGL ? ' [WebGL]' : '') + ')');
- var pdfTitle;
- if (metadata && metadata.has('dc:title')) {
- var title = metadata.get('dc:title');
- // Ghostscript sometimes return 'Untitled', sets the title to 'Untitled'
- if (title !== 'Untitled') {
- pdfTitle = title;
- }
- }
- if (!pdfTitle && info && info['Title']) {
- pdfTitle = info['Title'];
- }
- if (pdfTitle) {
- self.setTitle(pdfTitle + ' - ' + document.title);
- }
- if (info.IsAcroFormPresent) {
- console.warn('Warning: AcroForm/XFA is not supported');
- self.fallback(pdfjsLib.UNSUPPORTED_FEATURES.forms);
- }
- var versionId = String(info.PDFFormatVersion).slice(-1) | 0;
- var generatorId = 0;
- var KNOWN_GENERATORS = [
- 'acrobat distiller',
- 'acrobat pdfwriter',
- 'adobe livecycle',
- 'adobe pdf library',
- 'adobe photoshop',
- 'ghostscript',
- 'tcpdf',
- 'cairo',
- 'dvipdfm',
- 'dvips',
- 'pdftex',
- 'pdfkit',
- 'itext',
- 'prince',
- 'quarkxpress',
- 'mac os x',
- 'microsoft',
- 'openoffice',
- 'oracle',
- 'luradocument',
- 'pdf-xchange',
- 'antenna house',
- 'aspose.cells',
- 'fpdf'
- ];
- if (info.Producer) {
- KNOWN_GENERATORS.some(function (generator, s, i) {
- if (generator.indexOf(s) < 0) {
- return false;
- }
- generatorId = i + 1;
- return true;
- }.bind(null, info.Producer.toLowerCase()));
- }
- var formType = !info.IsAcroFormPresent ? null : info.IsXFAPresent ? 'xfa' : 'acroform';
- self.externalServices.reportTelemetry({
- type: 'documentInfo',
- version: versionId,
- generator: generatorId,
- formType: formType
- });
- });
- },
- setInitialView: function pdfViewSetInitialView(storedHash, options) {
- var scale = options && options.scale;
- var sidebarView = options && options.sidebarView;
- this.isInitialViewSet = true;
- this.pdfSidebar.setInitialView(this.preferenceSidebarViewOnLoad || sidebarView | 0);
- if (this.initialDestination) {
- this.pdfLinkService.navigateTo(this.initialDestination);
- this.initialDestination = null;
- } else if (this.initialBookmark) {
- this.pdfLinkService.setHash(this.initialBookmark);
- this.pdfHistory.push({ hash: this.initialBookmark }, true);
- this.initialBookmark = null;
- } else if (storedHash) {
- this.pdfLinkService.setHash(storedHash);
- } else if (scale) {
- this.pdfViewer.currentScaleValue = scale;
- this.page = 1;
- }
- if (!this.pdfViewer.currentScaleValue) {
- // Scale was not initialized: invalid bookmark or scale was not specified.
- // Setting the default one.
- this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
- }
- },
- cleanup: function pdfViewCleanup() {
- if (!this.pdfDocument) {
- return;
- }
- // run cleanup when document is loaded
- this.pdfViewer.cleanup();
- this.pdfThumbnailViewer.cleanup();
- this.pdfDocument.cleanup();
- },
- forceRendering: function pdfViewForceRendering() {
- this.pdfRenderingQueue.printing = this.printing;
- this.pdfRenderingQueue.isThumbnailViewEnabled = this.pdfSidebar.isThumbnailViewVisible;
- this.pdfRenderingQueue.renderHighestPriority();
- },
- beforePrint: function pdfViewSetupBeforePrint() {
- if (this.printService) {
- // There is no way to suppress beforePrint/afterPrint events,
- // but PDFPrintService may generate double events -- this will ignore
- // the second event that will be coming from native window.print().
- return;
- }
- if (!this.supportsPrinting) {
- var printMessage = mozL10n.get('printing_not_supported', null, 'Warning: Printing is not fully supported by this browser.');
- this.error(printMessage);
- return;
- }
- // The beforePrint is a sync method and we need to know layout before
- // returning from this method. Ensure that we can get sizes of the pages.
- if (!this.pdfViewer.pageViewsReady) {
- var notReadyMessage = mozL10n.get('printing_not_ready', null, 'Warning: The PDF is not fully loaded for printing.');
- window.alert(notReadyMessage);
- return;
- }
- var pagesOverview = this.pdfViewer.getPagesOverview();
- var printContainer = this.appConfig.printContainer;
- var printService = PDFPrintServiceFactory.instance.createPrintService(this.pdfDocument, pagesOverview, printContainer);
- this.printService = printService;
- this.forceRendering();
- printService.layout();
- this.externalServices.reportTelemetry({ type: 'print' });
- },
- // Whether all pages of the PDF have the same width and height.
- get hasEqualPageSizes() {
- var firstPage = this.pdfViewer.getPageView(0);
- for (var i = 1, ii = this.pagesCount; i < ii; ++i) {
- var pageView = this.pdfViewer.getPageView(i);
- if (pageView.width !== firstPage.width || pageView.height !== firstPage.height) {
- return false;
- }
- }
- return true;
- },
- afterPrint: function pdfViewSetupAfterPrint() {
- if (this.printService) {
- this.printService.destroy();
- this.printService = null;
- }
- this.forceRendering();
- },
- rotatePages: function pdfViewRotatePages(delta) {
- var pageNumber = this.page;
- this.pageRotation = (this.pageRotation + 360 + delta) % 360;
- this.pdfViewer.pagesRotation = this.pageRotation;
- this.pdfThumbnailViewer.pagesRotation = this.pageRotation;
- this.forceRendering();
- this.pdfViewer.currentPageNumber = pageNumber;
- },
- requestPresentationMode: function pdfViewRequestPresentationMode() {
- if (!this.pdfPresentationMode) {
- return;
- }
- this.pdfPresentationMode.request();
- },
- /**
- * @typedef UpdateUIToolbarParameters
- * @property {number} pageNumber
- * @property {string} pageLabel
- * @property {string} scaleValue
- * @property {number} scale
- * @property {boolean} resetNumPages
- */
- /**
- * @param {Object} UpdateUIToolbarParameters
- * @private
- */
- _updateUIToolbar: function (params) {
- function selectScaleOption(value, scale) {
- var options = toolbarConfig.scaleSelect.options;
- var predefinedValueFound = false;
- for (var i = 0, ii = options.length; i < ii; i++) {
- var option = options[i];
- if (option.value !== value) {
- option.selected = false;
- continue;
- }
- option.selected = true;
- predefinedValueFound = true;
- }
- if (!predefinedValueFound) {
- var customScale = Math.round(scale * 10000) / 100;
- toolbarConfig.customScaleOption.textContent = mozL10n.get('page_scale_percent', { scale: customScale }, '{{scale}}%');
- toolbarConfig.customScaleOption.selected = true;
- }
- }
- var pageNumber = params.pageNumber || this.pdfViewer.currentPageNumber;
- var scaleValue = (params.scaleValue || params.scale || this.pdfViewer.currentScaleValue || DEFAULT_SCALE_VALUE).toString();
- var scale = params.scale || this.pdfViewer.currentScale;
- var resetNumPages = params.resetNumPages || false;
- var toolbarConfig = this.appConfig.toolbar;
- var pagesCount = this.pagesCount;
- if (resetNumPages) {
- if (this.hasPageLabels) {
- toolbarConfig.pageNumber.type = 'text';
- } else {
- toolbarConfig.pageNumber.type = 'number';
- toolbarConfig.numPages.textContent = mozL10n.get('of_pages', { pagesCount: pagesCount }, 'of {{pagesCount}}');
- }
- toolbarConfig.pageNumber.max = pagesCount;
- }
- if (this.hasPageLabels) {
- toolbarConfig.pageNumber.value = params.pageLabel || this.pdfViewer.currentPageLabel;
- toolbarConfig.numPages.textContent = mozL10n.get('page_of_pages', {
- pageNumber: pageNumber,
- pagesCount: pagesCount
- }, '({{pageNumber}} of {{pagesCount}})');
- } else {
- toolbarConfig.pageNumber.value = pageNumber;
- }
- toolbarConfig.previous.disabled = pageNumber <= 1;
- toolbarConfig.next.disabled = pageNumber >= pagesCount;
- toolbarConfig.firstPage.disabled = pageNumber <= 1;
- toolbarConfig.lastPage.disabled = pageNumber >= pagesCount;
- toolbarConfig.zoomOut.disabled = scale <= MIN_SCALE;
- toolbarConfig.zoomIn.disabled = scale >= MAX_SCALE;
- selectScaleOption(scaleValue, scale);
- },
- bindEvents: function pdfViewBindEvents() {
- var eventBus = this.eventBus;
- eventBus.on('resize', webViewerResize);
- eventBus.on('localized', webViewerLocalized);
- eventBus.on('hashchange', webViewerHashchange);
- eventBus.on('beforeprint', this.beforePrint.bind(this));
- eventBus.on('afterprint', this.afterPrint.bind(this));
- eventBus.on('pagerendered', webViewerPageRendered);
- eventBus.on('textlayerrendered', webViewerTextLayerRendered);
- eventBus.on('updateviewarea', webViewerUpdateViewarea);
- eventBus.on('pagechanging', webViewerPageChanging);
- eventBus.on('scalechanging', webViewerScaleChanging);
- eventBus.on('sidebarviewchanged', webViewerSidebarViewChanged);
- eventBus.on('pagemode', webViewerPageMode);
- eventBus.on('namedaction', webViewerNamedAction);
- eventBus.on('presentationmodechanged', webViewerPresentationModeChanged);
- eventBus.on('presentationmode', webViewerPresentationMode);
- eventBus.on('openfile', webViewerOpenFile);
- eventBus.on('print', webViewerPrint);
- eventBus.on('download', webViewerDownload);
- eventBus.on('firstpage', webViewerFirstPage);
- eventBus.on('lastpage', webViewerLastPage);
- eventBus.on('rotatecw', webViewerRotateCw);
- eventBus.on('rotateccw', webViewerRotateCcw);
- eventBus.on('documentproperties', webViewerDocumentProperties);
- eventBus.on('find', webViewerFind);
- eventBus.on('findfromurlhash', webViewerFindFromUrlHash);
- }
- };
- var validateFileURL;
- function loadAndEnablePDFBug(enabledTabs) {
- return new Promise(function (resolve, reject) {
- var appConfig = PDFViewerApplication.appConfig;
- var script = document.createElement('script');
- script.src = appConfig.debuggerScriptPath;
- script.onload = function () {
- PDFBug.enable(enabledTabs);
- PDFBug.init(pdfjsLib, appConfig.mainContainer);
- resolve();
- };
- script.onerror = function () {
- reject(new Error('Cannot load debugger at ' + script.src));
- };
- (document.getElementsByTagName('head')[0] || document.body).appendChild(script);
- });
- }
- function webViewerInitialized() {
- var file;
- file = window.location.href.split('#')[0];
- var waitForBeforeOpening = [];
- var appConfig = PDFViewerApplication.appConfig;
- appConfig.toolbar.openFile.setAttribute('hidden', 'true');
- appConfig.secondaryToolbar.openFileButton.setAttribute('hidden', 'true');
- var PDFJS = pdfjsLib.PDFJS;
- if (PDFViewerApplication.preferencePdfBugEnabled) {
- // Special debugging flags in the hash section of the URL.
- var hash = document.location.hash.substring(1);
- var hashParams = parseQueryString(hash);
- if ('disableworker' in hashParams) {
- PDFJS.disableWorker = hashParams['disableworker'] === 'true';
- }
- if ('disablerange' in hashParams) {
- PDFJS.disableRange = hashParams['disablerange'] === 'true';
- }
- if ('disablestream' in hashParams) {
- PDFJS.disableStream = hashParams['disablestream'] === 'true';
- }
- if ('disableautofetch' in hashParams) {
- PDFJS.disableAutoFetch = hashParams['disableautofetch'] === 'true';
- }
- if ('disablefontface' in hashParams) {
- PDFJS.disableFontFace = hashParams['disablefontface'] === 'true';
- }
- if ('disablehistory' in hashParams) {
- PDFJS.disableHistory = hashParams['disablehistory'] === 'true';
- }
- if ('webgl' in hashParams) {
- PDFJS.disableWebGL = hashParams['webgl'] !== 'true';
- }
- if ('useonlycsszoom' in hashParams) {
- PDFJS.useOnlyCssZoom = hashParams['useonlycsszoom'] === 'true';
- }
- if ('verbosity' in hashParams) {
- PDFJS.verbosity = hashParams['verbosity'] | 0;
- }
- if ('ignorecurrentpositiononzoom' in hashParams) {
- PDFJS.ignoreCurrentPositionOnZoom = hashParams['ignorecurrentpositiononzoom'] === 'true';
- }
- if ('textlayer' in hashParams) {
- switch (hashParams['textlayer']) {
- case 'off':
- PDFJS.disableTextLayer = true;
- break;
- case 'visible':
- case 'shadow':
- case 'hover':
- var viewer = appConfig.viewerContainer;
- viewer.classList.add('textLayer-' + hashParams['textlayer']);
- break;
- }
- }
- if ('pdfbug' in hashParams) {
- PDFJS.pdfBug = true;
- var pdfBug = hashParams['pdfbug'];
- var enabled = pdfBug.split(',');
- waitForBeforeOpening.push(loadAndEnablePDFBug(enabled));
- }
- }
- if (!PDFViewerApplication.supportsDocumentFonts) {
- PDFJS.disableFontFace = true;
- console.warn(mozL10n.get('web_fonts_disabled', null, 'Web fonts are disabled: unable to use embedded PDF fonts.'));
- }
- if (!PDFViewerApplication.supportsPrinting) {
- appConfig.toolbar.print.classList.add('hidden');
- appConfig.secondaryToolbar.printButton.classList.add('hidden');
- }
- if (!PDFViewerApplication.supportsFullscreen) {
- appConfig.toolbar.presentationModeButton.classList.add('hidden');
- appConfig.secondaryToolbar.presentationModeButton.classList.add('hidden');
- }
- if (PDFViewerApplication.supportsIntegratedFind) {
- appConfig.toolbar.viewFind.classList.add('hidden');
- }
- // Suppress context menus for some controls
- appConfig.toolbar.scaleSelect.oncontextmenu = noContextMenuHandler;
- appConfig.sidebar.mainContainer.addEventListener('transitionend', function (e) {
- if (e.target === /* mainContainer */
- this) {
- PDFViewerApplication.eventBus.dispatch('resize');
- }
- }, true);
- appConfig.sidebar.toggleButton.addEventListener('click', function () {
- PDFViewerApplication.pdfSidebar.toggle();
- });
- appConfig.toolbar.previous.addEventListener('click', function () {
- PDFViewerApplication.page--;
- });
- appConfig.toolbar.next.addEventListener('click', function () {
- PDFViewerApplication.page++;
- });
- appConfig.toolbar.zoomIn.addEventListener('click', function () {
- PDFViewerApplication.zoomIn();
- });
- appConfig.toolbar.zoomOut.addEventListener('click', function () {
- PDFViewerApplication.zoomOut();
- });
- appConfig.toolbar.pageNumber.addEventListener('click', function () {
- this.select();
- });
- appConfig.toolbar.pageNumber.addEventListener('change', function () {
- var pdfViewer = PDFViewerApplication.pdfViewer;
- pdfViewer.currentPageLabel = this.value;
- // Ensure that the page number input displays the correct value, even if the
- // value entered by the user was invalid (e.g. a floating point number).
- if (this.value !== pdfViewer.currentPageNumber.toString() && this.value !== pdfViewer.currentPageLabel) {
- PDFViewerApplication._updateUIToolbar({});
- }
- });
- appConfig.toolbar.scaleSelect.addEventListener('change', function () {
- if (this.value === 'custom') {
- return;
- }
- PDFViewerApplication.pdfViewer.currentScaleValue = this.value;
- });
- appConfig.toolbar.presentationModeButton.addEventListener('click', function (e) {
- PDFViewerApplication.eventBus.dispatch('presentationmode');
- });
- appConfig.toolbar.openFile.addEventListener('click', function (e) {
- PDFViewerApplication.eventBus.dispatch('openfile');
- });
- appConfig.toolbar.print.addEventListener('click', function (e) {
- PDFViewerApplication.eventBus.dispatch('print');
- });
- appConfig.toolbar.download.addEventListener('click', function (e) {
- PDFViewerApplication.eventBus.dispatch('download');
- });
- Promise.all(waitForBeforeOpening).then(function () {
- webViewerOpenFileViaURL(file);
- }).catch(function (reason) {
- PDFViewerApplication.error(mozL10n.get('loading_error', null, 'An error occurred while opening.'), reason);
- });
- }
- var webViewerOpenFileViaURL;
- webViewerOpenFileViaURL = function webViewerOpenFileViaURL(file) {
- PDFViewerApplication.setTitleUsingUrl(file);
- PDFViewerApplication.initPassiveLoading();
- };
- function webViewerPageRendered(e) {
- var pageNumber = e.pageNumber;
- var pageIndex = pageNumber - 1;
- var pageView = PDFViewerApplication.pdfViewer.getPageView(pageIndex);
- // If the page is still visible when it has finished rendering,
- // ensure that the page number input loading indicator is hidden.
- if (pageNumber === PDFViewerApplication.page) {
- var pageNumberInput = PDFViewerApplication.appConfig.toolbar.pageNumber;
- pageNumberInput.classList.remove(PAGE_NUMBER_LOADING_INDICATOR);
- }
- // Prevent errors in the edge-case where the PDF document is removed *before*
- // the 'pagerendered' event handler is invoked.
- if (!pageView) {
- return;
- }
- // Use the rendered page to set the corresponding thumbnail image.
- if (PDFViewerApplication.pdfSidebar.isThumbnailViewVisible) {
- var thumbnailView = PDFViewerApplication.pdfThumbnailViewer.getThumbnail(pageIndex);
- thumbnailView.setImage(pageView);
- }
- if (pdfjsLib.PDFJS.pdfBug && Stats.enabled && pageView.stats) {
- Stats.add(pageNumber, pageView.stats);
- }
- if (pageView.error) {
- PDFViewerApplication.error(mozL10n.get('rendering_error', null, 'An error occurred while rendering the page.'), pageView.error);
- }
- PDFViewerApplication.externalServices.reportTelemetry({ type: 'pageInfo' });
- // It is a good time to report stream and font types.
- PDFViewerApplication.pdfDocument.getStats().then(function (stats) {
- PDFViewerApplication.externalServices.reportTelemetry({
- type: 'documentStats',
- stats: stats
- });
- });
- }
- function webViewerTextLayerRendered(e) {
- if (e.numTextDivs > 0 && !PDFViewerApplication.supportsDocumentColors) {
- console.error(mozL10n.get('document_colors_not_allowed', null, 'PDF documents are not allowed to use their own colors: ' + '\'Allow pages to choose their own colors\' ' + 'is deactivated in the browser.'));
- PDFViewerApplication.fallback();
- }
- }
- function webViewerPageMode(e) {
- if (!PDFViewerApplication.initialized) {
- return;
- }
- // Handle the 'pagemode' hash parameter, see also `PDFLinkService_setHash`.
- var mode = e.mode, view;
- switch (mode) {
- case 'thumbs':
- view = SidebarView.THUMBS;
- break;
- case 'bookmarks':
- case 'outline':
- view = SidebarView.OUTLINE;
- break;
- case 'attachments':
- view = SidebarView.ATTACHMENTS;
- break;
- case 'none':
- view = SidebarView.NONE;
- break;
- default:
- console.error('Invalid "pagemode" hash parameter: ' + mode);
- return;
- }
- PDFViewerApplication.pdfSidebar.switchView(view, /* forceOpen = */
- true);
- }
- function webViewerNamedAction(e) {
- if (!PDFViewerApplication.initialized) {
- return;
- }
- // Processing couple of named actions that might be useful.
- // See also PDFLinkService.executeNamedAction
- var action = e.action;
- switch (action) {
- case 'GoToPage':
- PDFViewerApplication.appConfig.toolbar.pageNumber.select();
- break;
- case 'Find':
- if (!PDFViewerApplication.supportsIntegratedFind) {
- PDFViewerApplication.findBar.toggle();
- }
- break;
- }
- }
- function webViewerPresentationModeChanged(e) {
- var active = e.active;
- var switchInProgress = e.switchInProgress;
- PDFViewerApplication.pdfViewer.presentationModeState = switchInProgress ? PresentationModeState.CHANGING : active ? PresentationModeState.FULLSCREEN : PresentationModeState.NORMAL;
- }
- function webViewerSidebarViewChanged(e) {
- if (!PDFViewerApplication.initialized) {
- return;
- }
- PDFViewerApplication.pdfRenderingQueue.isThumbnailViewEnabled = PDFViewerApplication.pdfSidebar.isThumbnailViewVisible;
- var store = PDFViewerApplication.store;
- if (!store || !PDFViewerApplication.isInitialViewSet) {
- // Only update the storage when the document has been loaded *and* rendered.
- return;
- }
- store.initializedPromise.then(function () {
- store.set('sidebarView', e.view).catch(function () {
- });
- });
- }
- function webViewerUpdateViewarea(e) {
- if (!PDFViewerApplication.initialized) {
- return;
- }
- var location = e.location, store = PDFViewerApplication.store;
- if (store) {
- store.initializedPromise.then(function () {
- store.setMultiple({
- 'exists': true,
- 'page': location.pageNumber,
- 'zoom': location.scale,
- 'scrollLeft': location.left,
- 'scrollTop': location.top
- }).catch(function () {
- });
- });
- }
- var href = PDFViewerApplication.pdfLinkService.getAnchorUrl(location.pdfOpenParams);
- PDFViewerApplication.appConfig.toolbar.viewBookmark.href = href;
- PDFViewerApplication.appConfig.secondaryToolbar.viewBookmarkButton.href = href;
- // Update the current bookmark in the browsing history.
- PDFViewerApplication.pdfHistory.updateCurrentBookmark(location.pdfOpenParams, location.pageNumber);
- // Show/hide the loading indicator in the page number input element.
- var pageNumberInput = PDFViewerApplication.appConfig.toolbar.pageNumber;
- var currentPage = PDFViewerApplication.pdfViewer.getPageView(PDFViewerApplication.page - 1);
- if (currentPage.renderingState === RenderingStates.FINISHED) {
- pageNumberInput.classList.remove(PAGE_NUMBER_LOADING_INDICATOR);
- } else {
- pageNumberInput.classList.add(PAGE_NUMBER_LOADING_INDICATOR);
- }
- }
- window.addEventListener('resize', function webViewerResize(evt) {
- if (!PDFViewerApplication.eventBus) {
- return;
- }
- PDFViewerApplication.eventBus.dispatch('resize');
- });
- function webViewerResize() {
- if (PDFViewerApplication.initialized) {
- var currentScaleValue = PDFViewerApplication.pdfViewer.currentScaleValue;
- if (currentScaleValue === 'auto' || currentScaleValue === 'page-fit' || currentScaleValue === 'page-width') {
- // Note: the scale is constant for 'page-actual'.
- PDFViewerApplication.pdfViewer.currentScaleValue = currentScaleValue;
- } else if (!currentScaleValue) {
- // Normally this shouldn't happen, but if the scale wasn't initialized
- // we set it to the default value in order to prevent any issues.
- // (E.g. the document being rendered with the wrong scale on load.)
- PDFViewerApplication.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
- }
- PDFViewerApplication.pdfViewer.update();
- }
- }
- window.addEventListener('hashchange', function webViewerHashchange(evt) {
- var hash = document.location.hash.substring(1);
- PDFViewerApplication.eventBus.dispatch('hashchange', { hash: hash });
- });
- function webViewerHashchange(e) {
- if (PDFViewerApplication.pdfHistory.isHashChangeUnlocked) {
- var hash = e.hash;
- if (!hash) {
- return;
- }
- if (!PDFViewerApplication.isInitialViewSet) {
- PDFViewerApplication.initialBookmark = hash;
- } else {
- PDFViewerApplication.pdfLinkService.setHash(hash);
- }
- }
- }
- var webViewerFileInputChange;
- window.addEventListener('localized', function localized(evt) {
- PDFViewerApplication.eventBus.dispatch('localized');
- });
- function webViewerLocalized() {
- document.getElementsByTagName('html')[0].dir = mozL10n.getDirection();
- PDFViewerApplication.animationStartedPromise.then(function () {
- // Adjust the width of the zoom box to fit the content.
- // Note: If the window is narrow enough that the zoom box is not visible,
- // we temporarily show it to be able to adjust its width.
- var container = PDFViewerApplication.appConfig.toolbar.scaleSelectContainer;
- if (container.clientWidth === 0) {
- container.setAttribute('style', 'display: inherit;');
- }
- if (container.clientWidth > 0) {
- var select = PDFViewerApplication.appConfig.toolbar.scaleSelect;
- select.setAttribute('style', 'min-width: inherit;');
- var width = select.clientWidth + SCALE_SELECT_CONTAINER_PADDING;
- select.setAttribute('style', 'min-width: ' + (width + SCALE_SELECT_PADDING) + 'px;');
- container.setAttribute('style', 'min-width: ' + width + 'px; ' + 'max-width: ' + width + 'px;');
- }
- });
- }
- function webViewerPresentationMode() {
- PDFViewerApplication.requestPresentationMode();
- }
- function webViewerOpenFile() {
- var openFileInputName = PDFViewerApplication.appConfig.openFileInputName;
- document.getElementById(openFileInputName).click();
- }
- function webViewerPrint() {
- window.print();
- }
- function webViewerDownload() {
- PDFViewerApplication.download();
- }
- function webViewerFirstPage() {
- if (PDFViewerApplication.pdfDocument) {
- PDFViewerApplication.page = 1;
- }
- }
- function webViewerLastPage() {
- if (PDFViewerApplication.pdfDocument) {
- PDFViewerApplication.page = PDFViewerApplication.pagesCount;
- }
- }
- function webViewerRotateCw() {
- PDFViewerApplication.rotatePages(90);
- }
- function webViewerRotateCcw() {
- PDFViewerApplication.rotatePages(-90);
- }
- function webViewerDocumentProperties() {
- PDFViewerApplication.pdfDocumentProperties.open();
- }
- function webViewerFind(e) {
- PDFViewerApplication.findController.executeCommand('find' + e.type, {
- query: e.query,
- phraseSearch: e.phraseSearch,
- caseSensitive: e.caseSensitive,
- highlightAll: e.highlightAll,
- findPrevious: e.findPrevious
- });
- }
- function webViewerFindFromUrlHash(e) {
- PDFViewerApplication.findController.executeCommand('find', {
- query: e.query,
- phraseSearch: e.phraseSearch,
- caseSensitive: false,
- highlightAll: true,
- findPrevious: false
- });
- }
- function webViewerScaleChanging(e) {
- PDFViewerApplication._updateUIToolbar({
- scaleValue: e.presetValue,
- scale: e.scale
- });
- if (!PDFViewerApplication.initialized) {
- return;
- }
- PDFViewerApplication.pdfViewer.update();
- }
- function webViewerPageChanging(e) {
- var page = e.pageNumber;
- PDFViewerApplication._updateUIToolbar({
- pageNumber: page,
- pageLabel: e.pageLabel
- });
- if (PDFViewerApplication.pdfSidebar.isThumbnailViewVisible) {
- PDFViewerApplication.pdfThumbnailViewer.scrollThumbnailIntoView(page);
- }
- // we need to update stats
- if (pdfjsLib.PDFJS.pdfBug && Stats.enabled) {
- var pageView = PDFViewerApplication.pdfViewer.getPageView(page - 1);
- if (pageView.stats) {
- Stats.add(page, pageView.stats);
- }
- }
- }
- var zoomDisabled = false, zoomDisabledTimeout;
- function handleMouseWheel(evt) {
- var pdfViewer = PDFViewerApplication.pdfViewer;
- if (!pdfViewer || pdfViewer.isInPresentationMode) {
- return;
- }
- if (evt.ctrlKey || evt.metaKey) {
- var support = PDFViewerApplication.supportedMouseWheelZoomModifierKeys;
- if (evt.ctrlKey && !support.ctrlKey || evt.metaKey && !support.metaKey) {
- return;
- }
- // Only zoom the pages, not the entire viewer.
- evt.preventDefault();
- // NOTE: this check must be placed *after* preventDefault.
- if (zoomDisabled) {
- return;
- }
- var previousScale = pdfViewer.currentScale;
- var delta = normalizeWheelEventDelta(evt);
- var MOUSE_WHEEL_DELTA_PER_PAGE_SCALE = 3.0;
- var ticks = delta * MOUSE_WHEEL_DELTA_PER_PAGE_SCALE;
- if (ticks < 0) {
- PDFViewerApplication.zoomOut(-ticks);
- } else {
- PDFViewerApplication.zoomIn(ticks);
- }
- var currentScale = pdfViewer.currentScale;
- if (previousScale !== currentScale) {
- // After scaling the page via zoomIn/zoomOut, the position of the upper-
- // left corner is restored. When the mouse wheel is used, the position
- // under the cursor should be restored instead.
- var scaleCorrectionFactor = currentScale / previousScale - 1;
- var rect = pdfViewer.container.getBoundingClientRect();
- var dx = evt.clientX - rect.left;
- var dy = evt.clientY - rect.top;
- pdfViewer.container.scrollLeft += dx * scaleCorrectionFactor;
- pdfViewer.container.scrollTop += dy * scaleCorrectionFactor;
- }
- } else {
- zoomDisabled = true;
- clearTimeout(zoomDisabledTimeout);
- zoomDisabledTimeout = setTimeout(function () {
- zoomDisabled = false;
- }, 1000);
- }
- }
- window.addEventListener('wheel', handleMouseWheel);
- window.addEventListener('click', function click(evt) {
- if (!PDFViewerApplication.secondaryToolbar.isOpen) {
- return;
- }
- var appConfig = PDFViewerApplication.appConfig;
- if (PDFViewerApplication.pdfViewer.containsElement(evt.target) || appConfig.toolbar.container.contains(evt.target) && evt.target !== appConfig.secondaryToolbar.toggleButton) {
- PDFViewerApplication.secondaryToolbar.close();
- }
- }, true);
- window.addEventListener('keydown', function keydown(evt) {
- if (OverlayManager.active) {
- return;
- }
- var handled = false;
- var cmd = (evt.ctrlKey ? 1 : 0) | (evt.altKey ? 2 : 0) | (evt.shiftKey ? 4 : 0) | (evt.metaKey ? 8 : 0);
- var pdfViewer = PDFViewerApplication.pdfViewer;
- var isViewerInPresentationMode = pdfViewer && pdfViewer.isInPresentationMode;
- // First, handle the key bindings that are independent whether an input
- // control is selected or not.
- if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) {
- // either CTRL or META key with optional SHIFT.
- switch (evt.keyCode) {
- case 70:
- // f
- if (!PDFViewerApplication.supportsIntegratedFind) {
- PDFViewerApplication.findBar.open();
- handled = true;
- }
- break;
- case 71:
- // g
- if (!PDFViewerApplication.supportsIntegratedFind) {
- var findState = PDFViewerApplication.findController.state;
- if (findState) {
- PDFViewerApplication.findController.executeCommand('findagain', {
- query: findState.query,
- phraseSearch: findState.phraseSearch,
- caseSensitive: findState.caseSensitive,
- highlightAll: findState.highlightAll,
- findPrevious: cmd === 5 || cmd === 12
- });
- }
- handled = true;
- }
- break;
- case 61:
- // FF/Mac '='
- case 107:
- // FF '+' and '='
- case 187:
- // Chrome '+'
- case 171:
- // FF with German keyboard
- if (!isViewerInPresentationMode) {
- PDFViewerApplication.zoomIn();
- }
- handled = true;
- break;
- case 173:
- // FF/Mac '-'
- case 109:
- // FF '-'
- case 189:
- // Chrome '-'
- if (!isViewerInPresentationMode) {
- PDFViewerApplication.zoomOut();
- }
- handled = true;
- break;
- case 48:
- // '0'
- case 96:
- // '0' on Numpad of Swedish keyboard
- if (!isViewerInPresentationMode) {
- // keeping it unhandled (to restore page zoom to 100%)
- setTimeout(function () {
- // ... and resetting the scale after browser adjusts its scale
- pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
- });
- handled = false;
- }
- break;
- }
- }
- // CTRL+ALT or Option+Command
- if (cmd === 3 || cmd === 10) {
- switch (evt.keyCode) {
- case 80:
- // p
- PDFViewerApplication.requestPresentationMode();
- handled = true;
- break;
- case 71:
- // g
- // focuses input#pageNumber field
- PDFViewerApplication.appConfig.toolbar.pageNumber.select();
- handled = true;
- break;
- }
- }
- if (handled) {
- evt.preventDefault();
- return;
- }
- // Some shortcuts should not get handled if a control/input element
- // is selected.
- var curElement = document.activeElement || document.querySelector(':focus');
- var curElementTagName = curElement && curElement.tagName.toUpperCase();
- if (curElementTagName === 'INPUT' || curElementTagName === 'TEXTAREA' || curElementTagName === 'SELECT') {
- // Make sure that the secondary toolbar is closed when Escape is pressed.
- if (evt.keyCode !== 27) {
- // 'Esc'
- return;
- }
- }
- var ensureViewerFocused = false;
- if (cmd === 0) {
- // no control key pressed at all.
- switch (evt.keyCode) {
- case 38:
- // up arrow
- case 33:
- // pg up
- case 8:
- // backspace
- if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== 'page-fit') {
- break;
- }
- /* in presentation mode */
- case 37:
- // left arrow
- // horizontal scrolling using arrow keys
- if (pdfViewer.isHorizontalScrollbarEnabled) {
- break;
- }
- case 75:
- // 'k'
- case 80:
- // 'p'
- if (PDFViewerApplication.page > 1) {
- PDFViewerApplication.page--;
- }
- handled = true;
- break;
- case 27:
- // esc key
- if (PDFViewerApplication.secondaryToolbar.isOpen) {
- PDFViewerApplication.secondaryToolbar.close();
- handled = true;
- }
- if (!PDFViewerApplication.supportsIntegratedFind && PDFViewerApplication.findBar.opened) {
- PDFViewerApplication.findBar.close();
- handled = true;
- }
- break;
- case 40:
- // down arrow
- case 34:
- // pg down
- case 32:
- // spacebar
- if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== 'page-fit') {
- break;
- }
- case 39:
- // right arrow
- // horizontal scrolling using arrow keys
- if (pdfViewer.isHorizontalScrollbarEnabled) {
- break;
- }
- case 74:
- // 'j'
- case 78:
- // 'n'
- if (PDFViewerApplication.page < PDFViewerApplication.pagesCount) {
- PDFViewerApplication.page++;
- }
- handled = true;
- break;
- case 36:
- // home
- if (isViewerInPresentationMode || PDFViewerApplication.page > 1) {
- PDFViewerApplication.page = 1;
- handled = true;
- ensureViewerFocused = true;
- }
- break;
- case 35:
- // end
- if (isViewerInPresentationMode || PDFViewerApplication.page < PDFViewerApplication.pagesCount) {
- PDFViewerApplication.page = PDFViewerApplication.pagesCount;
- handled = true;
- ensureViewerFocused = true;
- }
- break;
- case 72:
- // 'h'
- if (!isViewerInPresentationMode) {
- PDFViewerApplication.handTool.toggle();
- }
- break;
- case 82:
- // 'r'
- PDFViewerApplication.rotatePages(90);
- break;
- }
- }
- if (cmd === 4) {
- // shift-key
- switch (evt.keyCode) {
- case 32:
- // spacebar
- if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== 'page-fit') {
- break;
- }
- if (PDFViewerApplication.page > 1) {
- PDFViewerApplication.page--;
- }
- handled = true;
- break;
- case 82:
- // 'r'
- PDFViewerApplication.rotatePages(-90);
- break;
- }
- }
- if (!handled && !isViewerInPresentationMode) {
- // 33=Page Up 34=Page Down 35=End 36=Home
- // 37=Left 38=Up 39=Right 40=Down
- // 32=Spacebar
- if (evt.keyCode >= 33 && evt.keyCode <= 40 || evt.keyCode === 32 && curElementTagName !== 'BUTTON') {
- ensureViewerFocused = true;
- }
- }
- if (cmd === 2) {
- // alt-key
- switch (evt.keyCode) {
- case 37:
- // left arrow
- if (isViewerInPresentationMode) {
- PDFViewerApplication.pdfHistory.back();
- handled = true;
- }
- break;
- case 39:
- // right arrow
- if (isViewerInPresentationMode) {
- PDFViewerApplication.pdfHistory.forward();
- handled = true;
- }
- break;
- }
- }
- if (ensureViewerFocused && !pdfViewer.containsElement(curElement)) {
- // The page container is not focused, but a page navigation key has been
- // pressed. Change the focus to the viewer container to make sure that
- // navigation by keyboard works as expected.
- pdfViewer.focus();
- }
- if (handled) {
- evt.preventDefault();
- }
- });
- window.addEventListener('beforeprint', function beforePrint(evt) {
- PDFViewerApplication.eventBus.dispatch('beforeprint');
- });
- window.addEventListener('afterprint', function afterPrint(evt) {
- PDFViewerApplication.eventBus.dispatch('afterprint');
- });
- (function animationStartedClosure() {
- // The offsetParent is not set until the pdf.js iframe or object is visible.
- // Waiting for first animation.
- PDFViewerApplication.animationStartedPromise = new Promise(function (resolve) {
- window.requestAnimationFrame(resolve);
- });
- }());
- /* Abstract factory for the print service. */
- var PDFPrintServiceFactory = {
- instance: {
- supportsPrinting: false,
- createPrintService: function () {
- throw new Error('Not implemented: createPrintService');
- }
- }
- };
- exports.PDFViewerApplication = PDFViewerApplication;
- exports.DefaultExernalServices = DefaultExernalServices;
- exports.PDFPrintServiceFactory = PDFPrintServiceFactory;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebFirefoxPrintService = {}, root.pdfjsWebUIUtils, root.pdfjsWebApp, root.pdfjsWebPDFJS);
- }(this, function (exports, uiUtils, app, pdfjsLib) {
- var CSS_UNITS = uiUtils.CSS_UNITS;
- var PDFPrintServiceFactory = app.PDFPrintServiceFactory;
- // Creates a placeholder with div and canvas with right size for the page.
- function composePage(pdfDocument, pageNumber, size, printContainer) {
- var canvas = document.createElement('canvas');
- // The size of the canvas in pixels for printing.
- var PRINT_RESOLUTION = 150;
- var PRINT_UNITS = PRINT_RESOLUTION / 72.0;
- canvas.width = Math.floor(size.width * PRINT_UNITS);
- canvas.height = Math.floor(size.height * PRINT_UNITS);
- // The physical size of the canvas as specified by the PDF document.
- canvas.style.width = Math.floor(size.width * CSS_UNITS) + 'px';
- canvas.style.height = Math.floor(size.height * CSS_UNITS) + 'px';
- var canvasWrapper = document.createElement('div');
- canvasWrapper.appendChild(canvas);
- printContainer.appendChild(canvasWrapper);
- canvas.mozPrintCallback = function (obj) {
- // Printing/rendering the page.
- var ctx = obj.context;
- ctx.save();
- ctx.fillStyle = 'rgb(255, 255, 255)';
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- ctx.restore();
- pdfDocument.getPage(pageNumber).then(function (pdfPage) {
- var renderContext = {
- canvasContext: ctx,
- transform: [
- PRINT_UNITS,
- 0,
- 0,
- PRINT_UNITS,
- 0,
- 0
- ],
- viewport: pdfPage.getViewport(1),
- intent: 'print'
- };
- return pdfPage.render(renderContext).promise;
- }).then(function () {
- // Tell the printEngine that rendering this canvas/page has finished.
- obj.done();
- }, function (error) {
- console.error(error);
- // Tell the printEngine that rendering this canvas/page has failed.
- // This will make the print process stop.
- if ('abort' in obj) {
- obj.abort();
- } else {
- obj.done();
- }
- });
- };
- }
- function FirefoxPrintService(pdfDocument, pagesOverview, printContainer) {
- this.pdfDocument = pdfDocument;
- this.pagesOverview = pagesOverview;
- this.printContainer = printContainer;
- }
- FirefoxPrintService.prototype = {
- layout: function () {
- var pdfDocument = this.pdfDocument;
- var printContainer = this.printContainer;
- var body = document.querySelector('body');
- body.setAttribute('data-pdfjsprinting', true);
- for (var i = 0, ii = this.pagesOverview.length; i < ii; ++i) {
- composePage(pdfDocument, i + 1, this.pagesOverview[i], printContainer);
- }
- },
- destroy: function () {
- this.printContainer.textContent = '';
- }
- };
- PDFPrintServiceFactory.instance = {
- get supportsPrinting() {
- var canvas = document.createElement('canvas');
- var value = 'mozPrintCallback' in canvas;
- return pdfjsLib.shadow(this, 'supportsPrinting', value);
- },
- createPrintService: function (pdfDocument, pagesOverview, printContainer) {
- return new FirefoxPrintService(pdfDocument, pagesOverview, printContainer);
- }
- };
- exports.FirefoxPrintService = FirefoxPrintService;
- }));
- (function (root, factory) {
- factory(root.pdfjsWebFirefoxCom = {}, root.pdfjsWebPreferences, root.pdfjsWebApp, root.pdfjsWebPDFJS);
- }(this, function (exports, preferences, app, pdfjsLib) {
- var Preferences = preferences.Preferences;
- var PDFViewerApplication = app.PDFViewerApplication;
- var FirefoxCom = function FirefoxComClosure() {
- return {
- /**
- * Creates an event that the extension is listening for and will
- * synchronously respond to.
- * NOTE: It is reccomended to use request() instead since one day we may not
- * be able to synchronously reply.
- * @param {String} action The action to trigger.
- * @param {String} data Optional data to send.
- * @return {*} The response.
- */
- requestSync: function (action, data) {
- var request = document.createTextNode('');
- document.documentElement.appendChild(request);
- var sender = document.createEvent('CustomEvent');
- sender.initCustomEvent('pdf.js.message', true, false, {
- action: action,
- data: data,
- sync: true
- });
- request.dispatchEvent(sender);
- var response = sender.detail.response;
- document.documentElement.removeChild(request);
- return response;
- },
- /**
- * Creates an event that the extension is listening for and will
- * asynchronously respond by calling the callback.
- * @param {String} action The action to trigger.
- * @param {String} data Optional data to send.
- * @param {Function} callback Optional response callback that will be called
- * with one data argument.
- */
- request: function (action, data, callback) {
- var request = document.createTextNode('');
- if (callback) {
- document.addEventListener('pdf.js.response', function listener(event) {
- var node = event.target;
- var response = event.detail.response;
- document.documentElement.removeChild(node);
- document.removeEventListener('pdf.js.response', listener, false);
- return callback(response);
- }, false);
- }
- document.documentElement.appendChild(request);
- var sender = document.createEvent('CustomEvent');
- sender.initCustomEvent('pdf.js.message', true, false, {
- action: action,
- data: data,
- sync: false,
- responseExpected: !!callback
- });
- return request.dispatchEvent(sender);
- }
- };
- }();
- var DownloadManager = function DownloadManagerClosure() {
- function DownloadManager() {
- }
- DownloadManager.prototype = {
- downloadUrl: function DownloadManager_downloadUrl(url, filename) {
- FirefoxCom.request('download', {
- originalUrl: url,
- filename: filename
- });
- },
- downloadData: function DownloadManager_downloadData(data, filename, contentType) {
- var blobUrl = pdfjsLib.createObjectURL(data, contentType, false);
- FirefoxCom.request('download', {
- blobUrl: blobUrl,
- originalUrl: blobUrl,
- filename: filename,
- isAttachment: true
- });
- },
- download: function DownloadManager_download(blob, url, filename) {
- var blobUrl = window.URL.createObjectURL(blob);
- FirefoxCom.request('download', {
- blobUrl: blobUrl,
- originalUrl: url,
- filename: filename
- }, function response(err) {
- if (err && this.onerror) {
- this.onerror(err);
- }
- window.URL.revokeObjectURL(blobUrl);
- }.bind(this));
- }
- };
- return DownloadManager;
- }();
- Preferences._writeToStorage = function (prefObj) {
- return new Promise(function (resolve) {
- FirefoxCom.request('setPreferences', prefObj, resolve);
- });
- };
- Preferences._readFromStorage = function (prefObj) {
- return new Promise(function (resolve) {
- FirefoxCom.request('getPreferences', prefObj, function (prefStr) {
- var readPrefs = JSON.parse(prefStr);
- resolve(readPrefs);
- });
- });
- };
- (function listenFindEvents() {
- var events = [
- 'find',
- 'findagain',
- 'findhighlightallchange',
- 'findcasesensitivitychange'
- ];
- var handleEvent = function (evt) {
- if (!PDFViewerApplication.initialized) {
- return;
- }
- PDFViewerApplication.eventBus.dispatch('find', {
- source: window,
- type: evt.type.substring('find'.length),
- query: evt.detail.query,
- phraseSearch: true,
- caseSensitive: !!evt.detail.caseSensitive,
- highlightAll: !!evt.detail.highlightAll,
- findPrevious: !!evt.detail.findPrevious
- });
- }.bind(this);
- for (var i = 0, len = events.length; i < len; i++) {
- window.addEventListener(events[i], handleEvent);
- }
- }());
- function FirefoxComDataRangeTransport(length, initialData) {
- pdfjsLib.PDFDataRangeTransport.call(this, length, initialData);
- }
- FirefoxComDataRangeTransport.prototype = Object.create(pdfjsLib.PDFDataRangeTransport.prototype);
- FirefoxComDataRangeTransport.prototype.requestDataRange = function FirefoxComDataRangeTransport_requestDataRange(begin, end) {
- FirefoxCom.request('requestDataRange', {
- begin: begin,
- end: end
- });
- };
- FirefoxComDataRangeTransport.prototype.abort = function FirefoxComDataRangeTransport_abort() {
- // Sync call to ensure abort is really started.
- FirefoxCom.requestSync('abortLoading', null);
- };
- PDFViewerApplication.externalServices = {
- updateFindControlState: function (data) {
- FirefoxCom.request('updateFindControlState', data);
- },
- initPassiveLoading: function (callbacks) {
- var pdfDataRangeTransport;
- window.addEventListener('message', function windowMessage(e) {
- if (e.source !== null) {
- // The message MUST originate from Chrome code.
- console.warn('Rejected untrusted message from ' + e.origin);
- return;
- }
- var args = e.data;
- if (typeof args !== 'object' || !('pdfjsLoadAction' in args)) {
- return;
- }
- switch (args.pdfjsLoadAction) {
- case 'supportsRangedLoading':
- pdfDataRangeTransport = new FirefoxComDataRangeTransport(args.length, args.data);
- callbacks.onOpenWithTransport(args.pdfUrl, args.length, pdfDataRangeTransport);
- break;
- case 'range':
- pdfDataRangeTransport.onDataRange(args.begin, args.chunk);
- break;
- case 'rangeProgress':
- pdfDataRangeTransport.onDataProgress(args.loaded);
- break;
- case 'progressiveRead':
- pdfDataRangeTransport.onDataProgressiveRead(args.chunk);
- break;
- case 'progress':
- callbacks.onProgress(args.loaded, args.total);
- break;
- case 'complete':
- if (!args.data) {
- callbacks.onError(args.errorCode);
- break;
- }
- callbacks.onOpenWithData(args.data);
- break;
- }
- });
- FirefoxCom.requestSync('initPassiveLoading', null);
- },
- fallback: function (data, callback) {
- FirefoxCom.request('fallback', data, callback);
- },
- reportTelemetry: function (data) {
- FirefoxCom.request('reportTelemetry', JSON.stringify(data));
- },
- createDownloadManager: function () {
- return new DownloadManager();
- },
- get supportsIntegratedFind() {
- var support = FirefoxCom.requestSync('supportsIntegratedFind');
- return pdfjsLib.shadow(this, 'supportsIntegratedFind', support);
- },
- get supportsDocumentFonts() {
- var support = FirefoxCom.requestSync('supportsDocumentFonts');
- return pdfjsLib.shadow(this, 'supportsDocumentFonts', support);
- },
- get supportsDocumentColors() {
- var support = FirefoxCom.requestSync('supportsDocumentColors');
- return pdfjsLib.shadow(this, 'supportsDocumentColors', support);
- },
- get supportedMouseWheelZoomModifierKeys() {
- var support = FirefoxCom.requestSync('supportedMouseWheelZoomModifierKeys');
- return pdfjsLib.shadow(this, 'supportedMouseWheelZoomModifierKeys', support);
- }
- };
- //// l10n.js for Firefox extension expects services to be set.
- document.mozL10n.setExternalLocalizerServices({
- getLocale: function () {
- return FirefoxCom.requestSync('getLocale', null);
- },
- getStrings: function (key) {
- return FirefoxCom.requestSync('getStrings', key);
- }
- });
- exports.DownloadManager = DownloadManager;
- exports.FirefoxCom = FirefoxCom;
- }));
- }.call(pdfjsWebLibs));
-}
-{
- // FIXME the l10n.js file in the Firefox extension needs global FirefoxCom.
- window.FirefoxCom = pdfjsWebLibs.pdfjsWebFirefoxCom.FirefoxCom;
-}
-function getViewerConfiguration() {
- return {
- appContainer: document.body,
- mainContainer: document.getElementById('viewerContainer'),
- viewerContainer: document.getElementById('viewer'),
- eventBus: null,
- // using global event bus with DOM events
- toolbar: {
- container: document.getElementById('toolbarViewer'),
- numPages: document.getElementById('numPages'),
- pageNumber: document.getElementById('pageNumber'),
- scaleSelectContainer: document.getElementById('scaleSelectContainer'),
- scaleSelect: document.getElementById('scaleSelect'),
- customScaleOption: document.getElementById('customScaleOption'),
- previous: document.getElementById('previous'),
- next: document.getElementById('next'),
- firstPage: document.getElementById('firstPage'),
- lastPage: document.getElementById('lastPage'),
- zoomIn: document.getElementById('zoomIn'),
- zoomOut: document.getElementById('zoomOut'),
- viewFind: document.getElementById('viewFind'),
- openFile: document.getElementById('openFile'),
- print: document.getElementById('print'),
- presentationModeButton: document.getElementById('presentationMode'),
- download: document.getElementById('download'),
- viewBookmark: document.getElementById('viewBookmark')
- },
- secondaryToolbar: {
- toolbar: document.getElementById('secondaryToolbar'),
- toggleButton: document.getElementById('secondaryToolbarToggle'),
- toolbarButtonContainer: document.getElementById('secondaryToolbarButtonContainer'),
- presentationModeButton: document.getElementById('secondaryPresentationMode'),
- openFileButton: document.getElementById('secondaryOpenFile'),
- printButton: document.getElementById('secondaryPrint'),
- downloadButton: document.getElementById('secondaryDownload'),
- viewBookmarkButton: document.getElementById('secondaryViewBookmark'),
- firstPageButton: document.getElementById('firstPage'),
- lastPageButton: document.getElementById('lastPage'),
- pageRotateCwButton: document.getElementById('pageRotateCw'),
- pageRotateCcwButton: document.getElementById('pageRotateCcw'),
- toggleHandToolButton: document.getElementById('toggleHandTool'),
- documentPropertiesButton: document.getElementById('documentProperties')
- },
- fullscreen: {
- contextFirstPage: document.getElementById('contextFirstPage'),
- contextLastPage: document.getElementById('contextLastPage'),
- contextPageRotateCw: document.getElementById('contextPageRotateCw'),
- contextPageRotateCcw: document.getElementById('contextPageRotateCcw')
- },
- sidebar: {
- // Divs (and sidebar button)
- mainContainer: document.getElementById('mainContainer'),
- outerContainer: document.getElementById('outerContainer'),
- toggleButton: document.getElementById('sidebarToggle'),
- // Buttons
- thumbnailButton: document.getElementById('viewThumbnail'),
- outlineButton: document.getElementById('viewOutline'),
- attachmentsButton: document.getElementById('viewAttachments'),
- // Views
- thumbnailView: document.getElementById('thumbnailView'),
- outlineView: document.getElementById('outlineView'),
- attachmentsView: document.getElementById('attachmentsView')
- },
- findBar: {
- bar: document.getElementById('findbar'),
- toggleButton: document.getElementById('viewFind'),
- findField: document.getElementById('findInput'),
- highlightAllCheckbox: document.getElementById('findHighlightAll'),
- caseSensitiveCheckbox: document.getElementById('findMatchCase'),
- findMsg: document.getElementById('findMsg'),
- findResultsCount: document.getElementById('findResultsCount'),
- findStatusIcon: document.getElementById('findStatusIcon'),
- findPreviousButton: document.getElementById('findPrevious'),
- findNextButton: document.getElementById('findNext')
- },
- passwordOverlay: {
- overlayName: 'passwordOverlay',
- container: document.getElementById('passwordOverlay'),
- label: document.getElementById('passwordText'),
- input: document.getElementById('password'),
- submitButton: document.getElementById('passwordSubmit'),
- cancelButton: document.getElementById('passwordCancel')
- },
- documentProperties: {
- overlayName: 'documentPropertiesOverlay',
- container: document.getElementById('documentPropertiesOverlay'),
- closeButton: document.getElementById('documentPropertiesClose'),
- fields: {
- 'fileName': document.getElementById('fileNameField'),
- 'fileSize': document.getElementById('fileSizeField'),
- 'title': document.getElementById('titleField'),
- 'author': document.getElementById('authorField'),
- 'subject': document.getElementById('subjectField'),
- 'keywords': document.getElementById('keywordsField'),
- 'creationDate': document.getElementById('creationDateField'),
- 'modificationDate': document.getElementById('modificationDateField'),
- 'creator': document.getElementById('creatorField'),
- 'producer': document.getElementById('producerField'),
- 'version': document.getElementById('versionField'),
- 'pageCount': document.getElementById('pageCountField')
- }
- },
- errorWrapper: {
- container: document.getElementById('errorWrapper'),
- errorMessage: document.getElementById('errorMessage'),
- closeButton: document.getElementById('errorClose'),
- errorMoreInfo: document.getElementById('errorMoreInfo'),
- moreInfoButton: document.getElementById('errorShowMore'),
- lessInfoButton: document.getElementById('errorShowLess')
- },
- printContainer: document.getElementById('printContainer'),
- openFileInputName: 'fileInput',
- debuggerScriptPath: './debugger.js'
- };
-}
-function webViewerLoad() {
- var config = getViewerConfiguration();
- window.PDFViewerApplication = pdfjsWebLibs.pdfjsWebApp.PDFViewerApplication;
- pdfjsWebLibs.pdfjsWebApp.PDFViewerApplication.run(config);
-}
-document.addEventListener('DOMContentLoaded', webViewerLoad, true); \ No newline at end of file
diff --git a/extensions/pdfjs/jar.mn b/extensions/pdfjs/jar.mn
deleted file mode 100644
index ca11481..0000000
--- a/extensions/pdfjs/jar.mn
+++ /dev/null
@@ -1,3 +0,0 @@
-pdfjs.jar:
-% resource pdf.js %content/
- content/ (content/*)
diff --git a/extensions/pdfjs/moz.build b/extensions/pdfjs/moz.build
deleted file mode 100644
index aac3a83..0000000
--- a/extensions/pdfjs/moz.build
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']