Merge branch 'master' of github.com:mozilla/pdf.js into textsearch
This commit is contained in:
commit
0bac4abcb5
1
extensions/chrome/.gitignore
vendored
Normal file
1
extensions/chrome/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
content/
|
2
extensions/firefox/.gitignore
vendored
2
extensions/firefox/.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
content/
|
content/
|
||||||
metadata.inc
|
metadata.inc
|
||||||
|
chrome.manifest.inc
|
||||||
|
locale/
|
||||||
|
21
extensions/firefox/bootstrap.js
vendored
21
extensions/firefox/bootstrap.js
vendored
@ -10,13 +10,26 @@ let Cc = Components.classes;
|
|||||||
let Ci = Components.interfaces;
|
let Ci = Components.interfaces;
|
||||||
let Cm = Components.manager;
|
let Cm = Components.manager;
|
||||||
let Cu = Components.utils;
|
let Cu = Components.utils;
|
||||||
let application = Cc['@mozilla.org/fuel/application;1']
|
|
||||||
.getService(Ci.fuelIApplication);
|
|
||||||
|
|
||||||
Cu.import('resource://gre/modules/Services.jsm');
|
Cu.import('resource://gre/modules/Services.jsm');
|
||||||
|
|
||||||
|
function getBoolPref(pref, def) {
|
||||||
|
try {
|
||||||
|
return Services.prefs.getBoolPref(pref);
|
||||||
|
} catch (ex) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStringPref(pref, value) {
|
||||||
|
let str = Cc['@mozilla.org/supports-string;1']
|
||||||
|
.createInstance(Ci.nsISupportsString);
|
||||||
|
str.data = value;
|
||||||
|
Services.prefs.setComplexValue(pref, Ci.nsISupportsString, str);
|
||||||
|
}
|
||||||
|
|
||||||
function log(str) {
|
function log(str) {
|
||||||
if (!application.prefs.getValue(EXT_PREFIX + '.pdfBugEnabled', false))
|
if (!getBoolPref(EXT_PREFIX + '.pdfBugEnabled', false))
|
||||||
return;
|
return;
|
||||||
dump(str + '\n');
|
dump(str + '\n');
|
||||||
}
|
}
|
||||||
@ -93,6 +106,6 @@ function install(aData, aReason) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function uninstall(aData, aReason) {
|
function uninstall(aData, aReason) {
|
||||||
application.prefs.setValue(EXT_PREFIX + '.database', '{}');
|
setStringPref(EXT_PREFIX + '.database', '{}');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
extensions/firefox/chrome.manifest
Normal file
3
extensions/firefox/chrome.manifest
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Additional resources for pdf.js
|
||||||
|
|
||||||
|
# PDFJS_SUPPORTED_LOCALES
|
@ -13,18 +13,51 @@ const PDFJS_EVENT_ID = 'pdf.js.message';
|
|||||||
const PDF_CONTENT_TYPE = 'application/pdf';
|
const PDF_CONTENT_TYPE = 'application/pdf';
|
||||||
const EXT_PREFIX = 'extensions.uriloader@pdf.js';
|
const EXT_PREFIX = 'extensions.uriloader@pdf.js';
|
||||||
const MAX_DATABASE_LENGTH = 4096;
|
const MAX_DATABASE_LENGTH = 4096;
|
||||||
|
const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
|
||||||
|
const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
|
||||||
|
|
||||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||||
Cu.import('resource://gre/modules/Services.jsm');
|
Cu.import('resource://gre/modules/Services.jsm');
|
||||||
|
Cu.import('resource://gre/modules/NetUtil.jsm');
|
||||||
|
|
||||||
let application = Cc['@mozilla.org/fuel/application;1']
|
let appInfo = Cc['@mozilla.org/xre/app-info;1']
|
||||||
.getService(Ci.fuelIApplication);
|
.getService(Ci.nsIXULAppInfo);
|
||||||
let privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
|
let privateBrowsing, inPrivateBrowsing;
|
||||||
.getService(Ci.nsIPrivateBrowsingService);
|
|
||||||
let inPrivateBrowswing = privateBrowsing.privateBrowsingEnabled;
|
if (appInfo.ID === FIREFOX_ID) {
|
||||||
|
privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
|
||||||
|
.getService(Ci.nsIPrivateBrowsingService);
|
||||||
|
inPrivateBrowsing = privateBrowsing.privateBrowsingEnabled;
|
||||||
|
} else if (appInfo.ID === SEAMONKEY_ID) {
|
||||||
|
privateBrowsing = null;
|
||||||
|
inPrivateBrowsing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBoolPref(pref, def) {
|
||||||
|
try {
|
||||||
|
return Services.prefs.getBoolPref(pref);
|
||||||
|
} catch (ex) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStringPref(pref, value) {
|
||||||
|
let str = Cc['@mozilla.org/supports-string;1']
|
||||||
|
.createInstance(Ci.nsISupportsString);
|
||||||
|
str.data = value;
|
||||||
|
Services.prefs.setComplexValue(pref, Ci.nsISupportsString, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStringPref(pref, def) {
|
||||||
|
try {
|
||||||
|
return Services.prefs.getComplexValue(pref, Ci.nsISupportsString).data;
|
||||||
|
} catch (ex) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function log(aMsg) {
|
function log(aMsg) {
|
||||||
if (!application.prefs.getValue(EXT_PREFIX + '.pdfBugEnabled', false))
|
if (!getBoolPref(EXT_PREFIX + '.pdfBugEnabled', false))
|
||||||
return;
|
return;
|
||||||
let msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
|
let msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
|
||||||
Services.console.logStringMessage(msg);
|
Services.console.logStringMessage(msg);
|
||||||
@ -37,32 +70,97 @@ function getDOMWindow(aChannel) {
|
|||||||
return win;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
// All the priviledged actions.
|
// All the priviledged actions.
|
||||||
function ChromeActions() {
|
function ChromeActions() {
|
||||||
this.inPrivateBrowswing = privateBrowsing.privateBrowsingEnabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ChromeActions.prototype = {
|
ChromeActions.prototype = {
|
||||||
download: function(data) {
|
download: function(data) {
|
||||||
Services.wm.getMostRecentWindow('navigator:browser').saveURL(data);
|
let mimeService = Cc['@mozilla.org/mime;1'].getService(Ci.nsIMIMEService);
|
||||||
|
var handlerInfo = mimeService.
|
||||||
|
getFromTypeAndExtension('application/pdf', 'pdf');
|
||||||
|
var uri = NetUtil.newURI(data);
|
||||||
|
|
||||||
|
var extHelperAppSvc =
|
||||||
|
Cc['@mozilla.org/uriloader/external-helper-app-service;1'].
|
||||||
|
getService(Ci.nsIExternalHelperAppService);
|
||||||
|
var frontWindow = Cc['@mozilla.org/embedcomp/window-watcher;1'].
|
||||||
|
getService(Ci.nsIWindowWatcher).activeWindow;
|
||||||
|
var ioService = Services.io;
|
||||||
|
var channel = ioService.newChannel(data, null, null);
|
||||||
|
var listener = {
|
||||||
|
extListener: null,
|
||||||
|
onStartRequest: function(aRequest, aContext) {
|
||||||
|
this.extListener = extHelperAppSvc.doContent('application/pdf',
|
||||||
|
aRequest, frontWindow, false);
|
||||||
|
this.extListener.onStartRequest(aRequest, aContext);
|
||||||
|
},
|
||||||
|
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
||||||
|
if (this.extListener)
|
||||||
|
this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
|
||||||
|
},
|
||||||
|
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset,
|
||||||
|
aCount) {
|
||||||
|
this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
|
||||||
|
aOffset, aCount);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
channel.asyncOpen(listener, null);
|
||||||
},
|
},
|
||||||
setDatabase: function(data) {
|
setDatabase: function(data) {
|
||||||
if (this.inPrivateBrowswing)
|
if (inPrivateBrowsing)
|
||||||
return;
|
return;
|
||||||
// Protect against something sending tons of data to setDatabase.
|
// Protect against something sending tons of data to setDatabase.
|
||||||
if (data.length > MAX_DATABASE_LENGTH)
|
if (data.length > MAX_DATABASE_LENGTH)
|
||||||
return;
|
return;
|
||||||
application.prefs.setValue(EXT_PREFIX + '.database', data);
|
setStringPref(EXT_PREFIX + '.database', data);
|
||||||
},
|
},
|
||||||
getDatabase: function() {
|
getDatabase: function() {
|
||||||
if (this.inPrivateBrowswing)
|
if (inPrivateBrowsing)
|
||||||
return '{}';
|
return '{}';
|
||||||
return application.prefs.getValue(EXT_PREFIX + '.database', '{}');
|
return getStringPref(EXT_PREFIX + '.database', '{}');
|
||||||
},
|
},
|
||||||
getLocale: function() {
|
getLocale: function() {
|
||||||
return application.prefs.getValue('general.useragent.locale', 'en-US');
|
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 retrive localized strings: ' + e);
|
||||||
|
return 'null';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
pdfBugEnabled: function() {
|
pdfBugEnabled: function() {
|
||||||
return application.prefs.getValue(EXT_PREFIX + '.pdfBugEnabled', false);
|
return getBoolPref(EXT_PREFIX + '.pdfBugEnabled', false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,11 +8,22 @@
|
|||||||
<!-- PDFJS_LOCALIZED_METADATA -->
|
<!-- PDFJS_LOCALIZED_METADATA -->
|
||||||
<em:name>PDF Viewer</em:name>
|
<em:name>PDF Viewer</em:name>
|
||||||
<em:version>PDFJSSCRIPT_VERSION</em:version>
|
<em:version>PDFJSSCRIPT_VERSION</em:version>
|
||||||
|
|
||||||
|
<!-- Firefox -->
|
||||||
<em:targetApplication>
|
<em:targetApplication>
|
||||||
<Description>
|
<Description>
|
||||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||||
<em:minVersion>6.0</em:minVersion>
|
<em:minVersion>6.0</em:minVersion>
|
||||||
<em:maxVersion>14.0a1</em:maxVersion>
|
<em:maxVersion>15.0a1</em:maxVersion>
|
||||||
|
</Description>
|
||||||
|
</em:targetApplication>
|
||||||
|
|
||||||
|
<!-- SeaMonkey -->
|
||||||
|
<em:targetApplication>
|
||||||
|
<Description>
|
||||||
|
<em:id>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</em:id>
|
||||||
|
<em:minVersion>2.1.*</em:minVersion>
|
||||||
|
<em:maxVersion>2.12a1</em:maxVersion>
|
||||||
</Description>
|
</Description>
|
||||||
</em:targetApplication>
|
</em:targetApplication>
|
||||||
<em:bootstrap>true</em:bootstrap>
|
<em:bootstrap>true</em:bootstrap>
|
||||||
|
114
extensions/firefox/tools/l10n.js
Normal file
114
extensions/firefox/tools/l10n.js
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Small subset of the webL10n API by Fabien Cazenave for pdf.js extension.
|
||||||
|
(function(window) {
|
||||||
|
var gLanguage = '';
|
||||||
|
|
||||||
|
// fetch an l10n objects
|
||||||
|
function getL10nData(key) {
|
||||||
|
var response = FirefoxCom.request('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 data = getL10nData(key);
|
||||||
|
if (!data && fallback)
|
||||||
|
data = {textContent: fallback};
|
||||||
|
if (!data)
|
||||||
|
return '{{' + key + '}}';
|
||||||
|
return substArguments(data.textContent, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// translate an HTML element
|
||||||
|
function translateElement(element) {
|
||||||
|
if (!element || !element.dataset)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get the related l10n object
|
||||||
|
var data = getL10nData(element.dataset.l10nId);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('DOMContentLoaded', function() {
|
||||||
|
gLanguage = FirefoxCom.request('getLocale', null);
|
||||||
|
|
||||||
|
translateFragment();
|
||||||
|
|
||||||
|
// fire a 'localized' DOM event
|
||||||
|
var evtObject = document.createEvent('Event');
|
||||||
|
evtObject.initEvent('localized', false, false);
|
||||||
|
evtObject.language = gLanguage;
|
||||||
|
window.dispatchEvent(evtObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Public API
|
||||||
|
document.mozL10n = {
|
||||||
|
// get a localized string
|
||||||
|
get: translateString,
|
||||||
|
|
||||||
|
// get|set the document language and direction
|
||||||
|
get language() {
|
||||||
|
return {
|
||||||
|
// get|set the document language (ISO-639-1)
|
||||||
|
get code() { return gLanguage; },
|
||||||
|
|
||||||
|
// get the direction (ltr|rtl) of the current language
|
||||||
|
get direction() {
|
||||||
|
// http://www.w3.org/International/questions/qa-scripts
|
||||||
|
// Arabic, Hebrew, Farsi, Pashto, Urdu
|
||||||
|
var rtlList = ['ar', 'he', 'fa', 'ps', 'ur'];
|
||||||
|
return (rtlList.indexOf(gLanguage) >= 0) ? 'rtl' : 'ltr';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(this);
|
||||||
|
|
@ -40,3 +40,5 @@ download_label=Download
|
|||||||
zoom_out_label=Zoom Out
|
zoom_out_label=Zoom Out
|
||||||
zoom_in_label=Zoom In
|
zoom_in_label=Zoom In
|
||||||
zoom.title=Zoom
|
zoom.title=Zoom
|
||||||
|
thumb_page_title=Page {{page}}
|
||||||
|
thumb_page_canvas=Thumbnail of Page {{page}}
|
||||||
|
8
l10n/pl/metadata.inc
Normal file
8
l10n/pl/metadata.inc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<em:localized>
|
||||||
|
<Description>
|
||||||
|
<em:locale>pl</em:locale>
|
||||||
|
<em:name>Przeglądarka PDF</em:name>
|
||||||
|
<em:description>Używa HTML5 do wyświetlania plików PDF bezpośrednio w Firefoksie.</em:description>
|
||||||
|
</Description>
|
||||||
|
</em:localized>
|
||||||
|
|
42
l10n/pl/viewer.properties
Normal file
42
l10n/pl/viewer.properties
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
bookmark.title=Aktualny widok (kopiuj lub otwórz w nowym oknie)
|
||||||
|
previous.title=Poprzednia strona
|
||||||
|
next.title=Następna strona
|
||||||
|
print.title=Drukuj
|
||||||
|
download.title=Pobierz
|
||||||
|
zoom_out.title=Pomniejsz
|
||||||
|
zoom_in.title=Powiększ
|
||||||
|
error_more_info=Więcej informacji
|
||||||
|
error_less_info=Mniej informacji
|
||||||
|
error_close=Zamknij
|
||||||
|
error_build=Wersja PDF.JS: {{build}}
|
||||||
|
error_message=Wiadomość: {{message}}
|
||||||
|
error_stack=Stos: {{stack}}
|
||||||
|
error_file=Plik: {{file}}
|
||||||
|
error_line=Linia: {{line}}
|
||||||
|
page_scale_width=Szerokość strony
|
||||||
|
page_scale_fit=Cała strona
|
||||||
|
page_scale_auto=Automatyczne dopasowanie
|
||||||
|
page_scale_actual=Rzeczywisty rozmiar
|
||||||
|
toggle_slider.title=Włącz/wyłącz suwak
|
||||||
|
thumbs.title=Wyświetl miniatury
|
||||||
|
outline.title=Wyświetl konspekt dokumentu
|
||||||
|
loading=Wczytywanie... {{percent}}%
|
||||||
|
loading_error_indicator=Błąd
|
||||||
|
loading_error=Wystąpił błąd podczas wczytywania pliku PDF.
|
||||||
|
rendering_error=Wystąpił błąd podczas wyświetlania strony.
|
||||||
|
page_label=Strona:
|
||||||
|
page_of=z {{pageCount}}
|
||||||
|
no_outline=Konspekt nie jest dostępny
|
||||||
|
open_file.title=Otwórz plik
|
||||||
|
text_annotation_type=[Komentarz {{type}}]
|
||||||
|
toggle_slider_label=Przełącz suwak
|
||||||
|
thumbs_label=Miniatury
|
||||||
|
outline_label=Konspekt dokumentu
|
||||||
|
bookmark_label=Aktualny widok
|
||||||
|
previous_label=Wstecz
|
||||||
|
next_label=Dalej
|
||||||
|
print_label=Drukuj
|
||||||
|
download_label=Pobierz
|
||||||
|
zoom_out_label=Pomniejsz
|
||||||
|
zoom_in_label=Powiększ
|
||||||
|
zoom.title=Powiększenie
|
8
l10n/ro/metadata.inc
Normal file
8
l10n/ro/metadata.inc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<em:localized>
|
||||||
|
<Description>
|
||||||
|
<em:locale>ro</em:locale>
|
||||||
|
<em:name>Cititor PDF</em:name>
|
||||||
|
<em:description>Afișează fișierele PDF direct în Firefox.</em:description>
|
||||||
|
</Description>
|
||||||
|
</em:localized>
|
||||||
|
|
42
l10n/ro/viewer.properties
Normal file
42
l10n/ro/viewer.properties
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
bookmark.title=Vederea curentă (copiază sau deschide în fereastră nouă)
|
||||||
|
previous.title=Pagina precedentă
|
||||||
|
next.title=Pagina următoare
|
||||||
|
print.title=Tipărește
|
||||||
|
download.title=Descarcă
|
||||||
|
zoom_out.title=Micșorează
|
||||||
|
zoom_in.title=Mărește
|
||||||
|
error_more_info=Detaliat
|
||||||
|
error_less_info=Sumarizat
|
||||||
|
error_close=Închide
|
||||||
|
error_build=PDF.JS Build: {{build}}
|
||||||
|
error_message=Message: {{message}}
|
||||||
|
error_stack=Stack: {{stack}}
|
||||||
|
error_file=File: {{file}}
|
||||||
|
error_line=Line: {{line}}
|
||||||
|
page_scale_width=După lățime
|
||||||
|
page_scale_fit=Toată pagina
|
||||||
|
page_scale_auto=Mărime automată
|
||||||
|
page_scale_actual=Mărime originală
|
||||||
|
toggle_slider.title=Vedere de ansamblu
|
||||||
|
thumbs.title=Miniaturi
|
||||||
|
outline.title=Cuprins
|
||||||
|
loading=Încărcare... {{percent}}%
|
||||||
|
loading_error_indicator=Eroare
|
||||||
|
loading_error=S-a produs o eroare în timpul încărcării documentului.
|
||||||
|
rendering_error=S-a produs o eroare în timpul procesării paginii.
|
||||||
|
page_label=Pagina:
|
||||||
|
page_of=din {{pageCount}}
|
||||||
|
no_outline=Cuprins indisponibil
|
||||||
|
open_file.title=Deschide fișier
|
||||||
|
text_annotation_type=[Adnotare {{type}}]
|
||||||
|
toggle_slider_label=Vedere de ansamblu
|
||||||
|
thumbs_label=Miniaturi
|
||||||
|
outline_label=Cuprins
|
||||||
|
bookmark_label=Vederea curentă
|
||||||
|
previous_label=Înapoi
|
||||||
|
next_label=Înainte
|
||||||
|
print_label=Tipărește
|
||||||
|
download_label=Descarcă
|
||||||
|
zoom_out_label=Micșorează
|
||||||
|
zoom_in_label=Mărește
|
||||||
|
zoom.title=Mărime
|
@ -40,3 +40,5 @@ download_label=<<<_ÐOẂпḻOãÐ_>>>
|
|||||||
zoom_out_label=<<<_ƩOOм Oȗţ_>>>
|
zoom_out_label=<<<_ƩOOм Oȗţ_>>>
|
||||||
zoom_in_label=<<<_ƩOOм iп_>>>
|
zoom_in_label=<<<_ƩOOм iп_>>>
|
||||||
zoom.title=<<<_ƩOOм_>>>
|
zoom.title=<<<_ƩOOм_>>>
|
||||||
|
thumb_page_title=<<<_Þãģε {{page}}_>>>
|
||||||
|
thumb_page_canvas=<<<_ţНȗмьпãiḻ O£ Þãģε {{page}}_>>>
|
||||||
|
57
make.js
57
make.js
@ -6,6 +6,7 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root
|
|||||||
BUILD_TARGET = BUILD_DIR + 'pdf.js',
|
BUILD_TARGET = BUILD_DIR + 'pdf.js',
|
||||||
FIREFOX_BUILD_DIR = BUILD_DIR + '/firefox/',
|
FIREFOX_BUILD_DIR = BUILD_DIR + '/firefox/',
|
||||||
EXTENSION_SRC_DIR = 'extensions/',
|
EXTENSION_SRC_DIR = 'extensions/',
|
||||||
|
LOCALE_SRC_DIR = 'l10n/',
|
||||||
GH_PAGES_DIR = BUILD_DIR + 'gh-pages/',
|
GH_PAGES_DIR = BUILD_DIR + 'gh-pages/',
|
||||||
REPO = 'git@github.com:mozilla/pdf.js.git',
|
REPO = 'git@github.com:mozilla/pdf.js.git',
|
||||||
PYTHON_BIN = 'python2.7';
|
PYTHON_BIN = 'python2.7';
|
||||||
@ -67,8 +68,9 @@ target.web = function() {
|
|||||||
// Creates localized resources for the viewer and extension.
|
// Creates localized resources for the viewer and extension.
|
||||||
//
|
//
|
||||||
target.locale = function() {
|
target.locale = function() {
|
||||||
var L10N_PATH = 'l10n';
|
|
||||||
var METADATA_OUTPUT = 'extensions/firefox/metadata.inc';
|
var METADATA_OUTPUT = 'extensions/firefox/metadata.inc';
|
||||||
|
var CHROME_MANIFEST_OUTPUT = 'extensions/firefox/chrome.manifest.inc';
|
||||||
|
var EXTENSION_LOCALE_OUTPUT = 'extensions/firefox/locale';
|
||||||
var VIEWER_OUTPUT = 'web/locale.properties';
|
var VIEWER_OUTPUT = 'web/locale.properties';
|
||||||
var DEFAULT_LOCALE = 'en-US';
|
var DEFAULT_LOCALE = 'en-US';
|
||||||
|
|
||||||
@ -76,13 +78,17 @@ target.locale = function() {
|
|||||||
echo();
|
echo();
|
||||||
echo('### Building localization files');
|
echo('### Building localization files');
|
||||||
|
|
||||||
var subfolders = ls(L10N_PATH);
|
rm('-rf', EXTENSION_LOCALE_OUTPUT);
|
||||||
|
mkdir('-p', EXTENSION_LOCALE_OUTPUT);
|
||||||
|
|
||||||
|
var subfolders = ls(LOCALE_SRC_DIR);
|
||||||
subfolders.sort();
|
subfolders.sort();
|
||||||
var metadataContent = '';
|
var metadataContent = '';
|
||||||
|
var chromeManifestContent = '';
|
||||||
var viewerOutput = '';
|
var viewerOutput = '';
|
||||||
for (var i = 0; i < subfolders.length; i++) {
|
for (var i = 0; i < subfolders.length; i++) {
|
||||||
var locale = subfolders[i];
|
var locale = subfolders[i];
|
||||||
var path = L10N_PATH + '/' + locale;
|
var path = LOCALE_SRC_DIR + locale;
|
||||||
if (!test('-d', path))
|
if (!test('-d', path))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -91,12 +97,13 @@ target.locale = function() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mkdir('-p', EXTENSION_LOCALE_OUTPUT + '/' + locale);
|
||||||
|
chromeManifestContent += 'locale pdf.js ' + locale + ' locale/' + locale + '/\n';
|
||||||
|
|
||||||
if (test('-f', path + '/viewer.properties')) {
|
if (test('-f', path + '/viewer.properties')) {
|
||||||
var properties = cat(path + '/viewer.properties');
|
var properties = cat(path + '/viewer.properties');
|
||||||
if (locale == DEFAULT_LOCALE)
|
viewerOutput += '[' + locale + ']\n' + properties + '\n';
|
||||||
viewerOutput = '[*]\n' + properties + '\n' + viewerOutput;
|
cp(path + '/viewer.properties', EXTENSION_LOCALE_OUTPUT + '/' + locale);
|
||||||
else
|
|
||||||
viewerOutput = viewerOutput + '[' + locale + ']\n' + properties + '\n';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test('-f', path + '/metadata.inc')) {
|
if (test('-f', path + '/metadata.inc')) {
|
||||||
@ -106,6 +113,7 @@ target.locale = function() {
|
|||||||
}
|
}
|
||||||
viewerOutput.to(VIEWER_OUTPUT);
|
viewerOutput.to(VIEWER_OUTPUT);
|
||||||
metadataContent.to(METADATA_OUTPUT);
|
metadataContent.to(METADATA_OUTPUT);
|
||||||
|
chromeManifestContent.to(CHROME_MANIFEST_OUTPUT);
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -227,7 +235,7 @@ var EXTENSION_WEB_FILES =
|
|||||||
'web/viewer.css',
|
'web/viewer.css',
|
||||||
'web/viewer.js',
|
'web/viewer.js',
|
||||||
'web/viewer.html',
|
'web/viewer.html',
|
||||||
'external/webL10n/l10n.js',
|
'extensions/firefox/tools/l10n.js',
|
||||||
'web/viewer-production.html'],
|
'web/viewer-production.html'],
|
||||||
EXTENSION_BASE_VERSION = 'f0f0418a9c6637981fe1182b9212c2d592774c7d',
|
EXTENSION_BASE_VERSION = 'f0f0418a9c6637981fe1182b9212c2d592774c7d',
|
||||||
EXTENSION_VERSION_PREFIX = '0.3.',
|
EXTENSION_VERSION_PREFIX = '0.3.',
|
||||||
@ -242,6 +250,7 @@ target.extension = function() {
|
|||||||
echo();
|
echo();
|
||||||
echo('### Building extensions');
|
echo('### Building extensions');
|
||||||
|
|
||||||
|
target.locale();
|
||||||
target.production();
|
target.production();
|
||||||
target.firefox();
|
target.firefox();
|
||||||
target.chrome();
|
target.chrome();
|
||||||
@ -277,21 +286,24 @@ target.firefox = function() {
|
|||||||
'*.rdf',
|
'*.rdf',
|
||||||
'*.svg',
|
'*.svg',
|
||||||
'*.png',
|
'*.png',
|
||||||
|
'*.manifest',
|
||||||
'components',
|
'components',
|
||||||
|
'locale',
|
||||||
'../../LICENSE'],
|
'../../LICENSE'],
|
||||||
FIREFOX_EXTENSION_FILES =
|
FIREFOX_EXTENSION_FILES =
|
||||||
['bootstrap.js',
|
['bootstrap.js',
|
||||||
'install.rdf',
|
'install.rdf',
|
||||||
|
'chrome.manifest',
|
||||||
'icon.png',
|
'icon.png',
|
||||||
'icon64.png',
|
'icon64.png',
|
||||||
'components',
|
'components',
|
||||||
'content',
|
'content',
|
||||||
|
'locale',
|
||||||
'LICENSE'],
|
'LICENSE'],
|
||||||
FIREFOX_EXTENSION_NAME = 'pdf.js.xpi',
|
FIREFOX_EXTENSION_NAME = 'pdf.js.xpi',
|
||||||
FIREFOX_AMO_EXTENSION_NAME = 'pdf.js.amo.xpi';
|
FIREFOX_AMO_EXTENSION_NAME = 'pdf.js.amo.xpi';
|
||||||
|
|
||||||
var LOCALE_CONTENT = cat('web/locale.properties');
|
target.locale();
|
||||||
|
|
||||||
target.production();
|
target.production();
|
||||||
target.buildnumber();
|
target.buildnumber();
|
||||||
cd(ROOT_DIR);
|
cd(ROOT_DIR);
|
||||||
@ -310,7 +322,6 @@ target.firefox = function() {
|
|||||||
// Copy a standalone version of pdf.js inside the content directory
|
// Copy a standalone version of pdf.js inside the content directory
|
||||||
cp(BUILD_TARGET, FIREFOX_BUILD_CONTENT_DIR + BUILD_DIR);
|
cp(BUILD_TARGET, FIREFOX_BUILD_CONTENT_DIR + BUILD_DIR);
|
||||||
cp('-R', EXTENSION_WEB_FILES, FIREFOX_BUILD_CONTENT_DIR + '/web');
|
cp('-R', EXTENSION_WEB_FILES, FIREFOX_BUILD_CONTENT_DIR + '/web');
|
||||||
cp('web/locale.properties', FIREFOX_BUILD_CONTENT_DIR + '/web');
|
|
||||||
rm(FIREFOX_BUILD_CONTENT_DIR + '/web/viewer-production.html');
|
rm(FIREFOX_BUILD_CONTENT_DIR + '/web/viewer-production.html');
|
||||||
|
|
||||||
// Copy over the firefox extension snippet so we can inline pdf.js in it
|
// Copy over the firefox extension snippet so we can inline pdf.js in it
|
||||||
@ -319,7 +330,6 @@ target.firefox = function() {
|
|||||||
// Modify the viewer so it does all the extension-only stuff.
|
// Modify the viewer so it does all the extension-only stuff.
|
||||||
cd(FIREFOX_BUILD_CONTENT_DIR + '/web');
|
cd(FIREFOX_BUILD_CONTENT_DIR + '/web');
|
||||||
sed('-i', /.*PDFJSSCRIPT_INCLUDE_BUNDLE.*\n/, cat(ROOT_DIR + BUILD_TARGET), 'viewer-snippet-firefox-extension.html');
|
sed('-i', /.*PDFJSSCRIPT_INCLUDE_BUNDLE.*\n/, cat(ROOT_DIR + BUILD_TARGET), 'viewer-snippet-firefox-extension.html');
|
||||||
sed('-i', /.*PDFJSSCRIPT_LOCALE_DATA.*\n/, LOCALE_CONTENT, 'viewer-snippet-firefox-extension.html');
|
|
||||||
sed('-i', /.*PDFJSSCRIPT_REMOVE_CORE.*\n/g, '', 'viewer.html');
|
sed('-i', /.*PDFJSSCRIPT_REMOVE_CORE.*\n/g, '', 'viewer.html');
|
||||||
sed('-i', /.*PDFJSSCRIPT_REMOVE_FIREFOX_EXTENSION.*\n/g, '', 'viewer.html');
|
sed('-i', /.*PDFJSSCRIPT_REMOVE_FIREFOX_EXTENSION.*\n/g, '', 'viewer.html');
|
||||||
sed('-i', /.*PDFJSSCRIPT_INCLUDE_FIREFOX_EXTENSION.*\n/, cat('viewer-snippet-firefox-extension.html'), 'viewer.html');
|
sed('-i', /.*PDFJSSCRIPT_INCLUDE_FIREFOX_EXTENSION.*\n/, cat('viewer-snippet-firefox-extension.html'), 'viewer.html');
|
||||||
@ -328,7 +338,6 @@ target.firefox = function() {
|
|||||||
// We don't need pdf.js anymore since its inlined
|
// We don't need pdf.js anymore since its inlined
|
||||||
rm('-Rf', FIREFOX_BUILD_CONTENT_DIR + BUILD_DIR);
|
rm('-Rf', FIREFOX_BUILD_CONTENT_DIR + BUILD_DIR);
|
||||||
rm(FIREFOX_BUILD_CONTENT_DIR + '/web/viewer-snippet-firefox-extension.html');
|
rm(FIREFOX_BUILD_CONTENT_DIR + '/web/viewer-snippet-firefox-extension.html');
|
||||||
rm(FIREFOX_BUILD_CONTENT_DIR + '/web/locale.properties');
|
|
||||||
// Remove '.DS_Store' and other hidden files
|
// Remove '.DS_Store' and other hidden files
|
||||||
find(FIREFOX_BUILD_DIR).forEach(function(file) {
|
find(FIREFOX_BUILD_DIR).forEach(function(file) {
|
||||||
if (file.match(/^\./))
|
if (file.match(/^\./))
|
||||||
@ -342,6 +351,8 @@ target.firefox = function() {
|
|||||||
// Update localized metadata
|
// Update localized metadata
|
||||||
var localizedMetadata = cat(EXTENSION_SRC_DIR + '/firefox/metadata.inc');
|
var localizedMetadata = cat(EXTENSION_SRC_DIR + '/firefox/metadata.inc');
|
||||||
sed('-i', /.*PDFJS_LOCALIZED_METADATA.*\n/, localizedMetadata, FIREFOX_BUILD_DIR + '/install.rdf');
|
sed('-i', /.*PDFJS_LOCALIZED_METADATA.*\n/, localizedMetadata, FIREFOX_BUILD_DIR + '/install.rdf');
|
||||||
|
var chromeManifest = cat(EXTENSION_SRC_DIR + '/firefox/chrome.manifest.inc');
|
||||||
|
sed('-i', /.*PDFJS_SUPPORTED_LOCALES.*\n/, chromeManifest, FIREFOX_BUILD_DIR + '/chrome.manifest');
|
||||||
|
|
||||||
// Create the xpi
|
// Create the xpi
|
||||||
cd(FIREFOX_BUILD_DIR);
|
cd(FIREFOX_BUILD_DIR);
|
||||||
@ -365,25 +376,27 @@ target.mozcentral = function() {
|
|||||||
echo();
|
echo();
|
||||||
echo('### Building mozilla-central extension');
|
echo('### Building mozilla-central extension');
|
||||||
|
|
||||||
var MOZCENTRAL_DIR = BUILD_DIR + '/mozcentral',
|
var MOZCENTRAL_DIR = BUILD_DIR + 'mozcentral/',
|
||||||
MOZCENTRAL_CONTENT_DIR = MOZCENTRAL_DIR + '/content/',
|
MOZCENTRAL_EXTENSION_DIR = MOZCENTRAL_DIR + 'browser/app/profile/extensions/uriloader@pdf.js/',
|
||||||
MOZCENTRAL_L10N_DIR = MOZCENTRAL_DIR + '/l10n/',
|
MOZCENTRAL_CONTENT_DIR = MOZCENTRAL_EXTENSION_DIR + 'content/',
|
||||||
|
MOZCENTRAL_L10N_DIR = MOZCENTRAL_DIR + 'browser/locales/en-US/pdfviewer/',
|
||||||
FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/',
|
FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/',
|
||||||
FIREFOX_EXTENSION_FILES_TO_COPY =
|
FIREFOX_EXTENSION_FILES_TO_COPY =
|
||||||
['*.js',
|
['*.js',
|
||||||
'*.svg',
|
'*.svg',
|
||||||
'*.png',
|
'*.png',
|
||||||
|
'*.manifest',
|
||||||
'install.rdf.in',
|
'install.rdf.in',
|
||||||
'README.mozilla',
|
'README.mozilla',
|
||||||
'components',
|
'components',
|
||||||
'../../LICENSE'],
|
'../../LICENSE'],
|
||||||
DEFAULT_LOCALE_FILES =
|
DEFAULT_LOCALE_FILES =
|
||||||
['l10n/en-US/viewer.properties',
|
[LOCALE_SRC_DIR + 'en-US/viewer.properties'],
|
||||||
'l10n/en-US/metadata.inc'],
|
|
||||||
FIREFOX_MC_EXTENSION_FILES =
|
FIREFOX_MC_EXTENSION_FILES =
|
||||||
['bootstrap.js',
|
['bootstrap.js',
|
||||||
'icon.png',
|
'icon.png',
|
||||||
'icon64.png',
|
'icon64.png',
|
||||||
|
'chrome.manifest',
|
||||||
'components',
|
'components',
|
||||||
'content',
|
'content',
|
||||||
'LICENSE'];
|
'LICENSE'];
|
||||||
@ -401,7 +414,7 @@ target.mozcentral = function() {
|
|||||||
|
|
||||||
// Copy extension files
|
// Copy extension files
|
||||||
cd('extensions/firefox');
|
cd('extensions/firefox');
|
||||||
cp('-R', FIREFOX_EXTENSION_FILES_TO_COPY, ROOT_DIR + MOZCENTRAL_DIR);
|
cp('-R', FIREFOX_EXTENSION_FILES_TO_COPY, ROOT_DIR + MOZCENTRAL_EXTENSION_DIR);
|
||||||
cd(ROOT_DIR);
|
cd(ROOT_DIR);
|
||||||
|
|
||||||
// Copy a standalone version of pdf.js inside the content directory
|
// Copy a standalone version of pdf.js inside the content directory
|
||||||
@ -433,11 +446,11 @@ target.mozcentral = function() {
|
|||||||
cp(DEFAULT_LOCALE_FILES, MOZCENTRAL_L10N_DIR);
|
cp(DEFAULT_LOCALE_FILES, MOZCENTRAL_L10N_DIR);
|
||||||
|
|
||||||
// Update the build version number
|
// Update the build version number
|
||||||
sed('-i', /PDFJSSCRIPT_VERSION/, EXTENSION_VERSION, MOZCENTRAL_DIR + '/install.rdf.in');
|
sed('-i', /PDFJSSCRIPT_VERSION/, EXTENSION_VERSION, MOZCENTRAL_EXTENSION_DIR + 'install.rdf.in');
|
||||||
sed('-i', /PDFJSSCRIPT_VERSION/, EXTENSION_VERSION, MOZCENTRAL_DIR + '/README.mozilla');
|
sed('-i', /PDFJSSCRIPT_VERSION/, EXTENSION_VERSION, MOZCENTRAL_EXTENSION_DIR + 'README.mozilla');
|
||||||
|
|
||||||
// List all files for mozilla-central
|
// List all files for mozilla-central
|
||||||
cd(MOZCENTRAL_DIR);
|
cd(MOZCENTRAL_EXTENSION_DIR);
|
||||||
var extensionFiles = '';
|
var extensionFiles = '';
|
||||||
find(FIREFOX_MC_EXTENSION_FILES).forEach(function(file){
|
find(FIREFOX_MC_EXTENSION_FILES).forEach(function(file){
|
||||||
if (test('-f', file))
|
if (test('-f', file))
|
||||||
|
@ -8,10 +8,12 @@
|
|||||||
* e.g. No cross domain requests without CORS.
|
* e.g. No cross domain requests without CORS.
|
||||||
*
|
*
|
||||||
* @param {string|TypedAray} source Either a url to a PDF is located or a
|
* @param {string|TypedAray} source Either a url to a PDF is located or a
|
||||||
* typed array already populated with data.
|
* typed array (Uint8Array) already populated with data.
|
||||||
|
* @param {Object} headers An object containing the http headers like this:
|
||||||
|
* { Authorization: "BASIC XXX" }.
|
||||||
* @return {Promise} A promise that is resolved with {PDFDocumentProxy} object.
|
* @return {Promise} A promise that is resolved with {PDFDocumentProxy} object.
|
||||||
*/
|
*/
|
||||||
PDFJS.getDocument = function getDocument(source) {
|
PDFJS.getDocument = function getDocument(source, headers) {
|
||||||
var promise = new PDFJS.Promise();
|
var promise = new PDFJS.Promise();
|
||||||
var transport = new WorkerTransport(promise);
|
var transport = new WorkerTransport(promise);
|
||||||
if (typeof source === 'string') {
|
if (typeof source === 'string') {
|
||||||
@ -29,7 +31,8 @@ PDFJS.getDocument = function getDocument(source) {
|
|||||||
error: function getPDFError(e) {
|
error: function getPDFError(e) {
|
||||||
promise.reject('Unexpected server response of ' +
|
promise.reject('Unexpected server response of ' +
|
||||||
e.target.status + '.');
|
e.target.status + '.');
|
||||||
}
|
},
|
||||||
|
headers: headers
|
||||||
},
|
},
|
||||||
function getPDFLoad(data) {
|
function getPDFLoad(data) {
|
||||||
transport.sendData(data);
|
transport.sendData(data);
|
||||||
|
12
src/core.js
12
src/core.js
@ -31,7 +31,19 @@ function getPdf(arg, callback) {
|
|||||||
params = { url: arg };
|
params = { url: arg };
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
xhr.open('GET', params.url);
|
xhr.open('GET', params.url);
|
||||||
|
|
||||||
|
var headers = params.headers;
|
||||||
|
if (headers) {
|
||||||
|
for (var property in headers) {
|
||||||
|
if (typeof headers[property] === 'undefined')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
xhr.setRequestHeader(property, params.headers[property]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
|
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
|
||||||
var protocol = params.url.indexOf(':') < 0 ? window.location.protocol :
|
var protocol = params.url.indexOf(':') < 0 ? window.location.protocol :
|
||||||
params.url.substring(0, params.url.indexOf(':') + 1);
|
params.url.substring(0, params.url.indexOf(':') + 1);
|
||||||
|
@ -419,13 +419,14 @@ var CipherTransform = (function CipherTransformClosure() {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
var CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
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 prepareKeyData(fileId, password, ownerPassword, userPassword,
|
function prepareKeyData(fileId, password, ownerPassword, userPassword,
|
||||||
flags, revision, keyLength, encryptMetadata) {
|
flags, revision, keyLength, encryptMetadata) {
|
||||||
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]);
|
|
||||||
var hashData = new Uint8Array(100), i = 0, j, n;
|
var hashData = new Uint8Array(100), i = 0, j, n;
|
||||||
if (password) {
|
if (password) {
|
||||||
n = Math.min(32, password.length);
|
n = Math.min(32, password.length);
|
||||||
@ -462,9 +463,8 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
var cipher, checkData;
|
var cipher, checkData;
|
||||||
|
|
||||||
if (revision >= 3) {
|
if (revision >= 3) {
|
||||||
// padded password in hashData, we can use this array for user
|
for (i = 0; i < 32; ++i)
|
||||||
// password check
|
hashData[i] = defaultPasswordBytes[i];
|
||||||
i = 32;
|
|
||||||
for (j = 0, n = fileId.length; j < n; ++j)
|
for (j = 0, n = fileId.length; j < n; ++j)
|
||||||
hashData[i++] = fileId[j];
|
hashData[i++] = fileId[j];
|
||||||
cipher = new ARCFourCipher(encryptionKey);
|
cipher = new ARCFourCipher(encryptionKey);
|
||||||
@ -477,16 +477,53 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
cipher = new ARCFourCipher(derivedKey);
|
cipher = new ARCFourCipher(derivedKey);
|
||||||
checkData = cipher.encryptBlock(checkData);
|
checkData = cipher.encryptBlock(checkData);
|
||||||
}
|
}
|
||||||
|
for (j = 0, n = checkData.length; j < n; ++j) {
|
||||||
|
if (userPassword[j] != checkData[j])
|
||||||
|
return null;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cipher = new ARCFourCipher(encryptionKey);
|
cipher = new ARCFourCipher(encryptionKey);
|
||||||
checkData = cipher.encryptBlock(hashData.subarray(0, 32));
|
checkData = cipher.encryptBlock(defaultPasswordBytes);
|
||||||
}
|
for (j = 0, n = checkData.length; j < n; ++j) {
|
||||||
for (j = 0, n = checkData.length; j < n; ++j) {
|
if (userPassword[j] != checkData[j])
|
||||||
if (userPassword[j] != checkData[j])
|
return null;
|
||||||
error('incorrect password');
|
}
|
||||||
}
|
}
|
||||||
return encryptionKey;
|
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 = new Name('Identity');
|
var identityName = new Name('Identity');
|
||||||
|
|
||||||
@ -516,10 +553,23 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
|
|||||||
if (password)
|
if (password)
|
||||||
passwordBytes = stringToBytes(password);
|
passwordBytes = stringToBytes(password);
|
||||||
|
|
||||||
this.encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
|
var encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
|
||||||
ownerPassword, userPassword,
|
ownerPassword, userPassword, flags,
|
||||||
flags, revision,
|
revision, keyLength, encryptMetadata);
|
||||||
keyLength, encryptMetadata);
|
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)
|
||||||
|
error('incorrect password or encryption data');
|
||||||
|
|
||||||
|
this.encryptionKey = encryptionKey;
|
||||||
|
|
||||||
if (algorithm == 4) {
|
if (algorithm == 4) {
|
||||||
this.cf = dict.get('CF');
|
this.cf = dict.get('CF');
|
||||||
this.stmf = dict.get('StmF') || identityName;
|
this.stmf = dict.get('StmF') || identityName;
|
||||||
|
@ -112,14 +112,33 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function splitCombinedOperations(operations) {
|
function splitCombinedOperations(operations) {
|
||||||
// Two operations can be combined together, trying to find which two
|
// Two or more operations can be combined together, trying to find which
|
||||||
// operations were concatenated.
|
// operations were concatenated.
|
||||||
for (var i = operations.length - 1; i > 0; i--) {
|
var result = [];
|
||||||
var op1 = operations.substring(0, i), op2 = operations.substring(i);
|
var opIndex = 0;
|
||||||
if (op1 in OP_MAP && op2 in OP_MAP)
|
|
||||||
return [op1, op2]; // operations found
|
if (!operations) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
while (opIndex < operations.length) {
|
||||||
|
var currentOp = '';
|
||||||
|
for (var op in OP_MAP) {
|
||||||
|
if (op == operations.substr(opIndex, op.length) &&
|
||||||
|
op.length > currentOp.length) {
|
||||||
|
currentOp = op;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentOp.length > 0) {
|
||||||
|
result.push(operations.substr(opIndex, currentOp.length));
|
||||||
|
opIndex += currentOp.length;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PartialEvaluator.prototype = {
|
PartialEvaluator.prototype = {
|
||||||
@ -268,14 +287,14 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
var patterns = resources.get('Pattern') || new Dict();
|
var patterns = resources.get('Pattern') || new Dict();
|
||||||
var parser = new Parser(new Lexer(stream), false, xref);
|
var parser = new Parser(new Lexer(stream), false, xref);
|
||||||
var res = resources;
|
var res = resources;
|
||||||
var hasNextObj = false, nextObj;
|
var hasNextObj = false, nextObjs;
|
||||||
var args = [], obj;
|
var args = [], obj;
|
||||||
var TILING_PATTERN = 1, SHADING_PATTERN = 2;
|
var TILING_PATTERN = 1, SHADING_PATTERN = 2;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (hasNextObj) {
|
if (hasNextObj) {
|
||||||
obj = nextObj;
|
obj = nextObjs.pop();
|
||||||
hasNextObj = false;
|
hasNextObj = (nextObjs.length > 0);
|
||||||
} else {
|
} else {
|
||||||
obj = parser.getObj();
|
obj = parser.getObj();
|
||||||
if (isEOF(obj))
|
if (isEOF(obj))
|
||||||
@ -291,9 +310,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
if (cmds) {
|
if (cmds) {
|
||||||
cmd = cmds[0];
|
cmd = cmds[0];
|
||||||
fn = OP_MAP[cmd];
|
fn = OP_MAP[cmd];
|
||||||
// feeding other command on the next interation
|
// feeding other command on the next iteration
|
||||||
hasNextObj = true;
|
hasNextObj = true;
|
||||||
nextObj = Cmd.get(cmds[1]);
|
nextObjs = [];
|
||||||
|
for (var idx = 1; idx < cmds.length; idx++) {
|
||||||
|
nextObjs.push(Cmd.get(cmds[idx]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertWellFormed(fn, 'Unknown command "' + cmd + '"');
|
assertWellFormed(fn, 'Unknown command "' + cmd + '"');
|
||||||
|
@ -185,3 +185,66 @@ describe('crypto', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('CipherTransformFactory', function() {
|
||||||
|
function DictMock(map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
DictMock.prototype = {
|
||||||
|
get: function(key) {
|
||||||
|
return this.map[key];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var map1 = {
|
||||||
|
Filter: new Name('Standard'),
|
||||||
|
V: 2,
|
||||||
|
Length: 128,
|
||||||
|
O: unescape('%80%C3%04%96%91o%20sl%3A%E6%1B%13T%91%F2%0DV%12%E3%FF%5E%BB%' +
|
||||||
|
'E9VO%D8k%9A%CA%7C%5D'),
|
||||||
|
U: unescape('j%0C%8D%3EY%19%00%BCjd%7D%91%BD%AA%00%18%00%00%00%00%00%00%0' +
|
||||||
|
'0%00%00%00%00%00%00%00%00%00'),
|
||||||
|
P: -1028,
|
||||||
|
R: 3
|
||||||
|
};
|
||||||
|
var fileID1 = unescape('%F6%C6%AF%17%F3rR%8DRM%9A%80%D1%EF%DF%18');
|
||||||
|
|
||||||
|
var map2 = {
|
||||||
|
Filter: new Name('Standard'),
|
||||||
|
V: 4,
|
||||||
|
Length: 128,
|
||||||
|
O: unescape('sF%14v.y5%27%DB%97%0A5%22%B3%E1%D4%AD%BD%9B%3C%B4%A5%89u%15%' +
|
||||||
|
'B2Y%F1h%D9%E9%F4'),
|
||||||
|
U: unescape('%93%04%89%A9%BF%8AE%A6%88%A2%DB%C2%A0%A8gn%00%00%00%00%00%00' +
|
||||||
|
'%00%00%00%00%00%00%00%00%00%00'),
|
||||||
|
P: -1084,
|
||||||
|
R: 4
|
||||||
|
};
|
||||||
|
var fileID2 = unescape('%3CL_%3AD%96%AF@%9A%9D%B3%3Cx%1Cv%AC');
|
||||||
|
|
||||||
|
describe('#ctor', function() {
|
||||||
|
it('should accept user password', function() {
|
||||||
|
var factory = new CipherTransformFactory(new DictMock(map1), fileID1,
|
||||||
|
'123456');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept owner password', function() {
|
||||||
|
var factory = new CipherTransformFactory(new DictMock(map1), fileID1,
|
||||||
|
'654321');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not accept wrong password', function() {
|
||||||
|
var thrown = false;
|
||||||
|
try {
|
||||||
|
var factory = new CipherTransformFactory(new DictMock(map1), fileID1,
|
||||||
|
'wrong');
|
||||||
|
} catch (e) {
|
||||||
|
thrown = true;
|
||||||
|
}
|
||||||
|
expect(thrown).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept no password', function() {
|
||||||
|
var factory = new CipherTransformFactory(new DictMock(map2), fileID2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
83
test/unit/evaluator_spec.js
Normal file
83
test/unit/evaluator_spec.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('evaluator', function() {
|
||||||
|
function XrefMock(queue) {
|
||||||
|
this.queue = queue;
|
||||||
|
}
|
||||||
|
XrefMock.prototype = {
|
||||||
|
fetchIfRef: function() {
|
||||||
|
return this.queue.shift();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function HandlerMock() {
|
||||||
|
this.inputs = [];
|
||||||
|
}
|
||||||
|
HandlerMock.prototype = {
|
||||||
|
send: function(name, data) {
|
||||||
|
this.inputs({name: name, data: data});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function ResourcesMock() { }
|
||||||
|
ResourcesMock.prototype = {
|
||||||
|
get: function(name) {
|
||||||
|
return this[name];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('splitCombinedOperations', function() {
|
||||||
|
it('should reject unknown operations', function() {
|
||||||
|
var evaluator = new PartialEvaluator(new XrefMock(), new HandlerMock(),
|
||||||
|
'prefix');
|
||||||
|
var stream = new StringStream('qTT');
|
||||||
|
var thrown = false;
|
||||||
|
try {
|
||||||
|
evaluator.getOperatorList(stream, new ResourcesMock(), []);
|
||||||
|
} catch (e) {
|
||||||
|
thrown = e;
|
||||||
|
}
|
||||||
|
expect(thrown).toNotEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle one operations', function() {
|
||||||
|
var evaluator = new PartialEvaluator(new XrefMock(), new HandlerMock(),
|
||||||
|
'prefix');
|
||||||
|
var stream = new StringStream('Q');
|
||||||
|
var result = evaluator.getOperatorList(stream, new ResourcesMock(), []);
|
||||||
|
|
||||||
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
||||||
|
expect(result.fnArray.length).toEqual(1);
|
||||||
|
expect(result.fnArray[0]).toEqual('restore');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle two glued operations', function() {
|
||||||
|
var evaluator = new PartialEvaluator(new XrefMock(), new HandlerMock(),
|
||||||
|
'prefix');
|
||||||
|
var resources = new ResourcesMock();
|
||||||
|
resources.Res1 = {};
|
||||||
|
var stream = new StringStream('/Res1 DoQ');
|
||||||
|
var result = evaluator.getOperatorList(stream, resources, []);
|
||||||
|
|
||||||
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
||||||
|
expect(result.fnArray.length).toEqual(2);
|
||||||
|
expect(result.fnArray[0]).toEqual('paintXObject');
|
||||||
|
expect(result.fnArray[1]).toEqual('restore');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle tree glued operations', function() {
|
||||||
|
var evaluator = new PartialEvaluator(new XrefMock(), new HandlerMock(),
|
||||||
|
'prefix');
|
||||||
|
var stream = new StringStream('qqq');
|
||||||
|
var result = evaluator.getOperatorList(stream, new ResourcesMock(), []);
|
||||||
|
|
||||||
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
||||||
|
expect(result.fnArray.length).toEqual(3);
|
||||||
|
expect(result.fnArray[0]).toEqual('save');
|
||||||
|
expect(result.fnArray[1]).toEqual('save');
|
||||||
|
expect(result.fnArray[2]).toEqual('save');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -39,6 +39,7 @@
|
|||||||
<script type="text/javascript" src="font_spec.js"></script>
|
<script type="text/javascript" src="font_spec.js"></script>
|
||||||
<script type="text/javascript" src="function_spec.js"></script>
|
<script type="text/javascript" src="function_spec.js"></script>
|
||||||
<script type="text/javascript" src="crypto_spec.js"></script>
|
<script type="text/javascript" src="crypto_spec.js"></script>
|
||||||
|
<script type="text/javascript" src="evaluator_spec.js"></script>
|
||||||
<script type="text/javascript" src="stream_spec.js"></script>
|
<script type="text/javascript" src="stream_spec.js"></script>
|
||||||
<script type="text/javascript" src="api_spec.js"></script>
|
<script type="text/javascript" src="api_spec.js"></script>
|
||||||
<script type="text/javascript" src="metadata_spec.js"></script>
|
<script type="text/javascript" src="metadata_spec.js"></script>
|
||||||
|
@ -1179,7 +1179,8 @@ var PageView = function pageView(container, pdfPage, id, scale,
|
|||||||
var ThumbnailView = function thumbnailView(container, pdfPage, id) {
|
var ThumbnailView = function thumbnailView(container, pdfPage, id) {
|
||||||
var anchor = document.createElement('a');
|
var anchor = document.createElement('a');
|
||||||
anchor.href = PDFView.getAnchorUrl('#page=' + id);
|
anchor.href = PDFView.getAnchorUrl('#page=' + id);
|
||||||
anchor.onclick = function stopNivigation() {
|
anchor.title = mozL10n.get('thumb_page_title', {page: id}, 'Page {{page}}');
|
||||||
|
anchor.onclick = function stopNavigation() {
|
||||||
PDFView.page = id;
|
PDFView.page = id;
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@ -1212,6 +1213,8 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
|
|||||||
canvas.width = canvasWidth;
|
canvas.width = canvasWidth;
|
||||||
canvas.height = canvasHeight;
|
canvas.height = canvasHeight;
|
||||||
canvas.className = 'thumbnailImage';
|
canvas.className = 'thumbnailImage';
|
||||||
|
canvas.setAttribute('aria-label', mozL10n.get('thumb_page_canvas',
|
||||||
|
{page: id}, 'Thumbnail of Page {{page}}'));
|
||||||
|
|
||||||
div.setAttribute('data-loaded', true);
|
div.setAttribute('data-loaded', true);
|
||||||
|
|
||||||
@ -1468,11 +1471,12 @@ window.addEventListener('load', function webViewerLoad(evt) {
|
|||||||
if ('disableWorker' in hashParams)
|
if ('disableWorker' in hashParams)
|
||||||
PDFJS.disableWorker = (hashParams['disableWorker'] === 'true');
|
PDFJS.disableWorker = (hashParams['disableWorker'] === 'true');
|
||||||
|
|
||||||
var locale = !PDFJS.isFirefoxExtension ? navigator.language :
|
if (!PDFJS.isFirefoxExtension) {
|
||||||
FirefoxCom.request('getLocale', null);
|
var locale = navigator.language;
|
||||||
if ('locale' in hashParams)
|
if ('locale' in hashParams)
|
||||||
locale = hashParams['locale'];
|
locale = hashParams['locale'];
|
||||||
mozL10n.language.code = locale;
|
mozL10n.language.code = locale;
|
||||||
|
}
|
||||||
|
|
||||||
if ('disableTextLayer' in hashParams)
|
if ('disableTextLayer' in hashParams)
|
||||||
PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true');
|
PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user